From 189220e2f6d5aed809dc0a816f98018732ff0825 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Tue, 25 Jun 2024 09:14:07 -0600 Subject: [PATCH 01/61] fix: solana e2e test compilation (#13689) --- 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 b1982dcee0..4ba7eb9e65 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -277,7 +277,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 1cae6c5ee9..07fafe50ef 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1220,8 +1220,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 h1:h0gjVZ7oQwPPQOFJuZToDhB1NTEbIBrRtsJysATTG/g= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= diff --git a/go.mod b/go.mod index 690106070b..09916e704e 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/go.sum b/go.sum index 8c52ee53a1..d6a715faa5 100644 --- a/go.sum +++ b/go.sum @@ -1179,8 +1179,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 h1:h0gjVZ7oQwPPQOFJuZToDhB1NTEbIBrRtsJysATTG/g= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 2a36a950e6..bf82d1f8dd 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -381,7 +381,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 0878c9c35c..c20a0568d2 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1521,8 +1521,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 h1:h0gjVZ7oQwPPQOFJuZToDhB1NTEbIBrRtsJysATTG/g= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-testing-framework v1.31.4 h1:5/zF5Z2w+/HTvUSSJNhWSiHvlQ2O2qxRw4e1fBbVraQ= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 6c7f33d81c..2f983f57e4 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -367,7 +367,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 084207876d..cb05f66879 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1511,8 +1511,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5 h1:h0gjVZ7oQwPPQOFJuZToDhB1NTEbIBrRtsJysATTG/g= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625075314-affd4529a8f5/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-testing-framework v1.31.4 h1:5/zF5Z2w+/HTvUSSJNhWSiHvlQ2O2qxRw4e1fBbVraQ= From 1d640a21a3dd706dab14c86ca16f37bce1328845 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Tue, 25 Jun 2024 17:32:00 +0200 Subject: [PATCH 02/61] fix namespace creation in ocrv2 soak tests (#13690) --- integration-tests/testsetups/ocr.go | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index fe4d15fc96..749ca3beac 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -21,7 +21,6 @@ import ( geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/google/uuid" "github.com/pelletier/go-toml/v2" "github.com/rs/zerolog" "github.com/smartcontractkit/seth" @@ -152,22 +151,17 @@ func NewOCRSoakTest(t *testing.T, config *tc.TestConfig, opts ...OCRSoakTestOpti func (o *OCRSoakTest) DeployEnvironment(ocrTestConfig tt.OcrTestConfig) { nodeNetwork := networks.MustGetSelectedNetworkConfig(ocrTestConfig.GetNetworkConfig())[0] // Environment currently being used to soak test on - // Define namespace if default not set - if o.namespace == "" { - nsPre := fmt.Sprintf("soak-ocr-v%s-", o.OCRVersion) - if o.OperatorForwarderFlow { - nsPre = fmt.Sprintf("%sforwarder-", nsPre) - } - - nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(nodeNetwork.Name), " ", "-")) - nsPre = strings.ReplaceAll(nsPre, "_", "-") - - o.namespace = fmt.Sprintf("%s-%s", nsPre, uuid.NewString()[0:5]) + nsPre := fmt.Sprintf("soak-ocr-v%s-", o.OCRVersion) + if o.OperatorForwarderFlow { + nsPre = fmt.Sprintf("%sforwarder-", nsPre) } + nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(nodeNetwork.Name), " ", "-")) + nsPre = strings.ReplaceAll(nsPre, "_", "-") + baseEnvironmentConfig := &environment.Config{ TTL: time.Hour * 720, // 30 days, - Namespace: o.namespace, + NamespacePrefix: nsPre, Test: o.t, PreventPodEviction: true, } From 8ccaa140aebdafbb760569a1d2b7cabe8ac1bf61 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 25 Jun 2024 12:39:14 -0400 Subject: [PATCH 03/61] Support "dummy" relayer type (#13583) * Implement new relayer type "dummy" This allows testing of plugins without needing a real connection to any chain. * Add changeset * Spelling fix * Remove useless file * Update core/services/relay/dummy/llo_provider.go Co-authored-by: Jordan Krage * Fix typo * Move onchainconfig into llo package --------- Co-authored-by: Jordan Krage --- .changeset/tender-carpets-cry.md | 7 + core/chains/evm/logpoller/log_poller.go | 5 + core/cmd/shell.go | 2 +- core/internal/cltest/cltest.go | 2 +- core/internal/testutils/testutils.go | 4 +- .../chainlink/relayer_chain_interoperators.go | 24 +++ .../relayer_chain_interoperators_test.go | 6 + core/services/chainlink/relayer_factory.go | 9 + core/services/llo/bm/dummy_transmitter.go | 6 +- .../services/llo/bm/dummy_transmitter_test.go | 3 +- core/services/llo/data_source.go | 4 + core/services/llo/onchain_config.go | 21 ++ core/services/ocr2/delegate.go | 15 +- .../ocr2/plugins/llo/config/config.go | 6 +- .../services/ocr2/plugins/llo/helpers_test.go | 78 ++++--- .../ocr2/plugins/llo/integration_test.go | 203 +++++++++++++++--- core/services/relay/dummy/config_digester.go | 26 +++ core/services/relay/dummy/config_provider.go | 97 +++++++++ core/services/relay/dummy/config_tracker.go | 51 +++++ core/services/relay/dummy/llo_provider.go | 86 ++++++++ core/services/relay/dummy/relayer.go | 78 +++++++ core/services/relay/evm/evm.go | 2 +- core/services/relay/evm/llo_provider.go | 7 +- core/services/relay/relay.go | 4 + 24 files changed, 661 insertions(+), 85 deletions(-) create mode 100644 .changeset/tender-carpets-cry.md create mode 100644 core/services/llo/onchain_config.go create mode 100644 core/services/relay/dummy/config_digester.go create mode 100644 core/services/relay/dummy/config_provider.go create mode 100644 core/services/relay/dummy/config_tracker.go create mode 100644 core/services/relay/dummy/llo_provider.go create mode 100644 core/services/relay/dummy/relayer.go diff --git a/.changeset/tender-carpets-cry.md b/.changeset/tender-carpets-cry.md new file mode 100644 index 0000000000..075f769ce0 --- /dev/null +++ b/.changeset/tender-carpets-cry.md @@ -0,0 +1,7 @@ +--- +"chainlink": patch +--- + +Add new relayer type "dummy" for testing. + +#added diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 1c8996a46e..bc0dd40e28 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -1021,6 +1021,11 @@ func (lp *logPoller) latestBlocks(ctx context.Context) (*evmtypes.Head, int64, e if err != nil { return nil, 0, err } + if latestBlock == nil { + // Shouldn't happen with a real client, but still better rather to + // return error than panic + return nil, 0, errors.New("latest block is nil") + } // If chain has fewer blocks than finalityDepth, return 0 return latestBlock, mathutil.Max(latestBlock.Number-lp.finalityDepth, 0), nil } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index e12b069277..c79fb70310 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -184,7 +184,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } // evm always enabled for backward compatibility // TODO BCF-2510 this needs to change in order to clear the path for EVM extraction - initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(ctx, relayerFactory, evmFactoryCfg)} + initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitDummy(ctx, relayerFactory), chainlink.InitEVM(ctx, relayerFactory, evmFactoryCfg)} if cfg.CosmosEnabled() { cosmosCfg := chainlink.CosmosFactoryConfig{ diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 5212b29fce..e86394d82f 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -387,7 +387,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn testCtx := testutils.Context(t) // evm alway enabled for backward compatibility - initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(testCtx, relayerFactory, evmOpts)} + initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitDummy(testCtx, relayerFactory), chainlink.InitEVM(testCtx, relayerFactory, evmOpts)} if cfg.CosmosEnabled() { cosmosCfg := chainlink.CosmosFactoryConfig{ diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index 6b4388fccf..45609488b4 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -367,15 +367,17 @@ func RequireLogMessage(t *testing.T, observedLogs *observer.ObservedLogs, msg st // // observedZapCore, observedLogs := observer.New(zap.DebugLevel) // lggr := logger.TestLogger(t, observedZapCore) -func WaitForLogMessage(t *testing.T, observedLogs *observer.ObservedLogs, msg string) { +func WaitForLogMessage(t *testing.T, observedLogs *observer.ObservedLogs, msg string) (le observer.LoggedEntry) { AssertEventually(t, func() bool { for _, l := range observedLogs.All() { if strings.Contains(l.Message, msg) { + le = l return true } } return false }) + return } // WaitForLogMessageCount waits until at least count log message containing the diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index 32bcc9f18a..60381c0d47 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -69,6 +69,10 @@ type ChainsNodesStatuser interface { var _ RelayerChainInteroperators = &CoreRelayerChainInteroperators{} +type DummyFactory interface { + NewDummy(config DummyFactoryConfig) (loop.Relayer, error) +} + // CoreRelayerChainInteroperators implements [RelayerChainInteroperators] // as needed for the core [chainlink.Application] type CoreRelayerChainInteroperators struct { @@ -76,6 +80,8 @@ type CoreRelayerChainInteroperators struct { loopRelayers map[types.RelayID]loop.Relayer legacyChains legacyChains + dummyFactory DummyFactory + // we keep an explicit list of services because the legacy implementations have more than // just the relayer service srvs []services.ServiceCtx @@ -98,6 +104,14 @@ func NewCoreRelayerChainInteroperators(initFuncs ...CoreRelayerChainInitFunc) (* // CoreRelayerChainInitFunc is a hook in the constructor to create relayers from a factory. type CoreRelayerChainInitFunc func(op *CoreRelayerChainInteroperators) error +// InitDummy instantiates a dummy relayer +func InitDummy(ctx context.Context, factory RelayerFactory) CoreRelayerChainInitFunc { + return func(op *CoreRelayerChainInteroperators) error { + op.dummyFactory = &factory + return nil + } +} + // InitEVM is a option for instantiating evm relayers func InitEVM(ctx context.Context, factory RelayerFactory, config EVMFactoryConfig) CoreRelayerChainInitFunc { return func(op *CoreRelayerChainInteroperators) (err error) { @@ -178,6 +192,16 @@ func (rs *CoreRelayerChainInteroperators) Get(id types.RelayID) (loop.Relayer, e defer rs.mu.Unlock() lr, exist := rs.loopRelayers[id] if !exist { + // lazily create dummy relayers + if id.Network == "dummy" { + var err error + lr, err = rs.dummyFactory.NewDummy(DummyFactoryConfig{id.ChainID}) + if err != nil { + return nil, err + } + rs.loopRelayers[id] = lr + return lr, nil + } return nil, fmt.Errorf("%w: %s", ErrNoSuchRelayer, id) } return lr, nil diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index c4fbd26861..aaf458c76c 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -198,6 +198,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedStarknetNodeCnt int expectedStarknetRelayerIds []types.RelayID + expectedDummyChainCnt int + expectedDummyNodeCnt int + expectedDummyRelayerIds []types.RelayID + expectedCosmosChainCnt int expectedCosmosNodeCnt int expectedCosmosRelayerIds []types.RelayID @@ -368,6 +372,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedChainCnt, expectedNodeCnt = tt.expectedSolanaChainCnt, tt.expectedSolanaNodeCnt case relay.NetworkStarkNet: expectedChainCnt, expectedNodeCnt = tt.expectedStarknetChainCnt, tt.expectedStarknetNodeCnt + case relay.NetworkDummy: + expectedChainCnt, expectedNodeCnt = tt.expectedDummyChainCnt, tt.expectedDummyNodeCnt case relay.NetworkAptos: t.Skip("aptos doesn't need a CoreRelayerChainInteroperator") diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 9c17a5b221..ae222f56c6 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -26,6 +26,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" corerelay "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/dummy" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/plugins" @@ -39,6 +40,14 @@ type RelayerFactory struct { CapabilitiesRegistry *capabilities.Registry } +type DummyFactoryConfig struct { + ChainID string +} + +func (r *RelayerFactory) NewDummy(config DummyFactoryConfig) (loop.Relayer, error) { + return dummy.NewRelayer(r.Logger, config.ChainID), nil +} + type EVMFactoryConfig struct { legacyevm.ChainOpts evmrelay.CSAETHKeystore diff --git a/core/services/llo/bm/dummy_transmitter.go b/core/services/llo/bm/dummy_transmitter.go index b998c19cb2..5573350b4e 100644 --- a/core/services/llo/bm/dummy_transmitter.go +++ b/core/services/llo/bm/dummy_transmitter.go @@ -2,8 +2,6 @@ package bm import ( "context" - "crypto/ed25519" - "fmt" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -37,10 +35,10 @@ type transmitter struct { fromAccount string } -func NewTransmitter(lggr logger.Logger, fromAccount ed25519.PublicKey) Transmitter { +func NewTransmitter(lggr logger.Logger, fromAccount string) Transmitter { return &transmitter{ lggr.Named("DummyTransmitter"), - fmt.Sprintf("%x", fromAccount), + fromAccount, } } diff --git a/core/services/llo/bm/dummy_transmitter_test.go b/core/services/llo/bm/dummy_transmitter_test.go index 055b150ad1..e6c59e2f9e 100644 --- a/core/services/llo/bm/dummy_transmitter_test.go +++ b/core/services/llo/bm/dummy_transmitter_test.go @@ -1,7 +1,6 @@ package bm import ( - "crypto/ed25519" "testing" "github.com/stretchr/testify/require" @@ -19,7 +18,7 @@ import ( func Test_DummyTransmitter(t *testing.T) { lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel) - tr := NewTransmitter(lggr, ed25519.PublicKey("dummy")) + tr := NewTransmitter(lggr, "dummy") servicetest.Run(t, tr) diff --git a/core/services/llo/data_source.go b/core/services/llo/data_source.go index a9c3744f9e..30f646e1cb 100644 --- a/core/services/llo/data_source.go +++ b/core/services/llo/data_source.go @@ -61,6 +61,8 @@ func (d *dataSource) Observe(ctx context.Context, streamIDs map[llotypes.StreamI sv := make(llo.StreamValues) var mu sync.Mutex + d.lggr.Debugw("Observing streams", "streamIDs", streamIDs) + for streamID := range streamIDs { go func(streamID llotypes.StreamID) { defer wg.Done() @@ -99,5 +101,7 @@ func (d *dataSource) Observe(ctx context.Context, streamIDs map[llotypes.StreamI wg.Wait() + d.lggr.Debugw("Observed streams", "streamIDs", streamIDs, "values", sv) + return sv, nil } diff --git a/core/services/llo/onchain_config.go b/core/services/llo/onchain_config.go new file mode 100644 index 0000000000..7b5cfffaa9 --- /dev/null +++ b/core/services/llo/onchain_config.go @@ -0,0 +1,21 @@ +package llo + +type OnchainConfig struct{} + +type OnchainConfigCodec interface { + Encode(OnchainConfig) ([]byte, error) + Decode([]byte) (OnchainConfig, error) +} + +var _ OnchainConfigCodec = &JSONOnchainConfigCodec{} + +// TODO: Replace this with protobuf, if it is actually used for something +type JSONOnchainConfigCodec struct{} + +func (c *JSONOnchainConfigCodec) Encode(OnchainConfig) ([]byte, error) { + return nil, nil +} + +func (c *JSONOnchainConfigCodec) Decode([]byte) (OnchainConfig, error) { + return OnchainConfig{}, nil +} diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index a1a1c41774..875ee0f69e 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -802,7 +802,7 @@ func (d *Delegate) newServicesMercury( return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "mercury"} } if rid.Network != relay.NetworkEVM { - return nil, fmt.Errorf("mercury services: expected EVM relayer got %s", rid.Network) + return nil, fmt.Errorf("mercury services: expected EVM relayer got %q", rid.Network) } relayer, err := d.RelayGetter.Get(rid) if err != nil { @@ -895,9 +895,6 @@ func (d *Delegate) newServicesLLO( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "streams"} } - if rid.Network != relay.NetworkEVM { - return nil, fmt.Errorf("streams services: expected EVM relayer got %s", rid.Network) - } relayer, err := d.RelayGetter.Get(rid) if err != nil { return nil, ErrRelayNotEnabled{Err: err, Relay: spec.Relay, PluginName: "streams"} @@ -1079,7 +1076,7 @@ func (d *Delegate) newServicesDKG( return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "DKG"} } if rid.Network != relay.NetworkEVM { - return nil, fmt.Errorf("DKG services: expected EVM relayer got %s", rid.Network) + return nil, fmt.Errorf("DKG services: expected EVM relayer got %q", rid.Network) } chain, err2 := d.legacyChains.Get(rid.ChainID) @@ -1144,7 +1141,7 @@ func (d *Delegate) newServicesOCR2VRF( return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "VRF"} } if rid.Network != relay.NetworkEVM { - return nil, fmt.Errorf("VRF services: expected EVM relayer got %s", rid.Network) + return nil, fmt.Errorf("VRF services: expected EVM relayer got %q", rid.Network) } chain, err2 := d.legacyChains.Get(rid.ChainID) if err2 != nil { @@ -1358,7 +1355,7 @@ func (d *Delegate) newServicesOCR2Keepers21( return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "keeper2"} } if rid.Network != relay.NetworkEVM { - return nil, fmt.Errorf("keeper2 services: expected EVM relayer got %s", rid.Network) + return nil, fmt.Errorf("keeper2 services: expected EVM relayer got %q", rid.Network) } transmitterID := spec.TransmitterID.String @@ -1511,7 +1508,7 @@ func (d *Delegate) newServicesOCR2Keepers20( return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "keepers2.0"} } if rid.Network != relay.NetworkEVM { - return nil, fmt.Errorf("keepers2.0 services: expected EVM relayer got %s", rid.Network) + return nil, fmt.Errorf("keepers2.0 services: expected EVM relayer got %q", rid.Network) } chain, err2 := d.legacyChains.Get(rid.ChainID) if err2 != nil { @@ -1639,7 +1636,7 @@ func (d *Delegate) newServicesOCR2Functions( return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "functions"} } if rid.Network != relay.NetworkEVM { - return nil, fmt.Errorf("functions services: expected EVM relayer got %s", rid.Network) + return nil, fmt.Errorf("functions services: expected EVM relayer got %q", rid.Network) } chain, err := d.legacyChains.Get(rid.ChainID) if err != nil { diff --git a/core/services/ocr2/plugins/llo/config/config.go b/core/services/ocr2/plugins/llo/config/config.go index 1a6e528980..892229c46c 100644 --- a/core/services/ocr2/plugins/llo/config/config.go +++ b/core/services/ocr2/plugins/llo/config/config.go @@ -26,7 +26,7 @@ type PluginConfig struct { ChannelDefinitionsContractFromBlock int64 `json:"channelDefinitionsContractFromBlock" toml:"channelDefinitionsContractFromBlock"` // NOTE: ChannelDefinitions is an override. - // If Channe}lDefinitions is specified, values for + // If ChannelDefinitions is specified, values for // ChannelDefinitionsContractAddress and // ChannelDefinitionsContractFromBlock will be ignored ChannelDefinitions string `json:"channelDefinitions" toml:"channelDefinitions"` @@ -41,6 +41,10 @@ type PluginConfig struct { KeyBundleIDs map[string]string `json:"keyBundleIDs" toml:"keyBundleIDs"` } +func (p *PluginConfig) Unmarshal(data []byte) error { + return json.Unmarshal(data, p) +} + func (p PluginConfig) Validate() (merr error) { if p.RawServerURL == "" { merr = errors.New("llo: ServerURL must be specified") diff --git a/core/services/ocr2/plugins/llo/helpers_test.go b/core/services/ocr2/plugins/llo/helpers_test.go index 73f7fedc92..a29953d5d5 100644 --- a/core/services/ocr2/plugins/llo/helpers_test.go +++ b/core/services/ocr2/plugins/llo/helpers_test.go @@ -130,6 +130,7 @@ type Node struct { App chainlink.Application ClientPubKey credentials.StaticSizedPublicKey KeyBundle ocr2key.KeyBundle + ObservedLogs *observer.ObservedLogs } func (node *Node) AddStreamJob(t *testing.T, spec string) { @@ -197,7 +198,11 @@ func setupNode( }) lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel) - app = cltest.NewApplicationWithConfigV2OnSimulatedBlockchain(t, config, backend, p2pKey, ocr2kb, csaKey, lggr.Named(dbName)) + if backend != nil { + app = cltest.NewApplicationWithConfigV2OnSimulatedBlockchain(t, config, backend, p2pKey, ocr2kb, csaKey, lggr.Named(dbName)) + } else { + app = cltest.NewApplicationWithConfig(t, config, p2pKey, ocr2kb, csaKey, lggr.Named(dbName)) + } err := app.Start(testutils.Context(t)) require.NoError(t, err) @@ -236,74 +241,79 @@ observationSource = """ bridgeName, )) } -func addBootstrapJob(t *testing.T, bootstrapNode Node, chainID *big.Int, verifierAddress common.Address, name string) { + +func addBootstrapJob(t *testing.T, bootstrapNode Node, verifierAddress common.Address, name string, relayType, relayConfig string) { bootstrapNode.AddBootstrapJob(t, fmt.Sprintf(` type = "bootstrap" -relay = "evm" +relay = "%s" schemaVersion = 1 name = "boot-%s" contractID = "%s" contractConfigTrackerPollInterval = "1s" [relayConfig] -chainID = %s -providerType = "llo" - `, name, verifierAddress.Hex(), chainID.String())) +%s +providerType = "llo"`, relayType, name, verifierAddress.Hex(), relayConfig)) } func addLLOJob( t *testing.T, node Node, - verifierAddress, - configStoreAddress common.Address, + verifierAddress common.Address, bootstrapPeerID string, bootstrapNodePort int, - serverURL string, - serverPubKey, clientPubKey ed25519.PublicKey, jobName string, - chainID *big.Int, - fromBlock int, + pluginConfig, + relayType, + relayConfig string, ) { node.AddLLOJob(t, fmt.Sprintf(` type = "offchainreporting2" schemaVersion = 1 -name = "%[1]s" +name = "%s" forwardingAllowed = false maxTaskDuration = "1s" -contractID = "%[2]s" +contractID = "%s" contractConfigTrackerPollInterval = "1s" -ocrKeyBundleID = "%[3]s" +ocrKeyBundleID = "%s" p2pv2Bootstrappers = [ - "%[4]s" + "%s" ] -relay = "evm" +relay = "%s" pluginType = "llo" -transmitterID = "%[5]x" +transmitterID = "%x" [pluginConfig] -serverURL = "%[6]s" -serverPubKey = "%[7]x" -channelDefinitionsContractFromBlock = %[8]d -channelDefinitionsContractAddress = "%[9]s" +%s [relayConfig] -chainID = %[10]s -fromBlock = 1`, +%s`, jobName, verifierAddress.Hex(), node.KeyBundle.ID(), fmt.Sprintf("%s@127.0.0.1:%d", bootstrapPeerID, bootstrapNodePort), + relayType, clientPubKey, - serverURL, - serverPubKey, - fromBlock, - configStoreAddress.Hex(), - chainID.String(), + pluginConfig, + relayConfig, )) } -func addOCRJobs(t *testing.T, streams []Stream, serverPubKey ed25519.PublicKey, serverURL string, verifierAddress common.Address, bootstrapPeerID string, bootstrapNodePort int, nodes []Node, configStoreAddress common.Address, clientPubKeys []ed25519.PublicKey, chainID *big.Int, fromBlock int) { +func addOCRJobs( + t *testing.T, + streams []Stream, + serverPubKey ed25519.PublicKey, + serverURL string, + verifierAddress common.Address, + bootstrapPeerID string, + bootstrapNodePort int, + nodes []Node, + configStoreAddress common.Address, + clientPubKeys []ed25519.PublicKey, + pluginConfig, + relayType, + relayConfig string) { ctx := testutils.Context(t) createBridge := func(name string, i int, p *big.Int, borm bridges.ORM) (bridgeName string) { bridge := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { @@ -343,15 +353,13 @@ func addOCRJobs(t *testing.T, streams []Stream, serverPubKey ed25519.PublicKey, t, node, verifierAddress, - configStoreAddress, bootstrapPeerID, bootstrapNodePort, - serverURL, - serverPubKey, clientPubKeys[i], "feed-1", - chainID, - fromBlock, + pluginConfig, + relayType, + relayConfig, ) } } diff --git a/core/services/ocr2/plugins/llo/integration_test.go b/core/services/ocr2/plugins/llo/integration_test.go index fd955879f5..d80a422e68 100644 --- a/core/services/ocr2/plugins/llo/integration_test.go +++ b/core/services/ocr2/plugins/llo/integration_test.go @@ -3,6 +3,7 @@ package llo_test import ( "crypto/ed25519" "encoding/hex" + "encoding/json" "fmt" "math/big" "math/rand" @@ -20,6 +21,7 @@ import ( "github.com/stretchr/testify/require" chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -72,28 +74,31 @@ type Stream struct { baseBenchmarkPrice *big.Int } -func TestIntegration_LLO(t *testing.T) { - testStartTimeStamp := uint32(time.Now().Unix()) - - const fromBlock = 1 // cannot use zero, start from block 1 - - // streams - btcStream := Stream{ +var ( + btcStream = Stream{ id: 51, baseBenchmarkPrice: big.NewInt(20_000 * multiplier), } - ethStream := Stream{ + ethStream = Stream{ id: 52, baseBenchmarkPrice: big.NewInt(1_568 * multiplier), } - linkStream := Stream{ + linkStream = Stream{ id: 53, baseBenchmarkPrice: big.NewInt(7150 * multiplier / 1000), } - dogeStream := Stream{ + dogeStream = Stream{ id: 54, baseBenchmarkPrice: big.NewInt(2_020 * multiplier), } +) + +func TestIntegration_LLO(t *testing.T) { + testStartTimeStamp := uint32(time.Now().Unix()) + + const fromBlock = 1 // cannot use zero, start from block 1 + + // streams streams := []Stream{btcStream, ethStream, linkStream, dogeStream} streamMap := make(map[uint32]Stream) for _, strm := range streams { @@ -131,10 +136,10 @@ func TestIntegration_LLO(t *testing.T) { ) ports := freeport.GetN(t, nNodes) for i := 0; i < nNodes; i++ { - app, peerID, transmitter, kb, _ := setupNode(t, ports[i], fmt.Sprintf("oracle_streams_%d", i), backend, clientCSAKeys[i]) + app, peerID, transmitter, kb, observedLogs := setupNode(t, ports[i], fmt.Sprintf("oracle_streams_%d", i), backend, clientCSAKeys[i]) nodes = append(nodes, Node{ - app, transmitter, kb, + app, transmitter, kb, observedLogs, }) offchainPublicKey, _ := hex.DecodeString(strings.TrimPrefix(kb.OnChainPublicKey(), "0x")) oracles = append(oracles, confighelper.OracleIdentityExtra{ @@ -159,8 +164,16 @@ func TestIntegration_LLO(t *testing.T) { configDigest := setConfig(t, steve, backend, verifierContract, verifierAddress, nodes, oracles) channelDefinitions := setChannelDefinitions(t, steve, backend, configStoreContract, streams) - addBootstrapJob(t, bootstrapNode, chainID, verifierAddress, "job-1") - addOCRJobs(t, streams, serverPubKey, serverURL, verifierAddress, bootstrapPeerID, bootstrapNodePort, nodes, configStoreAddress, clientPubKeys, chainID, fromBlock) + relayType := "evm" + relayConfig := fmt.Sprintf(`chainID = %s +fromBlock = %d`, chainID.String(), fromBlock) + addBootstrapJob(t, bootstrapNode, verifierAddress, "job-1", relayType, relayConfig) + + pluginConfig := fmt.Sprintf(`serverURL = "%s" +serverPubKey = "%x" +channelDefinitionsContractFromBlock = %d +channelDefinitionsContractAddress = "%s"`, serverURL, serverPubKey, fromBlock, configStoreAddress.String()) + addOCRJobs(t, streams, serverPubKey, serverURL, verifierAddress, bootstrapPeerID, bootstrapNodePort, nodes, configStoreAddress, clientPubKeys, pluginConfig, relayType, relayConfig) t.Run("receives at least one report per feed from each oracle when EAs are at 100% reliability", func(t *testing.T) { // Expect at least one report per channel from each oracle (keyed by transmitter ID) seen := make(map[ocr2types.Account]map[llotypes.ChannelID]struct{}) @@ -254,17 +267,24 @@ func TestIntegration_LLO(t *testing.T) { // TODO: test verification } -func setConfig(t *testing.T, steve *bind.TransactOpts, backend *backends.SimulatedBackend, verifierContract *channel_verifier.ChannelVerifier, verifierAddress common.Address, nodes []Node, oracles []confighelper.OracleIdentityExtra) ocr2types.ConfigDigest { +func generateConfig(t *testing.T, nodes []Node, oracles []confighelper.OracleIdentityExtra) ( + signers []types.OnchainPublicKey, + transmitters []types.Account, + f uint8, + onchainConfig []byte, + offchainConfigVersion uint64, + offchainConfig []byte, +) { // Setup config on contract - rawOnchainConfig := datastreamsllo.OnchainConfig{} - onchainConfig, err := (&datastreamsllo.JSONOnchainConfigCodec{}).Encode(rawOnchainConfig) + rawOnchainConfig := llo.OnchainConfig{} + onchainConfig, err := (&llo.JSONOnchainConfigCodec{}).Encode(rawOnchainConfig) require.NoError(t, err) rawReportingPluginConfig := datastreamsllo.OffchainConfig{} reportingPluginConfig, err := rawReportingPluginConfig.Encode() require.NoError(t, err) - signers, _, _, _, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( + signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err = ocr3confighelper.ContractSetConfigArgsForTests( 2*time.Second, // DeltaProgress 20*time.Second, // DeltaResend 400*time.Millisecond, // DeltaInitial @@ -285,24 +305,24 @@ func setConfig(t *testing.T, steve *bind.TransactOpts, backend *backends.Simulat ) require.NoError(t, err) + + return +} + +func setConfig(t *testing.T, steve *bind.TransactOpts, backend *backends.SimulatedBackend, verifierContract *channel_verifier.ChannelVerifier, verifierAddress common.Address, nodes []Node, oracles []confighelper.OracleIdentityExtra) ocr2types.ConfigDigest { + signers, _, _, _, offchainConfigVersion, offchainConfig := generateConfig(t, nodes, oracles) + signerAddresses, err := evm.OnchainPublicKeyToAddress(signers) require.NoError(t, err) - offchainTransmitters := make([][32]byte, nNodes) for i := 0; i < nNodes; i++ { offchainTransmitters[i] = nodes[i].ClientPubKey } - _, err = verifierContract.SetConfig(steve, signerAddresses, offchainTransmitters, fNodes, offchainConfig, offchainConfigVersion, offchainConfig, nil) require.NoError(t, err) backend.Commit() - accounts := make([]ocr2types.Account, len(offchainTransmitters)) - for i := range offchainTransmitters { - accounts[i] = ocr2types.Account(fmt.Sprintf("%x", offchainTransmitters[i])) - } - l, err := verifierContract.LatestConfigDigestAndEpoch(&bind.CallOpts{}) require.NoError(t, err) @@ -367,3 +387,136 @@ func setChannelDefinitions(t *testing.T, steve *bind.TransactOpts, backend *back return channelDefinitions } + +func TestIntegration_LLO_Dummy(t *testing.T) { + testStartTimeStamp := time.Now() + + streams := []Stream{btcStream, ethStream, linkStream, dogeStream} + streamMap := make(map[uint32]Stream) + for _, strm := range streams { + streamMap[strm.id] = strm + } + + clientCSAKeys := make([]csakey.KeyV2, nNodes) + clientPubKeys := make([]ed25519.PublicKey, nNodes) + for i := 0; i < nNodes; i++ { + k := big.NewInt(int64(i)) + key := csakey.MustNewV2XXXTestingOnly(k) + clientCSAKeys[i] = key + clientPubKeys[i] = key.PublicKey + } + + // Setup bootstrap + bootstrapCSAKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) + bootstrapNodePort := freeport.GetOne(t) + appBootstrap, bootstrapPeerID, _, bootstrapKb, _ := setupNode(t, bootstrapNodePort, "bootstrap_mercury", nil, bootstrapCSAKey) + bootstrapNode := Node{App: appBootstrap, KeyBundle: bootstrapKb} + + t.Run("with at least one channel", func(t *testing.T) { + // Setup oracle nodes + var ( + oracles []confighelper.OracleIdentityExtra + nodes []Node + ) + ports := freeport.GetN(t, nNodes) + for i := 0; i < nNodes; i++ { + app, peerID, transmitter, kb, observedLogs := setupNode(t, ports[i], fmt.Sprintf("oracle_streams_%d", i), nil, clientCSAKeys[i]) + + nodes = append(nodes, Node{ + app, transmitter, kb, observedLogs, + }) + offchainPublicKey, _ := hex.DecodeString(strings.TrimPrefix(kb.OnChainPublicKey(), "0x")) + oracles = append(oracles, confighelper.OracleIdentityExtra{ + OracleIdentity: confighelper.OracleIdentity{ + OnchainPublicKey: offchainPublicKey, + TransmitAccount: ocr2types.Account(fmt.Sprintf("%x", transmitter[:])), + OffchainPublicKey: kb.OffchainPublicKey(), + PeerID: peerID, + }, + ConfigEncryptionPublicKey: kb.ConfigEncryptionPublicKey(), + }) + } + + verifierAddress := common.Address{} + chainID := "llo-dummy" + relayType := "dummy" + cd := "0x0102030405060708010203040506070801020304050607080102030405060708" + signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig := generateConfig(t, nodes, oracles) + var signersMarshalled, transmittersMarshalled []byte + { + var err error + signersHex := make([]string, len(signers)) + for i, signer := range signers { + signersHex[i] = fmt.Sprintf("0x%x", signer) + } + signersMarshalled, err = json.Marshal(signersHex) + require.NoError(t, err) + + transmittersMarshalled, err = json.Marshal(transmitters) + require.NoError(t, err) + } + + relayConfig := fmt.Sprintf(`chainID = "%s" +configTracker = { + configDigest = "%s", + configCoung = 1, + signers = %s, + transmitters = %s, + f = %d, + onchainConfig = "0x%x", + offchainConfigVersion = %d, + offchainConfig = "0x%x", + blockHeight = 10 +}`, chainID, cd, string(signersMarshalled), string(transmittersMarshalled), f, onchainConfig, offchainConfigVersion, offchainConfig) + addBootstrapJob(t, bootstrapNode, verifierAddress, "job-1", relayType, relayConfig) + + serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) + serverPubKey := serverKey.PublicKey + serverURL := "foo" + configStoreAddress := common.Address{} + + // NOTE: Don't actually care about the chain ID, it just needs to be + // a valid chainSelector + chainSelector, err := chainselectors.SelectorFromChainId(testutils.SimulatedChainID.Uint64()) + require.NoError(t, err) + + channelDefinitions := fmt.Sprintf(`{ +"42": { + "reportFormat": %d, + "chainSelector": %d, + "streamIds": [51, 52] + } +}`, llotypes.ReportFormatJSON, chainSelector) + + pluginConfig := fmt.Sprintf(`serverURL = "foo" +serverPubKey = "%x" +channelDefinitions = %q`, serverPubKey, channelDefinitions) + addOCRJobs(t, streams, serverPubKey, serverURL, verifierAddress, bootstrapPeerID, bootstrapNodePort, nodes, configStoreAddress, clientPubKeys, pluginConfig, relayType, relayConfig) + + for _, node := range nodes { + le := testutils.WaitForLogMessage(t, node.ObservedLogs, "Transmit") + fields := le.ContextMap() + assert.Equal(t, cd[2:], fields["digest"]) + assert.Equal(t, llotypes.ReportInfo{LifeCycleStage: "production", ReportFormat: llotypes.ReportFormatJSON}, fields["report.Info"]) + + binaryReport := fields["report.Report"].(types.Report) + report, err := (datastreamsllo.JSONReportCodec{}).Decode(binaryReport) + require.NoError(t, err) + assert.Equal(t, datastreamsllo.Report{ + ConfigDigest: types.ConfigDigest{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}, + ChainSelector: 0x2ee634951ef71b46, + SeqNr: fields["seqNr"].(uint64), + ChannelID: 0x2a, + ValidAfterSeconds: report.ValidAfterSeconds, // tested separately below + ValidUntilSeconds: report.ValidUntilSeconds, // tested separately below + Values: []*big.Int{big.NewInt(2000002000000), big.NewInt(156802000000)}, + Specimen: false, + }, report) + assert.GreaterOrEqual(t, report.ValidUntilSeconds, uint32(testStartTimeStamp.Unix())) + assert.GreaterOrEqual(t, report.ValidAfterSeconds, uint32(testStartTimeStamp.Unix())) + assert.GreaterOrEqual(t, report.ValidUntilSeconds, report.ValidAfterSeconds) + + assert.GreaterOrEqual(t, int(fields["seqNr"].(uint64)), 0) + } + }) +} diff --git a/core/services/relay/dummy/config_digester.go b/core/services/relay/dummy/config_digester.go new file mode 100644 index 0000000000..a74e007b0b --- /dev/null +++ b/core/services/relay/dummy/config_digester.go @@ -0,0 +1,26 @@ +package dummy + +import ( + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +// Stub config digester that uses a static config digest + +type configDigester struct { + configDigest ocrtypes.ConfigDigest +} + +func NewOffchainConfigDigester(cd ocrtypes.ConfigDigest) (ocrtypes.OffchainConfigDigester, error) { + return &configDigester{cd}, nil +} + +// Compute ConfigDigest for the given ContractConfig. The first two bytes of the +// ConfigDigest must be the big-endian encoding of ConfigDigestPrefix! +func (cd *configDigester) ConfigDigest(ocrtypes.ContractConfig) (ocrtypes.ConfigDigest, error) { + return cd.configDigest, nil +} + +// This should return the same constant value on every invocation +func (cd *configDigester) ConfigDigestPrefix() (ocrtypes.ConfigDigestPrefix, error) { + return ocrtypes.ConfigDigestPrefixFromConfigDigest(cd.configDigest), nil +} diff --git a/core/services/relay/dummy/config_provider.go b/core/services/relay/dummy/config_provider.go new file mode 100644 index 0000000000..10662ee296 --- /dev/null +++ b/core/services/relay/dummy/config_provider.go @@ -0,0 +1,97 @@ +package dummy + +import ( + "context" + + "github.com/ethereum/go-ethereum/common/hexutil" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// Stub ConfigTracker that uses static config + +// interim struct used for unmarshalling from relay config +type ConfigTrackerCfg struct { + // OCR Config + ConfigDigest hexutil.Bytes + ConfigCount uint64 + Signers []hexutil.Bytes + Transmitters []string + F uint8 + OnchainConfig hexutil.Bytes + OffchainConfigVersion uint64 + OffchainConfig hexutil.Bytes + + // Tracker config + ChangedInBlock uint64 + BlockHeight uint64 +} + +func (cfg ConfigTrackerCfg) ToContractConfig() (ocrtypes.ContractConfig, error) { + cd, err := ocrtypes.BytesToConfigDigest(cfg.ConfigDigest) + if err != nil { + return ocrtypes.ContractConfig{}, err + } + signers := make([]ocrtypes.OnchainPublicKey, len(cfg.Signers)) + for i, s := range cfg.Signers { + signers[i] = ocrtypes.OnchainPublicKey(s) + } + transmitters := make([]ocrtypes.Account, len(cfg.Transmitters)) + for i, t := range cfg.Transmitters { + transmitters[i] = ocrtypes.Account(t) + } + return ocrtypes.ContractConfig{ + ConfigDigest: cd, + ConfigCount: cfg.ConfigCount, + Signers: signers, + Transmitters: transmitters, + F: cfg.F, + OnchainConfig: cfg.OnchainConfig, + OffchainConfigVersion: cfg.OffchainConfigVersion, + OffchainConfig: cfg.OffchainConfig, + }, nil +} + +type configProvider struct { + lggr logger.Logger + + digester ocrtypes.OffchainConfigDigester + tracker ocrtypes.ContractConfigTracker +} + +func NewConfigProvider(lggr logger.Logger, cfg RelayConfig) (types.ConfigProvider, error) { + cp := &configProvider{lggr: lggr.Named("DummyConfigProvider")} + + { + contractConfig, err := cfg.ConfigTracker.ToContractConfig() + if err != nil { + return nil, err + } + + cp.digester, err = NewOffchainConfigDigester(contractConfig.ConfigDigest) + if err != nil { + return nil, err + } + } + var err error + cp.tracker, err = NewContractConfigTracker(cp.lggr, cfg.ConfigTracker) + if err != nil { + return nil, err + } + return cp, nil +} + +func (cp *configProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { + return cp.digester +} +func (cp *configProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker { return cp.tracker } +func (cp *configProvider) Name() string { return cp.lggr.Name() } +func (*configProvider) Start(context.Context) error { return nil } +func (*configProvider) Close() error { return nil } +func (*configProvider) Ready() error { return nil } +func (cp *configProvider) HealthReport() map[string]error { + return map[string]error{cp.lggr.Name(): nil} +} diff --git a/core/services/relay/dummy/config_tracker.go b/core/services/relay/dummy/config_tracker.go new file mode 100644 index 0000000000..0ae188361f --- /dev/null +++ b/core/services/relay/dummy/config_tracker.go @@ -0,0 +1,51 @@ +package dummy + +import ( + "context" + + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +type configTracker struct { + lggr logger.Logger + cfg ocrtypes.ContractConfig + + changedInBlock uint64 + blockHeight uint64 +} + +func NewContractConfigTracker(lggr logger.Logger, cfg ConfigTrackerCfg) (ocrtypes.ContractConfigTracker, error) { + contractConfig, err := cfg.ToContractConfig() + if err != nil { + return nil, err + } + return &configTracker{lggr.Named("DummyConfigProvider"), contractConfig, cfg.ChangedInBlock, cfg.BlockHeight}, nil +} + +// Notify may optionally emit notification events when the contract's +// configuration changes. This is purely used as an optimization reducing +// the delay between a configuration change and its enactment. Implementors +// who don't care about this may simply return a nil channel. +// +// The returned channel should never be closed. +func (ct *configTracker) Notify() <-chan struct{} { + return nil +} + +// LatestConfigDetails returns information about the latest configuration, +// but not the configuration itself. +func (ct *configTracker) LatestConfigDetails(ctx context.Context) (changedInBlock uint64, configDigest ocrtypes.ConfigDigest, err error) { + return ct.changedInBlock, ct.cfg.ConfigDigest, nil +} + +// LatestConfig returns the latest configuration. +func (ct *configTracker) LatestConfig(ctx context.Context, changedInBlock uint64) (ocrtypes.ContractConfig, error) { + return ct.cfg, nil +} + +// LatestBlockHeight returns the height of the most recent block in the chain. +func (ct *configTracker) LatestBlockHeight(ctx context.Context) (blockHeight uint64, err error) { + return ct.blockHeight, nil // set LatestBlockHeight to a high number so that OCR considers it to be confirmed +} diff --git a/core/services/relay/dummy/llo_provider.go b/core/services/relay/dummy/llo_provider.go new file mode 100644 index 0000000000..4aeb21bed8 --- /dev/null +++ b/core/services/relay/dummy/llo_provider.go @@ -0,0 +1,86 @@ +package dummy + +import ( + "context" + "errors" + + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/llo" +) + +var _ commontypes.LLOProvider = (*lloProvider)(nil) + +type lloProvider struct { + cp commontypes.ConfigProvider + transmitter llo.Transmitter + logger logger.Logger + channelDefinitionCache llotypes.ChannelDefinitionCache + + ms services.MultiStart +} + +func NewLLOProvider( + lggr logger.Logger, + cp commontypes.ConfigProvider, + transmitter llo.Transmitter, + channelDefinitionCache llotypes.ChannelDefinitionCache, +) relaytypes.LLOProvider { + return &lloProvider{ + cp, + transmitter, + lggr.Named("LLOProvider"), + channelDefinitionCache, + services.MultiStart{}, + } +} + +func (p *lloProvider) Start(ctx context.Context) error { + err := p.ms.Start(ctx, p.cp, p.transmitter, p.channelDefinitionCache) + return err +} + +func (p *lloProvider) Close() error { + return p.ms.Close() +} + +func (p *lloProvider) Ready() error { + return errors.Join(p.cp.Ready(), p.transmitter.Ready(), p.channelDefinitionCache.Ready()) +} + +func (p *lloProvider) Name() string { + return p.logger.Name() +} + +func (p *lloProvider) HealthReport() map[string]error { + report := map[string]error{p.Name(): nil} + services.CopyHealth(report, p.cp.HealthReport()) + services.CopyHealth(report, p.transmitter.HealthReport()) + services.CopyHealth(report, p.channelDefinitionCache.HealthReport()) + return report +} + +func (p *lloProvider) ContractConfigTracker() ocrtypes.ContractConfigTracker { + return p.cp.ContractConfigTracker() +} + +func (p *lloProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { + return p.cp.OffchainConfigDigester() +} + +func (p *lloProvider) OnchainConfigCodec() llo.OnchainConfigCodec { + return &llo.JSONOnchainConfigCodec{} +} + +func (p *lloProvider) ContractTransmitter() llotypes.Transmitter { + return p.transmitter +} + +func (p *lloProvider) ChannelDefinitionCache() llotypes.ChannelDefinitionCache { + return p.channelDefinitionCache +} diff --git a/core/services/relay/dummy/relayer.go b/core/services/relay/dummy/relayer.go new file mode 100644 index 0000000000..9818eabb20 --- /dev/null +++ b/core/services/relay/dummy/relayer.go @@ -0,0 +1,78 @@ +package dummy + +import ( + "context" + "encoding/json" + "math/big" + + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + "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/llo/config" +) + +// The dummy relayer is a simple reference implementation that doesn't actually +// connect to any chain. It's useful for testing and as a reference for +// implementing a new relayer. + +type RelayConfig struct { + ConfigTracker ConfigTrackerCfg +} + +type relayer struct { + lggr logger.Logger + chainID string +} + +func NewRelayer(lggr logger.Logger, chainID string) loop.Relayer { + return &relayer{lggr, chainID} +} + +func (r *relayer) NewContractReader(ctx context.Context, contractReaderConfig []byte) (types.ContractReader, error) { + return nil, nil +} +func (r *relayer) NewConfigProvider(_ context.Context, rargs types.RelayArgs) (types.ConfigProvider, error) { + var cfg RelayConfig + if err := json.Unmarshal(rargs.RelayConfig, &cfg); err != nil { + return nil, err + } + return NewConfigProvider(r.lggr, cfg) +} +func (r *relayer) NewPluginProvider(context.Context, types.RelayArgs, types.PluginArgs) (types.PluginProvider, error) { + return nil, nil +} +func (r *relayer) NewLLOProvider(ctx context.Context, rargs types.RelayArgs, pargs types.PluginArgs) (types.LLOProvider, error) { + cp, err := r.NewConfigProvider(ctx, rargs) + if err != nil { + return nil, err + } + transmitter := bm.NewTransmitter(r.lggr, pargs.TransmitterID) + pluginCfg := new(config.PluginConfig) + if err = pluginCfg.Unmarshal(pargs.PluginConfig); err != nil { + return nil, err + } + cdc, err := llo.NewStaticChannelDefinitionCache(r.lggr, pluginCfg.ChannelDefinitions) + if err != nil { + return nil, err + } + return NewLLOProvider(r.lggr, cp, transmitter, cdc), nil +} +func (r *relayer) GetChainStatus(ctx context.Context) (types.ChainStatus, error) { + return types.ChainStatus{}, nil +} +func (r *relayer) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []types.NodeStatus, nextPageToken string, total int, err error) { + return nil, "", 0, nil +} +func (r *relayer) Transact(ctx context.Context, from, to string, amount *big.Int, balanceCheck bool) error { + return nil +} +func (r *relayer) Name() string { return r.lggr.Name() } +func (r *relayer) Start(context.Context) error { return nil } +func (r *relayer) Close() error { return nil } +func (r *relayer) Ready() error { return nil } +func (r *relayer) HealthReport() map[string]error { + return map[string]error{r.lggr.Name(): nil} +} diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 61c484f82b..e6732a81cf 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -357,7 +357,7 @@ func (r *Relayer) NewLLOProvider(rargs commontypes.RelayArgs, pargs commontypes. var transmitter llo.Transmitter if lloCfg.BenchmarkMode { r.lggr.Info("Benchmark mode enabled, using dummy transmitter. NOTE: THIS WILL NOT TRANSMIT ANYTHING") - transmitter = bm.NewTransmitter(r.lggr, privKey.PublicKey) + transmitter = bm.NewTransmitter(r.lggr, fmt.Sprintf("%x", privKey.PublicKey)) } else { var client wsrpc.Client client, err = r.mercuryPool.Checkout(context.Background(), privKey, lloCfg.ServerPubKey, lloCfg.ServerURL()) diff --git a/core/services/relay/evm/llo_provider.go b/core/services/relay/evm/llo_provider.go index 0ab0773a16..b685565e6e 100644 --- a/core/services/relay/evm/llo_provider.go +++ b/core/services/relay/evm/llo_provider.go @@ -10,7 +10,6 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/llo" @@ -75,10 +74,8 @@ func (p *lloProvider) OffchainConfigDigester() ocrtypes.OffchainConfigDigester { return p.cp.OffchainConfigDigester() } -func (p *lloProvider) OnchainConfigCodec() datastreamsllo.OnchainConfigCodec { - // TODO: This should probably be moved to core since its chain-specific - // https://smartcontract-it.atlassian.net/browse/MERC-3661 - return &datastreamsllo.JSONOnchainConfigCodec{} +func (p *lloProvider) OnchainConfigCodec() llo.OnchainConfigCodec { + return &llo.JSONOnchainConfigCodec{} } func (p *lloProvider) ContractTransmitter() llotypes.Transmitter { diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go index de3f80a5e7..a2681418ce 100644 --- a/core/services/relay/relay.go +++ b/core/services/relay/relay.go @@ -6,6 +6,8 @@ const ( NetworkSolana = "solana" NetworkStarkNet = "starknet" NetworkAptos = "aptos" + + NetworkDummy = "dummy" ) var SupportedNetworks = map[string]struct{}{ @@ -14,4 +16,6 @@ var SupportedNetworks = map[string]struct{}{ NetworkSolana: {}, NetworkStarkNet: {}, NetworkAptos: {}, + + NetworkDummy: {}, } From c8b2836b360cb9cdf79b748add83859bb609d820 Mon Sep 17 00:00:00 2001 From: krehermann Date: Tue, 25 Jun 2024 11:43:21 -0600 Subject: [PATCH 04/61] re-enable v2 test (#13656) --- core/services/ocr2/plugins/mercury/integration_plugin_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/services/ocr2/plugins/mercury/integration_plugin_test.go b/core/services/ocr2/plugins/mercury/integration_plugin_test.go index 4089cc485c..1dedaadcb5 100644 --- a/core/services/ocr2/plugins/mercury/integration_plugin_test.go +++ b/core/services/ocr2/plugins/mercury/integration_plugin_test.go @@ -6,23 +6,19 @@ import ( "testing" "github.com/smartcontractkit/chainlink/v2/core/config/env" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) func TestIntegration_MercuryV1_Plugin(t *testing.T) { t.Setenv(string(env.MercuryPlugin.Cmd), "chainlink-mercury") - integration_MercuryV1(t) } func TestIntegration_MercuryV2_Plugin(t *testing.T) { - testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/MERC-5697") t.Setenv(string(env.MercuryPlugin.Cmd), "chainlink-mercury") integration_MercuryV2(t) } func TestIntegration_MercuryV3_Plugin(t *testing.T) { t.Setenv(string(env.MercuryPlugin.Cmd), "chainlink-mercury") - integration_MercuryV3(t) } From ed6b9ad7909e09d0ff9850b7a1e34a0137762642 Mon Sep 17 00:00:00 2001 From: Ryan Hall Date: Tue, 25 Jun 2024 13:49:11 -0400 Subject: [PATCH 05/61] remove stale automation HH tests (#13676) --- contracts/.changeset/tricky-comics-scream.md | 5 + .../automation/IKeeperRegistryMaster.test.ts | 116 - .../v0.8/automation/KeeperRegistrar.test.ts | 812 --- .../v0.8/automation/KeeperRegistry2_1.test.ts | 5655 ----------------- ...RegistryCheckUpkeepGasUsageWrapper.test.ts | 110 - .../v0.8/automation/UpkeepTranscoder.test.ts | 70 - 6 files changed, 5 insertions(+), 6763 deletions(-) create mode 100644 contracts/.changeset/tricky-comics-scream.md delete mode 100644 contracts/test/v0.8/automation/IKeeperRegistryMaster.test.ts delete mode 100644 contracts/test/v0.8/automation/KeeperRegistrar.test.ts delete mode 100644 contracts/test/v0.8/automation/KeeperRegistry2_1.test.ts delete mode 100644 contracts/test/v0.8/automation/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts delete mode 100644 contracts/test/v0.8/automation/UpkeepTranscoder.test.ts diff --git a/contracts/.changeset/tricky-comics-scream.md b/contracts/.changeset/tricky-comics-scream.md new file mode 100644 index 0000000000..f7cd1ceeab --- /dev/null +++ b/contracts/.changeset/tricky-comics-scream.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +remove stale automation HH tests diff --git a/contracts/test/v0.8/automation/IKeeperRegistryMaster.test.ts b/contracts/test/v0.8/automation/IKeeperRegistryMaster.test.ts deleted file mode 100644 index f894aa87cd..0000000000 --- a/contracts/test/v0.8/automation/IKeeperRegistryMaster.test.ts +++ /dev/null @@ -1,116 +0,0 @@ -import fs from 'fs' -import { ethers } from 'hardhat' -import { assert } from 'chai' -import { KeeperRegistry2_1__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry2_1__factory' -import { KeeperRegistryLogicA2_1__factory as KeeperRegistryLogicAFactory } from '../../../typechain/factories/KeeperRegistryLogicA2_1__factory' -import { KeeperRegistryLogicB2_1__factory as KeeperRegistryLogicBFactory } from '../../../typechain/factories/KeeperRegistryLogicB2_1__factory' -import { KeeperRegistryBase2_1__factory as KeeperRegistryBaseFactory } from '../../../typechain/factories/KeeperRegistryBase2_1__factory' -import { Chainable__factory as ChainableFactory } from '../../../typechain/factories/Chainable__factory' -import { IKeeperRegistryMaster__factory as IKeeperRegistryMasterFactory } from '../../../typechain/factories/IKeeperRegistryMaster__factory' -import { IAutomationRegistryConsumer__factory as IAutomationRegistryConsumerFactory } from '../../../typechain/factories/IAutomationRegistryConsumer__factory' -import { MigratableKeeperRegistryInterface__factory as MigratableKeeperRegistryInterfaceFactory } from '../../../typechain/factories/MigratableKeeperRegistryInterface__factory' -import { MigratableKeeperRegistryInterfaceV2__factory as MigratableKeeperRegistryInterfaceV2Factory } from '../../../typechain/factories/MigratableKeeperRegistryInterfaceV2__factory' -import { OCR2Abstract__factory as OCR2AbstractFactory } from '../../../typechain/factories/OCR2Abstract__factory' -import { IAutomationV21PlusCommon__factory as IAutomationV21PlusCommonFactory } from '../../../typechain/factories/IAutomationV21PlusCommon__factory' -import { - assertSatisfiesEvents, - assertSatisfiesInterface, - entryID, -} from './helpers' - -const compositeABIs = [ - KeeperRegistryFactory.abi, - KeeperRegistryLogicAFactory.abi, - KeeperRegistryLogicBFactory.abi, -] - -/** - * @dev because the keeper master interface is a composite of several different contracts, - * it is possible that an interface could be satisfied by functions across different - * contracts, and therefore not enforceable by the compiler directly. Instead, we use this - * test to assert that the master interface satisfies the constraints of an individual interface - */ -describe('IKeeperRegistryMaster', () => { - it('is up to date', async () => { - const checksum = ethers.utils.id(compositeABIs.join('')) - const knownChecksum = fs - .readFileSync( - 'src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol', - ) - .toString() - .slice(17, 83) // checksum located at top of file - assert.equal( - checksum, - knownChecksum, - 'master interface is out of date - regenerate using "pnpm ts-node ./scripts/generate-automation-master-interface.ts"', - ) - }) - - it('is generated from composite contracts without competing definitions', async () => { - const sharedEntries = [ - ...ChainableFactory.abi, - ...KeeperRegistryBaseFactory.abi, - ] - const abiSet = new Set() - const sharedSet = new Set() - for (const entry of sharedEntries) { - sharedSet.add(entryID(entry)) - } - for (const abi of compositeABIs) { - for (const entry of abi) { - const id = entryID(entry) - if (!abiSet.has(id)) { - abiSet.add(id) - } else if (!sharedSet.has(id)) { - assert.fail( - `composite contracts contain duplicate entry: ${JSON.stringify( - entry, - )}`, - ) - } - } - } - }) - - it('satisfies the IAutomationRegistryConsumer interface', async () => { - assertSatisfiesInterface( - IKeeperRegistryMasterFactory.abi, - IAutomationRegistryConsumerFactory.abi, - ) - }) - - it('satisfies the MigratableKeeperRegistryInterface interface', async () => { - assertSatisfiesInterface( - IKeeperRegistryMasterFactory.abi, - MigratableKeeperRegistryInterfaceFactory.abi, - ) - }) - - it('satisfies the MigratableKeeperRegistryInterfaceV2 interface', async () => { - assertSatisfiesInterface( - IKeeperRegistryMasterFactory.abi, - MigratableKeeperRegistryInterfaceV2Factory.abi, - ) - }) - - it('satisfies the OCR2Abstract interface', async () => { - assertSatisfiesInterface( - IKeeperRegistryMasterFactory.abi, - OCR2AbstractFactory.abi, - ) - }) - - it('satisfies the IAutomationV2Common interface', async () => { - assertSatisfiesInterface( - IKeeperRegistryMasterFactory.abi, - IAutomationV21PlusCommonFactory.abi, - ) - }) - - it('satisfies the IAutomationV2Common events', async () => { - assertSatisfiesEvents( - IKeeperRegistryMasterFactory.abi, - IAutomationV21PlusCommonFactory.abi, - ) - }) -}) diff --git a/contracts/test/v0.8/automation/KeeperRegistrar.test.ts b/contracts/test/v0.8/automation/KeeperRegistrar.test.ts deleted file mode 100644 index 8aef681010..0000000000 --- a/contracts/test/v0.8/automation/KeeperRegistrar.test.ts +++ /dev/null @@ -1,812 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { evmRevert, evmRevertCustomError } from '../../test-helpers/matchers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { BigNumber, Signer } from 'ethers' -import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' - -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' -import { KeeperRegistry1_2 as KeeperRegistry } from '../../../typechain/KeeperRegistry1_2' -import { KeeperRegistry1_2__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry1_2__factory' -import { KeeperRegistrar } from '../../../typechain/KeeperRegistrar' -import { KeeperRegistrar__factory as KeeperRegistrarFactory } from '../../../typechain/factories/KeeperRegistrar__factory' - -import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' -import { LinkToken } from '../../../typechain/LinkToken' -import { UpkeepMock } from '../../../typechain/UpkeepMock' -import { toWei } from '../../test-helpers/helpers' - -let linkTokenFactory: LinkTokenFactory -let mockV3AggregatorFactory: MockV3AggregatorFactory -let keeperRegistryFactory: KeeperRegistryFactory -let keeperRegistrar: KeeperRegistrarFactory -let upkeepMockFactory: UpkeepMockFactory - -let personas: Personas - -before(async () => { - personas = (await getUsers()).personas - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - // @ts-ignore bug in autogen file - keeperRegistryFactory = await ethers.getContractFactory('KeeperRegistry1_2') - keeperRegistrar = await ethers.getContractFactory('KeeperRegistrar') - upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') -}) - -const errorMsgs = { - onlyOwner: 'revert Only callable by owner', - onlyAdmin: 'OnlyAdminOrOwner', - hashPayload: 'HashMismatch', - requestNotFound: 'RequestNotFound', -} - -describe('KeeperRegistrar', () => { - const upkeepName = 'SampleUpkeep' - - const linkEth = BigNumber.from(300000000) - const gasWei = BigNumber.from(100) - const executeGas = BigNumber.from(100000) - const source = BigNumber.from(100) - const paymentPremiumPPB = BigNumber.from(250000000) - const flatFeeMicroLink = BigNumber.from(0) - const maxAllowedAutoApprove = 5 - - const blockCountPerTurn = BigNumber.from(3) - const emptyBytes = '0x00' - const stalenessSeconds = BigNumber.from(43820) - const gasCeilingMultiplier = BigNumber.from(1) - const checkGasLimit = BigNumber.from(20000000) - const fallbackGasPrice = BigNumber.from(200) - const fallbackLinkPrice = BigNumber.from(200000000) - const maxPerformGas = BigNumber.from(5000000) - const minUpkeepSpend = BigNumber.from('1000000000000000000') - const amount = BigNumber.from('5000000000000000000') - const amount1 = BigNumber.from('6000000000000000000') - const transcoder = ethers.constants.AddressZero - - // Enum values are not auto exported in ABI so have to manually declare - const autoApproveType_DISABLED = 0 - const autoApproveType_ENABLED_SENDER_ALLOWLIST = 1 - const autoApproveType_ENABLED_ALL = 2 - - let owner: Signer - let admin: Signer - let someAddress: Signer - let registrarOwner: Signer - let stranger: Signer - let requestSender: Signer - - let linkToken: LinkToken - let linkEthFeed: MockV3Aggregator - let gasPriceFeed: MockV3Aggregator - let registry: KeeperRegistry - let mock: UpkeepMock - let registrar: KeeperRegistrar - - beforeEach(async () => { - owner = personas.Default - admin = personas.Neil - someAddress = personas.Ned - registrarOwner = personas.Nelly - stranger = personas.Nancy - requestSender = personas.Norbert - - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder, - registrar: ethers.constants.AddressZero, - } - - linkToken = await linkTokenFactory.connect(owner).deploy() - gasPriceFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(0, gasWei) - linkEthFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(9, linkEth) - registry = await keeperRegistryFactory - .connect(owner) - .deploy( - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - config, - ) - - mock = await upkeepMockFactory.deploy() - - registrar = await keeperRegistrar - .connect(registrarOwner) - .deploy( - linkToken.address, - autoApproveType_DISABLED, - BigNumber.from('0'), - registry.address, - minUpkeepSpend, - ) - - await linkToken - .connect(owner) - .transfer(await requestSender.getAddress(), toWei('1000')) - - config.registrar = registrar.address - await registry.setConfig(config) - }) - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await registrar.typeAndVersion() - assert.equal(typeAndVersion, 'KeeperRegistrar 1.1.0') - }) - }) - - describe('#register', () => { - it('reverts if not called by the LINK token', async () => { - await evmRevertCustomError( - registrar - .connect(someAddress) - .register( - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ), - registrar, - 'OnlyLink', - ) - }) - - it('reverts if the amount passed in data mismatches actual amount sent', async () => { - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_ALL, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount1, - source, - await requestSender.getAddress(), - ], - ) - - await evmRevertCustomError( - linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes), - registrar, - 'AmountMismatch', - ) - }) - - it('reverts if the sender passed in data mismatches actual sender', async () => { - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await admin.getAddress(), // Should have been requestSender.getAddress() - ], - ) - await evmRevertCustomError( - linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes), - registrar, - 'SenderMismatch', - ) - }) - - it('reverts if the admin address is 0x0000...', async () => { - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - '0x0000000000000000000000000000000000000000', - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ], - ) - - await evmRevertCustomError( - linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes), - registrar, - 'RegistrationRequestFailed', - ) - }) - - it('Auto Approve ON - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { - //set auto approve ON with high threshold limits - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_ALL, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve ON - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - - const [id] = await registry.getActiveUpkeepIDs(0, 1) - - //confirm if a new upkeep has been registered and the details are the same as the one just registered - const newupkeep = await registry.getUpkeep(id) - assert.equal(newupkeep.target, mock.address) - assert.equal(newupkeep.admin, await admin.getAddress()) - assert.equal(newupkeep.checkData, emptyBytes) - assert.equal(newupkeep.balance.toString(), amount.toString()) - assert.equal(newupkeep.executeGas, executeGas.toNumber()) - - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).to.emit(registrar, 'RegistrationApproved') - }) - - it('Auto Approve OFF - does not registers an upkeep on KeeperRegistry, emits only RegistrationRequested event', async () => { - //get upkeep count before attempting registration - const beforeCount = (await registry.getState()).state.numUpkeeps - - //set auto approve OFF, threshold limits dont matter in this case - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_DISABLED, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve OFF - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - - //get upkeep count after attempting registration - const afterCount = (await registry.getState()).state.numUpkeeps - //confirm that a new upkeep has NOT been registered and upkeep count is still the same - assert.deepEqual(beforeCount, afterCount) - - //confirm that only RegistrationRequested event is emitted and RegistrationApproved event is not - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).not.to.emit(registrar, 'RegistrationApproved') - - const hash = receipt.logs[2].topics[1] - const pendingRequest = await registrar.getPendingRequest(hash) - assert.equal(await admin.getAddress(), pendingRequest[0]) - assert.ok(amount.eq(pendingRequest[1])) - }) - - it('Auto Approve ON - Throttle max approvals - does not register an upkeep on KeeperRegistry beyond the max limit, emits only RegistrationRequested event after limit is hit', async () => { - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 0) - - //set auto approve on, with max 1 allowed - await registrar.connect(registrarOwner).setRegistrationConfig( - autoApproveType_ENABLED_ALL, - 1, // maxAllowedAutoApprove - registry.address, - minUpkeepSpend, - ) - - //register within threshold, new upkeep should be registered - let abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // 0 -> 1 - - //try registering another one, new upkeep should not be registered - abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas.toNumber() + 1, // make unique hash - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // Still 1 - - // Now set new max limit to 2. One more upkeep should get auto approved - await registrar.connect(registrarOwner).setRegistrationConfig( - autoApproveType_ENABLED_ALL, - 2, // maxAllowedAutoApprove - registry.address, - minUpkeepSpend, - ) - abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas.toNumber() + 2, // make unique hash - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 2) // 1 -> 2 - - // One more upkeep should not get registered - abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas.toNumber() + 3, // make unique hash - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 2) // Still 2 - }) - - it('Auto Approve Sender Allowlist - sender in allowlist - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { - const senderAddress = await requestSender.getAddress() - - //set auto approve to ENABLED_SENDER_ALLOWLIST type with high threshold limits - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_SENDER_ALLOWLIST, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - // Add sender to allowlist - await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, true) - - //register with auto approve ON - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - - const [id] = await registry.getActiveUpkeepIDs(0, 1) - - //confirm if a new upkeep has been registered and the details are the same as the one just registered - const newupkeep = await registry.getUpkeep(id) - assert.equal(newupkeep.target, mock.address) - assert.equal(newupkeep.admin, await admin.getAddress()) - assert.equal(newupkeep.checkData, emptyBytes) - assert.equal(newupkeep.balance.toString(), amount.toString()) - assert.equal(newupkeep.executeGas, executeGas.toNumber()) - - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).to.emit(registrar, 'RegistrationApproved') - }) - - it('Auto Approve Sender Allowlist - sender NOT in allowlist - does not registers an upkeep on KeeperRegistry, emits only RegistrationRequested event', async () => { - const beforeCount = (await registry.getState()).state.numUpkeeps - const senderAddress = await requestSender.getAddress() - - //set auto approve to ENABLED_SENDER_ALLOWLIST type with high threshold limits - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_SENDER_ALLOWLIST, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - // Explicitly remove sender from allowlist - await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, false) - - //register. auto approve shouldn't happen - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - - //get upkeep count after attempting registration - const afterCount = (await registry.getState()).state.numUpkeeps - //confirm that a new upkeep has NOT been registered and upkeep count is still the same - assert.deepEqual(beforeCount, afterCount) - - //confirm that only RegistrationRequested event is emitted and RegistrationApproved event is not - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).not.to.emit(registrar, 'RegistrationApproved') - - const hash = receipt.logs[2].topics[1] - const pendingRequest = await registrar.getPendingRequest(hash) - assert.equal(await admin.getAddress(), pendingRequest[0]) - assert.ok(amount.eq(pendingRequest[1])) - }) - }) - - describe('#setAutoApproveAllowedSender', () => { - it('reverts if not called by the owner', async () => { - const tx = registrar - .connect(stranger) - .setAutoApproveAllowedSender(await admin.getAddress(), false) - await evmRevert(tx, 'Only callable by owner') - }) - - it('sets the allowed status correctly and emits log', async () => { - const senderAddress = await stranger.getAddress() - let tx = await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, true) - await expect(tx) - .to.emit(registrar, 'AutoApproveAllowedSenderSet') - .withArgs(senderAddress, true) - - let senderAllowedStatus = await registrar - .connect(owner) - .getAutoApproveAllowedSender(senderAddress) - assert.isTrue(senderAllowedStatus) - - tx = await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, false) - await expect(tx) - .to.emit(registrar, 'AutoApproveAllowedSenderSet') - .withArgs(senderAddress, false) - - senderAllowedStatus = await registrar - .connect(owner) - .getAutoApproveAllowedSender(senderAddress) - assert.isFalse(senderAllowedStatus) - }) - }) - - describe('#approve', () => { - let hash: string - - beforeEach(async () => { - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_DISABLED, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve OFF - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ], - ) - - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - hash = receipt.logs[2].topics[1] - }) - - it('reverts if not called by the owner', async () => { - const tx = registrar - .connect(stranger) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - hash, - ) - await evmRevert(tx, 'Only callable by owner') - }) - - it('reverts if the hash does not exist', async () => { - const tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', - ) - await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) - }) - - it('reverts if any member of the payload changes', async () => { - let tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - ethers.Wallet.createRandom().address, - executeGas, - await admin.getAddress(), - emptyBytes, - hash, - ) - await evmRevertCustomError(tx, registrar, errorMsgs.hashPayload) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - 10000, - await admin.getAddress(), - emptyBytes, - hash, - ) - await evmRevertCustomError(tx, registrar, errorMsgs.hashPayload) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - ethers.Wallet.createRandom().address, - emptyBytes, - hash, - ) - await evmRevertCustomError(tx, registrar, errorMsgs.hashPayload) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - '0x1234', - hash, - ) - await evmRevertCustomError(tx, registrar, errorMsgs.hashPayload) - }) - - it('approves an existing registration request', async () => { - const tx = await registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - hash, - ) - await expect(tx).to.emit(registrar, 'RegistrationApproved') - }) - - it('deletes the request afterwards / reverts if the request DNE', async () => { - await registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - hash, - ) - const tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - hash, - ) - await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) - }) - }) - - describe('#cancel', () => { - let hash: string - - beforeEach(async () => { - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_DISABLED, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve OFF - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - amount, - source, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - hash = receipt.logs[2].topics[1] - // submit duplicate request (increase balance) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - }) - - it('reverts if not called by the admin / owner', async () => { - const tx = registrar.connect(stranger).cancel(hash) - await evmRevertCustomError(tx, registrar, errorMsgs.onlyAdmin) - }) - - it('reverts if the hash does not exist', async () => { - const tx = registrar - .connect(registrarOwner) - .cancel( - '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', - ) - await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) - }) - - it('refunds the total request balance to the admin address', async () => { - const before = await linkToken.balanceOf(await admin.getAddress()) - const tx = await registrar.connect(admin).cancel(hash) - const after = await linkToken.balanceOf(await admin.getAddress()) - assert.isTrue(after.sub(before).eq(amount.mul(BigNumber.from(2)))) - await expect(tx).to.emit(registrar, 'RegistrationRejected') - }) - - it('deletes the request hash', async () => { - await registrar.connect(registrarOwner).cancel(hash) - let tx = registrar.connect(registrarOwner).cancel(hash) - await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - hash, - ) - await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/KeeperRegistry2_1.test.ts b/contracts/test/v0.8/automation/KeeperRegistry2_1.test.ts deleted file mode 100644 index 05bdabbea5..0000000000 --- a/contracts/test/v0.8/automation/KeeperRegistry2_1.test.ts +++ /dev/null @@ -1,5655 +0,0 @@ -import { ethers } from 'hardhat' -import { assert } from 'chai' -import { KeeperRegistry2_1__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry2_1__factory' -import { KeeperRegistryLogicA2_1__factory as KeeperRegistryLogicAFactory } from '../../../typechain/factories/KeeperRegistryLogicA2_1__factory' -import { KeeperRegistryLogicB2_1__factory as KeeperRegistryLogicBFactory } from '../../../typechain/factories/KeeperRegistryLogicB2_1__factory' -import { AutomationForwarderLogic__factory as AutomationForwarderLogicFactory } from '../../../typechain/factories/AutomationForwarderLogic__factory' - -// const describeMaybe = process.env.SKIP_SLOW ? describe.skip : describe -// const itMaybe = process.env.SKIP_SLOW ? it.skip : it - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -/*********************************** REGISTRY v2.1 IS FROZEN ************************************/ - -// We are leaving the original tests enabled, however as 2.1 is still actively being deployed - -describe('KeeperRegistry2_1 - Frozen [ @skip-coverage ]', () => { - it('has not changed', () => { - assert.equal( - ethers.utils.id(KeeperRegistryFactory.bytecode), - '0x05aaa1024d7400e9c4824dde093b96edf5888fa6e6be2c2fc4dca7ae47cc9de9', - 'KeeperRegistry bytecode has changed', - ) - assert.equal( - ethers.utils.id(KeeperRegistryLogicAFactory.bytecode), - '0xdcc8805e88c550b2a25b972bee9f4e4c3649f01e26f8dda6b25d7a9c5da8ab2f', - 'KeeperRegistryLogicA bytecode has changed', - ) - assert.equal( - ethers.utils.id(KeeperRegistryLogicBFactory.bytecode), - '0x891c26ba35b9b13afc9400fac5471d15842828ab717cbdc70ee263210c542563', - 'KeeperRegistryLogicB bytecode has changed', - ) - assert.equal( - ethers.utils.id(AutomationForwarderLogicFactory.bytecode), - '0x6b89065111e9236407329fae3d68b33c311b7d3b6c2ae3dd15c1691a28b1aca7', - 'AutomationForwarderLogic bytecode has changed', - ) - }) -}) - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -// copied from AutomationRegistryInterface2_1.sol -// enum UpkeepFailureReason { -// NONE, -// UPKEEP_CANCELLED, -// UPKEEP_PAUSED, -// TARGET_CHECK_REVERTED, -// UPKEEP_NOT_NEEDED, -// PERFORM_DATA_EXCEEDS_LIMIT, -// INSUFFICIENT_BALANCE, -// CHECK_CALLBACK_REVERTED, -// REVERT_DATA_EXCEEDS_LIMIT, -// REGISTRY_PAUSED, -// } -// -// // copied from AutomationRegistryInterface2_1.sol -// enum Mode { -// DEFAULT, -// ARBITRUM, -// OPTIMISM, -// } -// -// // copied from KeeperRegistryBase2_1.sol -// enum Trigger { -// CONDITION, -// LOG, -// } -// -// // un-exported types that must be extracted from the utils contract -// type Report = Parameters[0] -// type OnChainConfig = Parameters[0] -// type LogTrigger = Parameters[0] -// type ConditionalTrigger = Parameters[0] -// type Log = Parameters[0] -// -// // ----------------------------------------------------------------------------------------------- -// -// // These values should match the constants declared in registry -// let registryConditionalOverhead: BigNumber -// let registryLogOverhead: BigNumber -// let registryPerSignerGasOverhead: BigNumber -// let registryPerPerformByteGasOverhead: BigNumber -// let cancellationDelay: number -// -// // This is the margin for gas that we test for. Gas charged should always be greater -// // than total gas used in tx but should not increase beyond this margin -// const gasCalculationMargin = BigNumber.from(8000) -// -// const linkEth = BigNumber.from(5000000000000000) // 1 Link = 0.005 Eth -// const gasWei = BigNumber.from(1000000000) // 1 gwei -// // ----------------------------------------------------------------------------------------------- -// // test-wide configs for upkeeps -// const linkDivisibility = BigNumber.from('1000000000000000000') -// const performGas = BigNumber.from('1000000') -// const paymentPremiumBase = BigNumber.from('1000000000') -// const paymentPremiumPPB = BigNumber.from('250000000') -// const flatFeeMicroLink = BigNumber.from(0) -// -// const randomBytes = '0x1234abcd' -// const emptyBytes = '0x' -// const emptyBytes32 = -// '0x0000000000000000000000000000000000000000000000000000000000000000' -// -// const transmitGasOverhead = 1_000_000 -// const checkGasOverhead = 400_000 -// -// const stalenessSeconds = BigNumber.from(43820) -// const gasCeilingMultiplier = BigNumber.from(2) -// const checkGasLimit = BigNumber.from(10000000) -// const fallbackGasPrice = gasWei.mul(BigNumber.from('2')) -// const fallbackLinkPrice = linkEth.div(BigNumber.from('2')) -// const maxCheckDataSize = BigNumber.from(1000) -// const maxPerformDataSize = BigNumber.from(1000) -// const maxRevertDataSize = BigNumber.from(1000) -// const maxPerformGas = BigNumber.from(5000000) -// const minUpkeepSpend = BigNumber.from(0) -// const f = 1 -// const offchainVersion = 1 -// const offchainBytes = '0x' -// const zeroAddress = ethers.constants.AddressZero -// const epochAndRound5_1 = -// '0x0000000000000000000000000000000000000000000000000000000000000501' -// -// let logTriggerConfig: string -// -// // ----------------------------------------------------------------------------------------------- -// -// // Smart contract factories -// let linkTokenFactory: LinkTokenFactory -// let mockV3AggregatorFactory: MockV3AggregatorFactory -// let upkeepMockFactory: UpkeepMockFactory -// let upkeepAutoFunderFactory: UpkeepAutoFunderFactory -// let mockArbGasInfoFactory: MockArbGasInfoFactory -// let mockOVMGasPriceOracleFactory: MockOVMGasPriceOracleFactory -// let streamsLookupUpkeepFactory: StreamsLookupUpkeepFactory -// let personas: Personas -// -// // contracts -// let linkToken: LinkToken -// let linkEthFeed: MockV3Aggregator -// let gasPriceFeed: MockV3Aggregator -// let registry: IKeeperRegistry // default registry, used for most tests -// let arbRegistry: IKeeperRegistry // arbitrum registry -// let opRegistry: IKeeperRegistry // optimism registry -// let mgRegistry: IKeeperRegistry // "migrate registry" used in migration tests -// let blankRegistry: IKeeperRegistry // used to test initial configurations -// let mock: UpkeepMock -// let autoFunderUpkeep: UpkeepAutoFunder -// let ltUpkeep: MockContract -// let transcoder: UpkeepTranscoder -// let mockArbGasInfo: MockArbGasInfo -// let mockOVMGasPriceOracle: MockOVMGasPriceOracle -// let streamsLookupUpkeep: StreamsLookupUpkeep -// let automationUtils: AutomationUtils -// -// function now() { -// return Math.floor(Date.now() / 1000) -// } -// -// async function getUpkeepID(tx: ContractTransaction): Promise { -// const receipt = await tx.wait() -// for (const event of receipt.events || []) { -// if ( -// event.args && -// event.eventSignature == 'UpkeepRegistered(uint256,uint32,address)' -// ) { -// return event.args[0] -// } -// } -// throw new Error('could not find upkeep ID in tx event logs') -// } -// -// const getTriggerType = (upkeepId: BigNumber): Trigger => { -// const hexBytes = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) -// const bytes = ethers.utils.arrayify(hexBytes) -// for (let idx = 4; idx < 15; idx++) { -// if (bytes[idx] != 0) { -// return Trigger.CONDITION -// } -// } -// return bytes[15] as Trigger -// } -// -// const encodeConfig = (onchainConfig: OnChainConfig) => { -// return ( -// '0x' + -// automationUtils.interface -// .encodeFunctionData('_onChainConfig', [onchainConfig]) -// .slice(10) -// ) -// } -// -// const encodeBlockTrigger = (conditionalTrigger: ConditionalTrigger) => { -// return ( -// '0x' + -// automationUtils.interface -// .encodeFunctionData('_conditionalTrigger', [conditionalTrigger]) -// .slice(10) -// ) -// } -// -// const encodeLogTrigger = (logTrigger: LogTrigger) => { -// return ( -// '0x' + -// automationUtils.interface -// .encodeFunctionData('_logTrigger', [logTrigger]) -// .slice(10) -// ) -// } -// -// const encodeLog = (log: Log) => { -// return ( -// '0x' + automationUtils.interface.encodeFunctionData('_log', [log]).slice(10) -// ) -// } -// -// const encodeReport = (report: Report) => { -// return ( -// '0x' + -// automationUtils.interface.encodeFunctionData('_report', [report]).slice(10) -// ) -// } -// -// type UpkeepData = { -// Id: BigNumberish -// performGas: BigNumberish -// performData: BytesLike -// trigger: BytesLike -// } -// -// const makeReport = (upkeeps: UpkeepData[]) => { -// const upkeepIds = upkeeps.map((u) => u.Id) -// const performGases = upkeeps.map((u) => u.performGas) -// const triggers = upkeeps.map((u) => u.trigger) -// const performDatas = upkeeps.map((u) => u.performData) -// return encodeReport({ -// fastGasWei: gasWei, -// linkNative: linkEth, -// upkeepIds, -// gasLimits: performGases, -// triggers, -// performDatas, -// }) -// } -// -// const makeLatestBlockReport = async (upkeepsIDs: BigNumberish[]) => { -// const latestBlock = await ethers.provider.getBlock('latest') -// const upkeeps: UpkeepData[] = [] -// for (let i = 0; i < upkeepsIDs.length; i++) { -// upkeeps.push({ -// Id: upkeepsIDs[i], -// performGas, -// trigger: encodeBlockTrigger({ -// blockNum: latestBlock.number, -// blockHash: latestBlock.hash, -// }), -// performData: '0x', -// }) -// } -// return makeReport(upkeeps) -// } -// -// const signReport = ( -// reportContext: string[], -// report: any, -// signers: Wallet[], -// ) => { -// const reportDigest = ethers.utils.keccak256(report) -// const packedArgs = ethers.utils.solidityPack( -// ['bytes32', 'bytes32[3]'], -// [reportDigest, reportContext], -// ) -// const packedDigest = ethers.utils.keccak256(packedArgs) -// -// const signatures = [] -// for (const signer of signers) { -// signatures.push(signer._signingKey().signDigest(packedDigest)) -// } -// const vs = signatures.map((i) => '0' + (i.v - 27).toString(16)).join('') -// return { -// vs: '0x' + vs.padEnd(64, '0'), -// rs: signatures.map((i) => i.r), -// ss: signatures.map((i) => i.s), -// } -// } -// -// const parseUpkeepPerformedLogs = (receipt: ContractReceipt) => { -// const parsedLogs = [] -// for (const rawLog of receipt.logs) { -// try { -// const log = registry.interface.parseLog(rawLog) -// if ( -// log.name == -// registry.interface.events[ -// 'UpkeepPerformed(uint256,bool,uint96,uint256,uint256,bytes)' -// ].name -// ) { -// parsedLogs.push(log as unknown as UpkeepPerformedEvent) -// } -// } catch { -// continue -// } -// } -// return parsedLogs -// } -// -// const parseReorgedUpkeepReportLogs = (receipt: ContractReceipt) => { -// const parsedLogs = [] -// for (const rawLog of receipt.logs) { -// try { -// const log = registry.interface.parseLog(rawLog) -// if ( -// log.name == -// registry.interface.events['ReorgedUpkeepReport(uint256,bytes)'].name -// ) { -// parsedLogs.push(log as unknown as ReorgedUpkeepReportEvent) -// } -// } catch { -// continue -// } -// } -// return parsedLogs -// } -// -// const parseStaleUpkeepReportLogs = (receipt: ContractReceipt) => { -// const parsedLogs = [] -// for (const rawLog of receipt.logs) { -// try { -// const log = registry.interface.parseLog(rawLog) -// if ( -// log.name == -// registry.interface.events['StaleUpkeepReport(uint256,bytes)'].name -// ) { -// parsedLogs.push(log as unknown as StaleUpkeepReportEvent) -// } -// } catch { -// continue -// } -// } -// return parsedLogs -// } -// -// const parseInsufficientFundsUpkeepReportLogs = (receipt: ContractReceipt) => { -// const parsedLogs = [] -// for (const rawLog of receipt.logs) { -// try { -// const log = registry.interface.parseLog(rawLog) -// if ( -// log.name == -// registry.interface.events[ -// 'InsufficientFundsUpkeepReport(uint256,bytes)' -// ].name -// ) { -// parsedLogs.push(log as unknown as InsufficientFundsUpkeepReportEvent) -// } -// } catch { -// continue -// } -// } -// return parsedLogs -// } -// -// const parseCancelledUpkeepReportLogs = (receipt: ContractReceipt) => { -// const parsedLogs = [] -// for (const rawLog of receipt.logs) { -// try { -// const log = registry.interface.parseLog(rawLog) -// if ( -// log.name == -// registry.interface.events['CancelledUpkeepReport(uint256,bytes)'].name -// ) { -// parsedLogs.push(log as unknown as CancelledUpkeepReportEvent) -// } -// } catch { -// continue -// } -// } -// return parsedLogs -// } -// -// describe('KeeperRegistry2_1', () => { -// let owner: Signer -// let keeper1: Signer -// let keeper2: Signer -// let keeper3: Signer -// let keeper4: Signer -// let keeper5: Signer -// let nonkeeper: Signer -// let signer1: Wallet -// let signer2: Wallet -// let signer3: Wallet -// let signer4: Wallet -// let signer5: Wallet -// let admin: Signer -// let payee1: Signer -// let payee2: Signer -// let payee3: Signer -// let payee4: Signer -// let payee5: Signer -// -// let upkeepId: BigNumber // conditional upkeep -// let afUpkeepId: BigNumber // auto funding upkeep -// let logUpkeepId: BigNumber // log trigger upkeepID -// let streamsLookupUpkeepId: BigNumber // streams lookup upkeep -// const numUpkeeps = 4 // see above -// let keeperAddresses: string[] -// let payees: string[] -// let signers: Wallet[] -// let signerAddresses: string[] -// let config: any -// let baseConfig: Parameters -// let upkeepManager: string -// -// before(async () => { -// personas = (await getUsers()).personas -// -// const utilsFactory = await ethers.getContractFactory('AutomationUtils2_1') -// automationUtils = await utilsFactory.deploy() -// -// linkTokenFactory = await ethers.getContractFactory( -// 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', -// ) -// // need full path because there are two contracts with name MockV3Aggregator -// mockV3AggregatorFactory = (await ethers.getContractFactory( -// 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', -// )) as unknown as MockV3AggregatorFactory -// upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') -// upkeepAutoFunderFactory = -// await ethers.getContractFactory('UpkeepAutoFunder') -// mockArbGasInfoFactory = await ethers.getContractFactory('MockArbGasInfo') -// mockOVMGasPriceOracleFactory = await ethers.getContractFactory( -// 'MockOVMGasPriceOracle', -// ) -// streamsLookupUpkeepFactory = await ethers.getContractFactory( -// 'StreamsLookupUpkeep', -// ) -// -// owner = personas.Default -// keeper1 = personas.Carol -// keeper2 = personas.Eddy -// keeper3 = personas.Nancy -// keeper4 = personas.Norbert -// keeper5 = personas.Nick -// nonkeeper = personas.Ned -// admin = personas.Neil -// payee1 = personas.Nelly -// payee2 = personas.Norbert -// payee3 = personas.Nick -// payee4 = personas.Eddy -// payee5 = personas.Carol -// upkeepManager = await personas.Norbert.getAddress() -// // signers -// signer1 = new ethers.Wallet( -// '0x7777777000000000000000000000000000000000000000000000000000000001', -// ) -// signer2 = new ethers.Wallet( -// '0x7777777000000000000000000000000000000000000000000000000000000002', -// ) -// signer3 = new ethers.Wallet( -// '0x7777777000000000000000000000000000000000000000000000000000000003', -// ) -// signer4 = new ethers.Wallet( -// '0x7777777000000000000000000000000000000000000000000000000000000004', -// ) -// signer5 = new ethers.Wallet( -// '0x7777777000000000000000000000000000000000000000000000000000000005', -// ) -// -// keeperAddresses = [ -// await keeper1.getAddress(), -// await keeper2.getAddress(), -// await keeper3.getAddress(), -// await keeper4.getAddress(), -// await keeper5.getAddress(), -// ] -// payees = [ -// await payee1.getAddress(), -// await payee2.getAddress(), -// await payee3.getAddress(), -// await payee4.getAddress(), -// await payee5.getAddress(), -// ] -// signers = [signer1, signer2, signer3, signer4, signer5] -// -// // We append 26 random addresses to keepers, payees and signers to get a system of 31 oracles -// // This allows f value of 1 - 10 -// for (let i = 0; i < 26; i++) { -// keeperAddresses.push(randomAddress()) -// payees.push(randomAddress()) -// signers.push(ethers.Wallet.createRandom()) -// } -// signerAddresses = [] -// for (const signer of signers) { -// signerAddresses.push(await signer.getAddress()) -// } -// -// logTriggerConfig = -// '0x' + -// automationUtils.interface -// .encodeFunctionData('_logTriggerConfig', [ -// { -// contractAddress: randomAddress(), -// filterSelector: 0, -// topic0: ethers.utils.randomBytes(32), -// topic1: ethers.utils.randomBytes(32), -// topic2: ethers.utils.randomBytes(32), -// topic3: ethers.utils.randomBytes(32), -// }, -// ]) -// .slice(10) -// }) -// -// const linkForGas = ( -// upkeepGasSpent: BigNumber, -// gasOverhead: BigNumber, -// gasMultiplier: BigNumber, -// premiumPPB: BigNumber, -// flatFee: BigNumber, -// l1CostWei?: BigNumber, -// numUpkeepsBatch?: BigNumber, -// ) => { -// l1CostWei = l1CostWei === undefined ? BigNumber.from(0) : l1CostWei -// numUpkeepsBatch = -// numUpkeepsBatch === undefined ? BigNumber.from(1) : numUpkeepsBatch -// -// const gasSpent = gasOverhead.add(BigNumber.from(upkeepGasSpent)) -// const base = gasWei -// .mul(gasMultiplier) -// .mul(gasSpent) -// .mul(linkDivisibility) -// .div(linkEth) -// const l1Fee = l1CostWei -// .mul(gasMultiplier) -// .div(numUpkeepsBatch) -// .mul(linkDivisibility) -// .div(linkEth) -// const gasPayment = base.add(l1Fee) -// -// const premium = gasWei -// .mul(gasMultiplier) -// .mul(upkeepGasSpent) -// .add(l1CostWei.mul(gasMultiplier).div(numUpkeepsBatch)) -// .mul(linkDivisibility) -// .div(linkEth) -// .mul(premiumPPB) -// .div(paymentPremiumBase) -// .add(BigNumber.from(flatFee).mul('1000000000000')) -// -// return { -// total: gasPayment.add(premium), -// gasPaymemnt: gasPayment, -// premium, -// } -// } -// -// const verifyMaxPayment = async ( -// registry: IKeeperRegistry, -// l1CostWei?: BigNumber, -// ) => { -// type TestCase = { -// name: string -// multiplier: number -// gas: number -// premium: number -// flatFee: number -// } -// -// const tests: TestCase[] = [ -// { -// name: 'no fees', -// multiplier: 1, -// gas: 100000, -// premium: 0, -// flatFee: 0, -// }, -// { -// name: 'basic fees', -// multiplier: 1, -// gas: 100000, -// premium: 250000000, -// flatFee: 1000000, -// }, -// { -// name: 'max fees', -// multiplier: 3, -// gas: 10000000, -// premium: 250000000, -// flatFee: 1000000, -// }, -// ] -// -// const fPlusOne = BigNumber.from(f + 1) -// const totalConditionalOverhead = registryConditionalOverhead -// .add(registryPerSignerGasOverhead.mul(fPlusOne)) -// .add(registryPerPerformByteGasOverhead.mul(maxPerformDataSize)) -// const totalLogOverhead = registryLogOverhead -// .add(registryPerSignerGasOverhead.mul(fPlusOne)) -// .add(registryPerPerformByteGasOverhead.mul(maxPerformDataSize)) -// -// for (const test of tests) { -// await registry.connect(owner).setConfig( -// signerAddresses, -// keeperAddresses, -// f, -// encodeConfig({ -// paymentPremiumPPB: test.premium, -// flatFeeMicroLink: test.flatFee, -// checkGasLimit, -// stalenessSeconds, -// gasCeilingMultiplier: test.multiplier, -// minUpkeepSpend, -// maxCheckDataSize, -// maxPerformDataSize, -// maxRevertDataSize, -// maxPerformGas, -// fallbackGasPrice, -// fallbackLinkPrice, -// transcoder: transcoder.address, -// registrars: [], -// upkeepPrivilegeManager: upkeepManager, -// }), -// offchainVersion, -// offchainBytes, -// ) -// -// const conditionalPrice = await registry.getMaxPaymentForGas( -// Trigger.CONDITION, -// test.gas, -// ) -// expect(conditionalPrice).to.equal( -// linkForGas( -// BigNumber.from(test.gas), -// totalConditionalOverhead, -// BigNumber.from(test.multiplier), -// BigNumber.from(test.premium), -// BigNumber.from(test.flatFee), -// l1CostWei, -// ).total, -// ) -// -// const logPrice = await registry.getMaxPaymentForGas(Trigger.LOG, test.gas) -// expect(logPrice).to.equal( -// linkForGas( -// BigNumber.from(test.gas), -// totalLogOverhead, -// BigNumber.from(test.multiplier), -// BigNumber.from(test.premium), -// BigNumber.from(test.flatFee), -// l1CostWei, -// ).total, -// ) -// } -// } -// -// const verifyConsistentAccounting = async ( -// maxAllowedSpareChange: BigNumber, -// ) => { -// const expectedLinkBalance = (await registry.getState()).state -// .expectedLinkBalance -// const linkTokenBalance = await linkToken.balanceOf(registry.address) -// const upkeepIdBalance = (await registry.getUpkeep(upkeepId)).balance -// let totalKeeperBalance = BigNumber.from(0) -// for (let i = 0; i < keeperAddresses.length; i++) { -// totalKeeperBalance = totalKeeperBalance.add( -// (await registry.getTransmitterInfo(keeperAddresses[i])).balance, -// ) -// } -// const ownerBalance = (await registry.getState()).state.ownerLinkBalance -// assert.isTrue(expectedLinkBalance.eq(linkTokenBalance)) -// assert.isTrue( -// upkeepIdBalance -// .add(totalKeeperBalance) -// .add(ownerBalance) -// .lte(expectedLinkBalance), -// ) -// assert.isTrue( -// expectedLinkBalance -// .sub(upkeepIdBalance) -// .sub(totalKeeperBalance) -// .sub(ownerBalance) -// .lte(maxAllowedSpareChange), -// ) -// } -// -// interface GetTransmitTXOptions { -// numSigners?: number -// startingSignerIndex?: number -// gasLimit?: BigNumberish -// gasPrice?: BigNumberish -// performGas?: BigNumberish -// performData?: string -// checkBlockNum?: number -// checkBlockHash?: string -// logBlockHash?: BytesLike -// txHash?: BytesLike -// logIndex?: number -// timestamp?: number -// } -// -// const getTransmitTx = async ( -// registry: IKeeperRegistry, -// transmitter: Signer, -// upkeepIds: BigNumber[], -// overrides: GetTransmitTXOptions = {}, -// ) => { -// const latestBlock = await ethers.provider.getBlock('latest') -// const configDigest = (await registry.getState()).state.latestConfigDigest -// const config = { -// numSigners: f + 1, -// startingSignerIndex: 0, -// performData: '0x', -// performGas, -// checkBlockNum: latestBlock.number, -// checkBlockHash: latestBlock.hash, -// logIndex: 0, -// txHash: undefined, // assigned uniquely below -// logBlockHash: undefined, // assigned uniquely below -// timestamp: now(), -// gasLimit: undefined, -// gasPrice: undefined, -// } -// Object.assign(config, overrides) -// const upkeeps: UpkeepData[] = [] -// for (let i = 0; i < upkeepIds.length; i++) { -// let trigger: string -// switch (getTriggerType(upkeepIds[i])) { -// case Trigger.CONDITION: -// trigger = encodeBlockTrigger({ -// blockNum: config.checkBlockNum, -// blockHash: config.checkBlockHash, -// }) -// break -// case Trigger.LOG: -// trigger = encodeLogTrigger({ -// logBlockHash: config.logBlockHash || ethers.utils.randomBytes(32), -// txHash: config.txHash || ethers.utils.randomBytes(32), -// logIndex: config.logIndex, -// blockNum: config.checkBlockNum, -// blockHash: config.checkBlockHash, -// }) -// break -// } -// upkeeps.push({ -// Id: upkeepIds[i], -// performGas: config.performGas, -// trigger, -// performData: config.performData, -// }) -// } -// -// const report = makeReport(upkeeps) -// const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] -// const sigs = signReport( -// reportContext, -// report, -// signers.slice( -// config.startingSignerIndex, -// config.startingSignerIndex + config.numSigners, -// ), -// ) -// -// type txOverride = { -// gasLimit?: BigNumberish | Promise -// gasPrice?: BigNumberish | Promise -// } -// const txOverrides: txOverride = {} -// if (config.gasLimit) { -// txOverrides.gasLimit = config.gasLimit -// } -// if (config.gasPrice) { -// txOverrides.gasPrice = config.gasPrice -// } -// -// return registry -// .connect(transmitter) -// .transmit( -// [configDigest, epochAndRound5_1, emptyBytes32], -// report, -// sigs.rs, -// sigs.ss, -// sigs.vs, -// txOverrides, -// ) -// } -// -// const getTransmitTxWithReport = async ( -// registry: IKeeperRegistry, -// transmitter: Signer, -// report: BytesLike, -// ) => { -// const configDigest = (await registry.getState()).state.latestConfigDigest -// const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] -// const sigs = signReport(reportContext, report, signers.slice(0, f + 1)) -// -// return registry -// .connect(transmitter) -// .transmit( -// [configDigest, epochAndRound5_1, emptyBytes32], -// report, -// sigs.rs, -// sigs.ss, -// sigs.vs, -// ) -// } -// -// const setup = async () => { -// linkToken = await linkTokenFactory.connect(owner).deploy() -// gasPriceFeed = await mockV3AggregatorFactory -// .connect(owner) -// .deploy(0, gasWei) -// linkEthFeed = await mockV3AggregatorFactory -// .connect(owner) -// .deploy(9, linkEth) -// const upkeepTranscoderFactory = await ethers.getContractFactory( -// 'UpkeepTranscoder4_0', -// ) -// transcoder = await upkeepTranscoderFactory.connect(owner).deploy() -// mockArbGasInfo = await mockArbGasInfoFactory.connect(owner).deploy() -// mockOVMGasPriceOracle = await mockOVMGasPriceOracleFactory -// .connect(owner) -// .deploy() -// streamsLookupUpkeep = await streamsLookupUpkeepFactory -// .connect(owner) -// .deploy( -// BigNumber.from('10000'), -// BigNumber.from('100'), -// false /* useArbBlock */, -// true /* staging */, -// false /* verify mercury response */, -// ) -// -// const arbOracleCode = await ethers.provider.send('eth_getCode', [ -// mockArbGasInfo.address, -// ]) -// await ethers.provider.send('hardhat_setCode', [ -// '0x000000000000000000000000000000000000006C', -// arbOracleCode, -// ]) -// -// const optOracleCode = await ethers.provider.send('eth_getCode', [ -// mockOVMGasPriceOracle.address, -// ]) -// await ethers.provider.send('hardhat_setCode', [ -// '0x420000000000000000000000000000000000000F', -// optOracleCode, -// ]) -// -// const mockArbSys = await new MockArbSysFactory(owner).deploy() -// const arbSysCode = await ethers.provider.send('eth_getCode', [ -// mockArbSys.address, -// ]) -// await ethers.provider.send('hardhat_setCode', [ -// '0x0000000000000000000000000000000000000064', -// arbSysCode, -// ]) -// -// config = { -// paymentPremiumPPB, -// flatFeeMicroLink, -// checkGasLimit, -// stalenessSeconds, -// gasCeilingMultiplier, -// minUpkeepSpend, -// maxCheckDataSize, -// maxPerformDataSize, -// maxRevertDataSize, -// maxPerformGas, -// fallbackGasPrice, -// fallbackLinkPrice, -// transcoder: transcoder.address, -// registrars: [], -// upkeepPrivilegeManager: upkeepManager, -// } -// -// baseConfig = [ -// signerAddresses, -// keeperAddresses, -// f, -// encodeConfig(config), -// offchainVersion, -// offchainBytes, -// ] -// -// registry = await deployRegistry21( -// owner, -// Mode.DEFAULT, -// linkToken.address, -// linkEthFeed.address, -// gasPriceFeed.address, -// ) -// -// arbRegistry = await deployRegistry21( -// owner, -// Mode.ARBITRUM, -// linkToken.address, -// linkEthFeed.address, -// gasPriceFeed.address, -// ) -// -// opRegistry = await deployRegistry21( -// owner, -// Mode.OPTIMISM, -// linkToken.address, -// linkEthFeed.address, -// gasPriceFeed.address, -// ) -// -// mgRegistry = await deployRegistry21( -// owner, -// Mode.DEFAULT, -// linkToken.address, -// linkEthFeed.address, -// gasPriceFeed.address, -// ) -// -// blankRegistry = await deployRegistry21( -// owner, -// Mode.DEFAULT, -// linkToken.address, -// linkEthFeed.address, -// gasPriceFeed.address, -// ) -// -// registryConditionalOverhead = await registry.getConditionalGasOverhead() -// registryLogOverhead = await registry.getLogGasOverhead() -// registryPerSignerGasOverhead = await registry.getPerSignerGasOverhead() -// registryPerPerformByteGasOverhead = -// await registry.getPerPerformByteGasOverhead() -// cancellationDelay = (await registry.getCancellationDelay()).toNumber() -// -// for (const reg of [registry, arbRegistry, opRegistry, mgRegistry]) { -// await reg.connect(owner).setConfig(...baseConfig) -// await reg.connect(owner).setPayees(payees) -// await linkToken.connect(admin).approve(reg.address, toWei('1000')) -// await linkToken.connect(owner).approve(reg.address, toWei('1000')) -// } -// -// mock = await upkeepMockFactory.deploy() -// await linkToken -// .connect(owner) -// .transfer(await admin.getAddress(), toWei('1000')) -// let tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// upkeepId = await getUpkeepID(tx) -// -// autoFunderUpkeep = await upkeepAutoFunderFactory -// .connect(owner) -// .deploy(linkToken.address, registry.address) -// tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](autoFunderUpkeep.address, performGas, autoFunderUpkeep.address, randomBytes, '0x') -// afUpkeepId = await getUpkeepID(tx) -// -// ltUpkeep = await deployMockContract(owner, ILogAutomationactory.abi) -// tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,uint8,bytes,bytes,bytes)' -// ](ltUpkeep.address, performGas, await admin.getAddress(), Trigger.LOG, '0x', logTriggerConfig, emptyBytes) -// logUpkeepId = await getUpkeepID(tx) -// -// await autoFunderUpkeep.setUpkeepId(afUpkeepId) -// // Give enough funds for upkeep as well as to the upkeep contract -// await linkToken -// .connect(owner) -// .transfer(autoFunderUpkeep.address, toWei('1000')) -// -// tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](streamsLookupUpkeep.address, performGas, await admin.getAddress(), randomBytes, '0x') -// streamsLookupUpkeepId = await getUpkeepID(tx) -// } -// -// const getMultipleUpkeepsDeployedAndFunded = async ( -// numPassingConditionalUpkeeps: number, -// numPassingLogUpkeeps: number, -// numFailingUpkeeps: number, -// ) => { -// const passingConditionalUpkeepIds = [] -// const passingLogUpkeepIds = [] -// const failingUpkeepIds = [] -// for (let i = 0; i < numPassingConditionalUpkeeps; i++) { -// const mock = await upkeepMockFactory.deploy() -// await mock.setCanPerform(true) -// await mock.setPerformGasToBurn(BigNumber.from('0')) -// const tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// const condUpkeepId = await getUpkeepID(tx) -// passingConditionalUpkeepIds.push(condUpkeepId) -// -// // Add funds to passing upkeeps -// await registry.connect(admin).addFunds(condUpkeepId, toWei('100')) -// } -// for (let i = 0; i < numPassingLogUpkeeps; i++) { -// const mock = await upkeepMockFactory.deploy() -// await mock.setCanPerform(true) -// await mock.setPerformGasToBurn(BigNumber.from('0')) -// const tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,uint8,bytes,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), Trigger.LOG, '0x', logTriggerConfig, emptyBytes) -// const logUpkeepId = await getUpkeepID(tx) -// passingLogUpkeepIds.push(logUpkeepId) -// -// // Add funds to passing upkeeps -// await registry.connect(admin).addFunds(logUpkeepId, toWei('100')) -// } -// for (let i = 0; i < numFailingUpkeeps; i++) { -// const mock = await upkeepMockFactory.deploy() -// await mock.setCanPerform(true) -// await mock.setPerformGasToBurn(BigNumber.from('0')) -// const tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// const failingUpkeepId = await getUpkeepID(tx) -// failingUpkeepIds.push(failingUpkeepId) -// } -// return { -// passingConditionalUpkeepIds, -// passingLogUpkeepIds, -// failingUpkeepIds, -// } -// } -// -// beforeEach(async () => { -// await loadFixture(setup) -// }) -// -// describe('#transmit', () => { -// const fArray = [1, 5, 10] -// -// it('reverts when registry is paused', async () => { -// await registry.connect(owner).pause() -// await evmRevert( -// getTransmitTx(registry, keeper1, [upkeepId]), -// 'RegistryPaused()', -// ) -// }) -// -// it('reverts when called by non active transmitter', async () => { -// await evmRevert( -// getTransmitTx(registry, payee1, [upkeepId]), -// 'OnlyActiveTransmitters()', -// ) -// }) -// -// it('reverts when report data lengths mismatches', async () => { -// const upkeepIds = [] -// const gasLimits: BigNumber[] = [] -// const triggers: string[] = [] -// const performDatas = [] -// -// upkeepIds.push(upkeepId) -// gasLimits.push(performGas) -// triggers.push('0x') -// performDatas.push('0x') -// // Push an extra perform data -// performDatas.push('0x') -// -// const report = encodeReport({ -// fastGasWei: 0, -// linkNative: 0, -// upkeepIds, -// gasLimits, -// triggers, -// performDatas, -// }) -// -// await evmRevert( -// getTransmitTxWithReport(registry, keeper1, report), -// 'InvalidReport()', -// ) -// }) -// -// it('returns early when invalid upkeepIds are included in report', async () => { -// const tx = await getTransmitTx(registry, keeper1, [ -// upkeepId.add(BigNumber.from('1')), -// ]) -// -// const receipt = await tx.wait() -// const cancelledUpkeepReportLogs = parseCancelledUpkeepReportLogs(receipt) -// // exactly 1 CancelledUpkeepReport log should be emitted -// assert.equal(cancelledUpkeepReportLogs.length, 1) -// }) -// -// it('returns early when upkeep has insufficient funds', async () => { -// const tx = await getTransmitTx(registry, keeper1, [upkeepId]) -// const receipt = await tx.wait() -// const insufficientFundsUpkeepReportLogs = -// parseInsufficientFundsUpkeepReportLogs(receipt) -// // exactly 1 InsufficientFundsUpkeepReportLogs log should be emitted -// assert.equal(insufficientFundsUpkeepReportLogs.length, 1) -// }) -// -// it('permits retrying log triggers after funds are added', async () => { -// const txHash = ethers.utils.randomBytes(32) -// let tx = await getTransmitTx(registry, keeper1, [logUpkeepId], { -// txHash, -// logIndex: 0, -// }) -// let receipt = await tx.wait() -// const insufficientFundsLogs = -// parseInsufficientFundsUpkeepReportLogs(receipt) -// assert.equal(insufficientFundsLogs.length, 1) -// registry.connect(admin).addFunds(logUpkeepId, toWei('100')) -// tx = await getTransmitTx(registry, keeper1, [logUpkeepId], { -// txHash, -// logIndex: 0, -// }) -// receipt = await tx.wait() -// const performedLogs = parseUpkeepPerformedLogs(receipt) -// assert.equal(performedLogs.length, 1) -// }) -// -// context('When the upkeep is funded', async () => { -// beforeEach(async () => { -// // Fund the upkeep -// await Promise.all([ -// registry.connect(admin).addFunds(upkeepId, toWei('100')), -// registry.connect(admin).addFunds(logUpkeepId, toWei('100')), -// ]) -// }) -// -// it('handles duplicate upkeepIDs', async () => { -// const tests: [string, BigNumber, number, number][] = [ -// // [name, upkeep, num stale, num performed] -// ['conditional', upkeepId, 1, 1], // checkBlocks must be sequential -// ['log-trigger', logUpkeepId, 0, 2], // logs are deduped based on the "trigger ID" -// ] -// for (const [type, id, nStale, nPerformed] of tests) { -// const tx = await getTransmitTx(registry, keeper1, [id, id]) -// const receipt = await tx.wait() -// const staleUpkeepReport = parseStaleUpkeepReportLogs(receipt) -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// assert.equal( -// staleUpkeepReport.length, -// nStale, -// `wrong log count for ${type} upkeep`, -// ) -// assert.equal( -// upkeepPerformedLogs.length, -// nPerformed, -// `wrong log count for ${type} upkeep`, -// ) -// } -// }) -// -// it('handles duplicate log triggers', async () => { -// const logBlockHash = ethers.utils.randomBytes(32) -// const txHash = ethers.utils.randomBytes(32) -// const logIndex = 0 -// const expectedDedupKey = ethers.utils.solidityKeccak256( -// ['uint256', 'bytes32', 'bytes32', 'uint32'], -// [logUpkeepId, logBlockHash, txHash, logIndex], -// ) -// assert.isFalse(await registry.hasDedupKey(expectedDedupKey)) -// const tx = await getTransmitTx( -// registry, -// keeper1, -// [logUpkeepId, logUpkeepId], -// { logBlockHash, txHash, logIndex }, // will result in the same dedup key -// ) -// const receipt = await tx.wait() -// const staleUpkeepReport = parseStaleUpkeepReportLogs(receipt) -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// assert.equal(staleUpkeepReport.length, 1) -// assert.equal(upkeepPerformedLogs.length, 1) -// assert.isTrue(await registry.hasDedupKey(expectedDedupKey)) -// await expect(tx) -// .to.emit(registry, 'DedupKeyAdded') -// .withArgs(expectedDedupKey) -// }) -// -// it('returns early when check block number is less than last perform (block)', async () => { -// // First perform an upkeep to put last perform block number on upkeep state -// const tx = await getTransmitTx(registry, keeper1, [upkeepId]) -// await tx.wait() -// const lastPerformed = (await registry.getUpkeep(upkeepId)) -// .lastPerformedBlockNumber -// const lastPerformBlock = await ethers.provider.getBlock(lastPerformed) -// assert.equal(lastPerformed.toString(), tx.blockNumber?.toString()) -// // Try to transmit a report which has checkBlockNumber = lastPerformed-1, should result in stale report -// const transmitTx = await getTransmitTx(registry, keeper1, [upkeepId], { -// checkBlockNum: lastPerformBlock.number - 1, -// checkBlockHash: lastPerformBlock.parentHash, -// }) -// const receipt = await transmitTx.wait() -// const staleUpkeepReportLogs = parseStaleUpkeepReportLogs(receipt) -// // exactly 1 StaleUpkeepReportLogs log should be emitted -// assert.equal(staleUpkeepReportLogs.length, 1) -// }) -// -// it('handles case when check block hash does not match', async () => { -// const tests: [string, BigNumber][] = [ -// ['conditional', upkeepId], -// ['log-trigger', logUpkeepId], -// ] -// for (const [type, id] of tests) { -// const latestBlock = await ethers.provider.getBlock('latest') -// // Try to transmit a report which has incorrect checkBlockHash -// const tx = await getTransmitTx(registry, keeper1, [id], { -// checkBlockNum: latestBlock.number - 1, -// checkBlockHash: latestBlock.hash, // should be latestBlock.parentHash -// }) -// -// const receipt = await tx.wait() -// const reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) -// // exactly 1 ReorgedUpkeepReportLogs log should be emitted -// assert.equal( -// reorgedUpkeepReportLogs.length, -// 1, -// `wrong log count for ${type} upkeep`, -// ) -// } -// }) -// -// it('handles case when check block number is older than 256 blocks', async () => { -// for (let i = 0; i < 256; i++) { -// await ethers.provider.send('evm_mine', []) -// } -// const tests: [string, BigNumber][] = [ -// ['conditional', upkeepId], -// ['log-trigger', logUpkeepId], -// ] -// for (const [type, id] of tests) { -// const latestBlock = await ethers.provider.getBlock('latest') -// const old = await ethers.provider.getBlock(latestBlock.number - 256) -// // Try to transmit a report which has incorrect checkBlockHash -// const tx = await getTransmitTx(registry, keeper1, [id], { -// checkBlockNum: old.number, -// checkBlockHash: old.hash, -// }) -// -// const receipt = await tx.wait() -// const reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) -// // exactly 1 ReorgedUpkeepReportLogs log should be emitted -// assert.equal( -// reorgedUpkeepReportLogs.length, -// 1, -// `wrong log count for ${type} upkeep`, -// ) -// } -// }) -// -// it('allows bypassing reorg protection with empty blockhash', async () => { -// const tests: [string, BigNumber][] = [ -// ['conditional', upkeepId], -// ['log-trigger', logUpkeepId], -// ] -// for (const [type, id] of tests) { -// const latestBlock = await ethers.provider.getBlock('latest') -// const tx = await getTransmitTx(registry, keeper1, [id], { -// checkBlockNum: latestBlock.number, -// checkBlockHash: emptyBytes32, -// }) -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// assert.equal( -// upkeepPerformedLogs.length, -// 1, -// `wrong log count for ${type} upkeep`, -// ) -// } -// }) -// -// it('allows very old trigger block numbers when bypassing reorg protection with empty blockhash', async () => { -// // mine enough blocks so that blockhash(1) is unavailable -// for (let i = 0; i <= 256; i++) { -// await ethers.provider.send('evm_mine', []) -// } -// const tests: [string, BigNumber][] = [ -// ['conditional', upkeepId], -// ['log-trigger', logUpkeepId], -// ] -// for (const [type, id] of tests) { -// const tx = await getTransmitTx(registry, keeper1, [id], { -// checkBlockNum: 1, -// checkBlockHash: emptyBytes32, -// }) -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// assert.equal( -// upkeepPerformedLogs.length, -// 1, -// `wrong log count for ${type} upkeep`, -// ) -// } -// }) -// -// it('returns early when future block number is provided as trigger, irrespective of blockhash being present', async () => { -// const tests: [string, BigNumber][] = [ -// ['conditional', upkeepId], -// ['log-trigger', logUpkeepId], -// ] -// for (const [type, id] of tests) { -// const latestBlock = await ethers.provider.getBlock('latest') -// -// // Should fail when blockhash is empty -// let tx = await getTransmitTx(registry, keeper1, [id], { -// checkBlockNum: latestBlock.number + 100, -// checkBlockHash: emptyBytes32, -// }) -// let receipt = await tx.wait() -// let reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) -// // exactly 1 ReorgedUpkeepReportLogs log should be emitted -// assert.equal( -// reorgedUpkeepReportLogs.length, -// 1, -// `wrong log count for ${type} upkeep`, -// ) -// -// // Should also fail when blockhash is not empty -// tx = await getTransmitTx(registry, keeper1, [id], { -// checkBlockNum: latestBlock.number + 100, -// checkBlockHash: latestBlock.hash, -// }) -// receipt = await tx.wait() -// reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) -// // exactly 1 ReorgedUpkeepReportLogs log should be emitted -// assert.equal( -// reorgedUpkeepReportLogs.length, -// 1, -// `wrong log count for ${type} upkeep`, -// ) -// } -// }) -// -// it('returns early when upkeep is cancelled and cancellation delay has gone', async () => { -// const latestBlockReport = await makeLatestBlockReport([upkeepId]) -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// for (let i = 0; i < cancellationDelay; i++) { -// await ethers.provider.send('evm_mine', []) -// } -// -// const tx = await getTransmitTxWithReport( -// registry, -// keeper1, -// latestBlockReport, -// ) -// -// const receipt = await tx.wait() -// const cancelledUpkeepReportLogs = -// parseCancelledUpkeepReportLogs(receipt) -// // exactly 1 CancelledUpkeepReport log should be emitted -// assert.equal(cancelledUpkeepReportLogs.length, 1) -// }) -// -// it('does not revert if the target cannot execute', async () => { -// await mock.setCanPerform(false) -// const tx = await getTransmitTx(registry, keeper1, [upkeepId]) -// -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const success = upkeepPerformedLog.args.success -// assert.equal(success, false) -// }) -// -// it('does not revert if the target runs out of gas', async () => { -// await mock.setCanPerform(false) -// -// const tx = await getTransmitTx(registry, keeper1, [upkeepId], { -// performGas: 10, // too little gas -// }) -// -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const success = upkeepPerformedLog.args.success -// assert.equal(success, false) -// }) -// -// it('reverts if not enough gas supplied', async () => { -// await evmRevert( -// getTransmitTx(registry, keeper1, [upkeepId], { -// gasLimit: performGas, -// }), -// ) -// }) -// -// it('executes the data passed to the registry', async () => { -// await mock.setCanPerform(true) -// -// const tx = await getTransmitTx(registry, keeper1, [upkeepId], { -// performData: randomBytes, -// }) -// const receipt = await tx.wait() -// -// const upkeepPerformedWithABI = [ -// 'event UpkeepPerformedWith(bytes upkeepData)', -// ] -// const iface = new ethers.utils.Interface(upkeepPerformedWithABI) -// const parsedLogs = [] -// for (let i = 0; i < receipt.logs.length; i++) { -// const log = receipt.logs[i] -// try { -// parsedLogs.push(iface.parseLog(log)) -// } catch (e) { -// // ignore log -// } -// } -// assert.equal(parsedLogs.length, 1) -// assert.equal(parsedLogs[0].args.upkeepData, randomBytes) -// }) -// -// it('uses actual execution price for payment and premium calculation', async () => { -// // Actual multiplier is 2, but we set gasPrice to be 1x gasWei -// const gasPrice = gasWei.mul(BigNumber.from('1')) -// await mock.setCanPerform(true) -// const registryPremiumBefore = (await registry.getState()).state -// .totalPremium -// const tx = await getTransmitTx(registry, keeper1, [upkeepId], { -// gasPrice, -// }) -// const receipt = await tx.wait() -// const registryPremiumAfter = (await registry.getState()).state -// .totalPremium -// const premium = registryPremiumAfter.sub(registryPremiumBefore) -// -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const gasUsed = upkeepPerformedLog.args.gasUsed -// const gasOverhead = upkeepPerformedLog.args.gasOverhead -// const totalPayment = upkeepPerformedLog.args.totalPayment -// -// assert.equal( -// linkForGas( -// gasUsed, -// gasOverhead, -// BigNumber.from('1'), // Not the config multiplier, but the actual gas used -// paymentPremiumPPB, -// flatFeeMicroLink, -// ).total.toString(), -// totalPayment.toString(), -// ) -// -// assert.equal( -// linkForGas( -// gasUsed, -// gasOverhead, -// BigNumber.from('1'), // Not the config multiplier, but the actual gas used -// paymentPremiumPPB, -// flatFeeMicroLink, -// ).premium.toString(), -// premium.toString(), -// ) -// }) -// -// it('only pays at a rate up to the gas ceiling [ @skip-coverage ]', async () => { -// // Actual multiplier is 2, but we set gasPrice to be 10x -// const gasPrice = gasWei.mul(BigNumber.from('10')) -// await mock.setCanPerform(true) -// -// const tx = await getTransmitTx(registry, keeper1, [upkeepId], { -// gasPrice, -// }) -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const gasUsed = upkeepPerformedLog.args.gasUsed -// const gasOverhead = upkeepPerformedLog.args.gasOverhead -// const totalPayment = upkeepPerformedLog.args.totalPayment -// -// assert.equal( -// linkForGas( -// gasUsed, -// gasOverhead, -// gasCeilingMultiplier, // Should be same with exisitng multiplier -// paymentPremiumPPB, -// flatFeeMicroLink, -// ).total.toString(), -// totalPayment.toString(), -// ) -// }) -// -// it('correctly accounts for l payment', async () => { -// await mock.setCanPerform(true) -// // Same as MockArbGasInfo.sol -// const l1CostWeiArb = BigNumber.from(1000000) -// -// let tx = await arbRegistry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// const testUpkeepId = await getUpkeepID(tx) -// await arbRegistry.connect(owner).addFunds(testUpkeepId, toWei('100')) -// -// // Do the thing -// tx = await getTransmitTx( -// arbRegistry, -// keeper1, -// [testUpkeepId], -// -// { gasPrice: gasWei.mul('5') }, // High gas price so that it gets capped -// ) -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const gasUsed = upkeepPerformedLog.args.gasUsed -// const gasOverhead = upkeepPerformedLog.args.gasOverhead -// const totalPayment = upkeepPerformedLog.args.totalPayment -// -// assert.equal( -// linkForGas( -// gasUsed, -// gasOverhead, -// gasCeilingMultiplier, -// paymentPremiumPPB, -// flatFeeMicroLink, -// l1CostWeiArb.div(gasCeilingMultiplier), // Dividing by gasCeilingMultiplier as it gets multiplied later -// ).total.toString(), -// totalPayment.toString(), -// ) -// }) -// -// itMaybe('can self fund', async () => { -// const maxPayment = await registry.getMaxPaymentForGas( -// Trigger.CONDITION, -// performGas, -// ) -// -// // First set auto funding amount to 0 and verify that balance is deducted upon performUpkeep -// let initialBalance = toWei('100') -// await registry.connect(owner).addFunds(afUpkeepId, initialBalance) -// await autoFunderUpkeep.setAutoFundLink(0) -// await autoFunderUpkeep.setIsEligible(true) -// await getTransmitTx(registry, keeper1, [afUpkeepId]) -// -// let postUpkeepBalance = (await registry.getUpkeep(afUpkeepId)).balance -// assert.isTrue(postUpkeepBalance.lt(initialBalance)) // Balance should be deducted -// assert.isTrue(postUpkeepBalance.gte(initialBalance.sub(maxPayment))) // Balance should not be deducted more than maxPayment -// -// // Now set auto funding amount to 100 wei and verify that the balance increases -// initialBalance = postUpkeepBalance -// const autoTopupAmount = toWei('100') -// await autoFunderUpkeep.setAutoFundLink(autoTopupAmount) -// await autoFunderUpkeep.setIsEligible(true) -// await getTransmitTx(registry, keeper1, [afUpkeepId]) -// -// postUpkeepBalance = (await registry.getUpkeep(afUpkeepId)).balance -// // Balance should increase by autoTopupAmount and decrease by max maxPayment -// assert.isTrue( -// postUpkeepBalance.gte( -// initialBalance.add(autoTopupAmount).sub(maxPayment), -// ), -// ) -// }) -// -// it('can self cancel', async () => { -// await registry.connect(owner).addFunds(afUpkeepId, toWei('100')) -// -// await autoFunderUpkeep.setIsEligible(true) -// await autoFunderUpkeep.setShouldCancel(true) -// -// let registration = await registry.getUpkeep(afUpkeepId) -// const oldExpiration = registration.maxValidBlocknumber -// -// // Do the thing -// await getTransmitTx(registry, keeper1, [afUpkeepId]) -// -// // Verify upkeep gets cancelled -// registration = await registry.getUpkeep(afUpkeepId) -// const newExpiration = registration.maxValidBlocknumber -// assert.isTrue(newExpiration.lt(oldExpiration)) -// }) -// -// it('reverts when configDigest mismatches', async () => { -// const report = await makeLatestBlockReport([upkeepId]) -// const reportContext = [emptyBytes32, epochAndRound5_1, emptyBytes32] // wrong config digest -// const sigs = signReport(reportContext, report, signers.slice(0, f + 1)) -// await evmRevert( -// registry -// .connect(keeper1) -// .transmit( -// [reportContext[0], reportContext[1], reportContext[2]], -// report, -// sigs.rs, -// sigs.ss, -// sigs.vs, -// ), -// 'ConfigDigestMismatch()', -// ) -// }) -// -// it('reverts with incorrect number of signatures', async () => { -// const configDigest = (await registry.getState()).state -// .latestConfigDigest -// const report = await makeLatestBlockReport([upkeepId]) -// const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest -// const sigs = signReport(reportContext, report, signers.slice(0, f + 2)) -// await evmRevert( -// registry -// .connect(keeper1) -// .transmit( -// [reportContext[0], reportContext[1], reportContext[2]], -// report, -// sigs.rs, -// sigs.ss, -// sigs.vs, -// ), -// 'IncorrectNumberOfSignatures()', -// ) -// }) -// -// it('reverts with invalid signature for inactive signers', async () => { -// const configDigest = (await registry.getState()).state -// .latestConfigDigest -// const report = await makeLatestBlockReport([upkeepId]) -// const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest -// const sigs = signReport(reportContext, report, [ -// new ethers.Wallet(ethers.Wallet.createRandom()), -// new ethers.Wallet(ethers.Wallet.createRandom()), -// ]) -// await evmRevert( -// registry -// .connect(keeper1) -// .transmit( -// [reportContext[0], reportContext[1], reportContext[2]], -// report, -// sigs.rs, -// sigs.ss, -// sigs.vs, -// ), -// 'OnlyActiveSigners()', -// ) -// }) -// -// it('reverts with invalid signature for duplicated signers', async () => { -// const configDigest = (await registry.getState()).state -// .latestConfigDigest -// const report = await makeLatestBlockReport([upkeepId]) -// const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest -// const sigs = signReport(reportContext, report, [signer1, signer1]) -// await evmRevert( -// registry -// .connect(keeper1) -// .transmit( -// [reportContext[0], reportContext[1], reportContext[2]], -// report, -// sigs.rs, -// sigs.ss, -// sigs.vs, -// ), -// 'DuplicateSigners()', -// ) -// }) -// -// itMaybe( -// 'has a large enough gas overhead to cover upkeep that use all its gas [ @skip-coverage ]', -// async () => { -// await registry.connect(owner).setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// 10, // maximise f to maximise overhead -// config, -// offchainVersion, -// offchainBytes, -// ) -// const tx = await registry -// .connect(owner) -// ['registerUpkeep(address,uint32,address,bytes,bytes)']( -// mock.address, -// maxPerformGas, // max allowed gas -// await admin.getAddress(), -// randomBytes, -// '0x', -// ) -// const testUpkeepId = await getUpkeepID(tx) -// await registry.connect(admin).addFunds(testUpkeepId, toWei('100')) -// -// let performData = '0x' -// for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { -// performData += '11' -// } // max allowed performData -// -// await mock.setCanPerform(true) -// await mock.setPerformGasToBurn(maxPerformGas) -// -// await getTransmitTx(registry, keeper1, [testUpkeepId], { -// gasLimit: maxPerformGas.add(transmitGasOverhead), -// numSigners: 11, -// performData, -// }) // Should not revert -// }, -// ) -// -// itMaybe( -// 'performs upkeep, deducts payment, updates lastPerformed and emits events', -// async () => { -// await mock.setCanPerform(true) -// -// for (const i in fArray) { -// const newF = fArray[i] -// await registry -// .connect(owner) -// .setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// newF, -// config, -// offchainVersion, -// offchainBytes, -// ) -// const checkBlock = await ethers.provider.getBlock('latest') -// -// const keeperBefore = await registry.getTransmitterInfo( -// await keeper1.getAddress(), -// ) -// const registrationBefore = await registry.getUpkeep(upkeepId) -// const registryPremiumBefore = (await registry.getState()).state -// .totalPremium -// const keeperLinkBefore = await linkToken.balanceOf( -// await keeper1.getAddress(), -// ) -// const registryLinkBefore = await linkToken.balanceOf( -// registry.address, -// ) -// -// // Do the thing -// const tx = await getTransmitTx(registry, keeper1, [upkeepId], { -// checkBlockNum: checkBlock.number, -// checkBlockHash: checkBlock.hash, -// numSigners: newF + 1, -// }) -// -// const receipt = await tx.wait() -// -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const id = upkeepPerformedLog.args.id -// const success = upkeepPerformedLog.args.success -// const trigger = upkeepPerformedLog.args.trigger -// const gasUsed = upkeepPerformedLog.args.gasUsed -// const gasOverhead = upkeepPerformedLog.args.gasOverhead -// const totalPayment = upkeepPerformedLog.args.totalPayment -// assert.equal(id.toString(), upkeepId.toString()) -// assert.equal(success, true) -// assert.equal( -// trigger, -// encodeBlockTrigger({ -// blockNum: checkBlock.number, -// blockHash: checkBlock.hash, -// }), -// ) -// assert.isTrue(gasUsed.gt(BigNumber.from('0'))) -// assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) -// assert.isTrue(totalPayment.gt(BigNumber.from('0'))) -// -// const keeperAfter = await registry.getTransmitterInfo( -// await keeper1.getAddress(), -// ) -// const registrationAfter = await registry.getUpkeep(upkeepId) -// const keeperLinkAfter = await linkToken.balanceOf( -// await keeper1.getAddress(), -// ) -// const registryLinkAfter = await linkToken.balanceOf( -// registry.address, -// ) -// const registryPremiumAfter = (await registry.getState()).state -// .totalPremium -// const premium = registryPremiumAfter.sub(registryPremiumBefore) -// // Keeper payment is gasPayment + premium / num keepers -// const keeperPayment = totalPayment -// .sub(premium) -// .add(premium.div(BigNumber.from(keeperAddresses.length))) -// -// assert.equal( -// keeperAfter.balance.sub(keeperPayment).toString(), -// keeperBefore.balance.toString(), -// ) -// assert.equal( -// registrationBefore.balance.sub(totalPayment).toString(), -// registrationAfter.balance.toString(), -// ) -// assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) -// assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) -// -// // Amount spent should be updated correctly -// assert.equal( -// registrationAfter.amountSpent.sub(totalPayment).toString(), -// registrationBefore.amountSpent.toString(), -// ) -// assert.isTrue( -// registrationAfter.amountSpent -// .sub(registrationBefore.amountSpent) -// .eq(registrationBefore.balance.sub(registrationAfter.balance)), -// ) -// // Last perform block number should be updated -// assert.equal( -// registrationAfter.lastPerformedBlockNumber.toString(), -// tx.blockNumber?.toString(), -// ) -// -// // Latest epoch should be 5 -// assert.equal((await registry.getState()).state.latestEpoch, 5) -// } -// }, -// ) -// -// describeMaybe( -// 'Gas benchmarking conditional upkeeps [ @skip-coverage ]', -// function () { -// const fs = [1, 10] -// fs.forEach(function (newF) { -// it( -// 'When f=' + -// newF + -// ' calculates gas overhead appropriately within a margin for different scenarios', -// async () => { -// // Perform the upkeep once to remove non-zero storage slots and have predictable gas measurement -// let tx = await getTransmitTx(registry, keeper1, [upkeepId]) -// await tx.wait() -// -// // Different test scenarios -// let longBytes = '0x' -// for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { -// longBytes += '11' -// } -// const upkeepSuccessArray = [true, false] -// const performGasArray = [5000, performGas] -// const performDataArray = ['0x', longBytes] -// -// for (const i in upkeepSuccessArray) { -// for (const j in performGasArray) { -// for (const k in performDataArray) { -// const upkeepSuccess = upkeepSuccessArray[i] -// const performGas = performGasArray[j] -// const performData = performDataArray[k] -// -// await mock.setCanPerform(upkeepSuccess) -// await mock.setPerformGasToBurn(performGas) -// await registry -// .connect(owner) -// .setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// newF, -// config, -// offchainVersion, -// offchainBytes, -// ) -// tx = await getTransmitTx(registry, keeper1, [upkeepId], { -// numSigners: newF + 1, -// performData, -// }) -// const receipt = await tx.wait() -// const upkeepPerformedLogs = -// parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const upkeepGasUsed = upkeepPerformedLog.args.gasUsed -// const chargedGasOverhead = -// upkeepPerformedLog.args.gasOverhead -// const actualGasOverhead = -// receipt.gasUsed.sub(upkeepGasUsed) -// -// assert.isTrue(upkeepGasUsed.gt(BigNumber.from('0'))) -// assert.isTrue(chargedGasOverhead.gt(BigNumber.from('0'))) -// -// console.log( -// 'Gas Benchmarking conditional upkeeps:', -// 'upkeepSuccess=', -// upkeepSuccess, -// 'performGas=', -// performGas.toString(), -// 'performData length=', -// performData.length / 2 - 1, -// 'sig verification ( f =', -// newF, -// '): calculated overhead: ', -// chargedGasOverhead.toString(), -// ' actual overhead: ', -// actualGasOverhead.toString(), -// ' margin over gasUsed: ', -// chargedGasOverhead.sub(actualGasOverhead).toString(), -// ) -// -// // Overhead should not get capped -// const gasOverheadCap = registryConditionalOverhead -// .add( -// registryPerSignerGasOverhead.mul( -// BigNumber.from(newF + 1), -// ), -// ) -// .add( -// BigNumber.from( -// registryPerPerformByteGasOverhead.toNumber() * -// performData.length, -// ), -// ) -// const gasCapMinusOverhead = -// gasOverheadCap.sub(chargedGasOverhead) -// assert.isTrue( -// gasCapMinusOverhead.gt(BigNumber.from(0)), -// 'Gas overhead got capped. Verify gas overhead variables in test match those in the registry. To not have the overheads capped increase REGISTRY_GAS_OVERHEAD by atleast ' + -// gasCapMinusOverhead.toString(), -// ) -// // total gas charged should be greater than tx gas but within gasCalculationMargin -// assert.isTrue( -// chargedGasOverhead.gt(actualGasOverhead), -// 'Gas overhead calculated is too low, increase account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by atleast ' + -// actualGasOverhead.sub(chargedGasOverhead).toString(), -// ) -// -// assert.isTrue( -// chargedGasOverhead -// .sub(actualGasOverhead) -// .lt(gasCalculationMargin), -// ), -// 'Gas overhead calculated is too high, decrease account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by atleast ' + -// chargedGasOverhead -// .sub(chargedGasOverhead) -// .sub(gasCalculationMargin) -// .toString() -// } -// } -// } -// }, -// ) -// }) -// }, -// ) -// -// describeMaybe( -// 'Gas benchmarking log upkeeps [ @skip-coverage ]', -// function () { -// const fs = [1, 10] -// fs.forEach(function (newF) { -// it( -// 'When f=' + -// newF + -// ' calculates gas overhead appropriately within a margin', -// async () => { -// // Perform the upkeep once to remove non-zero storage slots and have predictable gas measurement -// let tx = await getTransmitTx(registry, keeper1, [logUpkeepId]) -// await tx.wait() -// const performData = '0x' -// await mock.setCanPerform(true) -// await mock.setPerformGasToBurn(performGas) -// await registry.setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// newF, -// config, -// offchainVersion, -// offchainBytes, -// ) -// tx = await getTransmitTx(registry, keeper1, [logUpkeepId], { -// numSigners: newF + 1, -// performData, -// }) -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly 1 Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, 1) -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const upkeepGasUsed = upkeepPerformedLog.args.gasUsed -// const chargedGasOverhead = upkeepPerformedLog.args.gasOverhead -// const actualGasOverhead = receipt.gasUsed.sub(upkeepGasUsed) -// -// assert.isTrue(upkeepGasUsed.gt(BigNumber.from('0'))) -// assert.isTrue(chargedGasOverhead.gt(BigNumber.from('0'))) -// -// console.log( -// 'Gas Benchmarking log upkeeps:', -// 'upkeepSuccess=', -// true, -// 'performGas=', -// performGas.toString(), -// 'performData length=', -// performData.length / 2 - 1, -// 'sig verification ( f =', -// newF, -// '): calculated overhead: ', -// chargedGasOverhead.toString(), -// ' actual overhead: ', -// actualGasOverhead.toString(), -// ' margin over gasUsed: ', -// chargedGasOverhead.sub(actualGasOverhead).toString(), -// ) -// -// // Overhead should not get capped -// const gasOverheadCap = registryLogOverhead -// .add( -// registryPerSignerGasOverhead.mul(BigNumber.from(newF + 1)), -// ) -// .add( -// BigNumber.from( -// registryPerPerformByteGasOverhead.toNumber() * -// performData.length, -// ), -// ) -// const gasCapMinusOverhead = -// gasOverheadCap.sub(chargedGasOverhead) -// assert.isTrue( -// gasCapMinusOverhead.gt(BigNumber.from(0)), -// 'Gas overhead got capped. Verify gas overhead variables in test match those in the registry. To not have the overheads capped increase REGISTRY_GAS_OVERHEAD by atleast ' + -// gasCapMinusOverhead.toString(), -// ) -// // total gas charged should be greater than tx gas but within gasCalculationMargin -// assert.isTrue( -// chargedGasOverhead.gt(actualGasOverhead), -// 'Gas overhead calculated is too low, increase account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by atleast ' + -// actualGasOverhead.sub(chargedGasOverhead).toString(), -// ) -// -// assert.isTrue( -// chargedGasOverhead -// .sub(actualGasOverhead) -// .lt(gasCalculationMargin), -// ), -// 'Gas overhead calculated is too high, decrease account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by atleast ' + -// chargedGasOverhead -// .sub(chargedGasOverhead) -// .sub(gasCalculationMargin) -// .toString() -// }, -// ) -// }) -// }, -// ) -// }) -// }) -// -// describeMaybe( -// '#transmit with upkeep batches [ @skip-coverage ]', -// function () { -// const numPassingConditionalUpkeepsArray = [0, 1, 5] -// const numPassingLogUpkeepsArray = [0, 1, 5] -// const numFailingUpkeepsArray = [0, 3] -// -// for (let idx = 0; idx < numPassingConditionalUpkeepsArray.length; idx++) { -// for (let jdx = 0; jdx < numPassingLogUpkeepsArray.length; jdx++) { -// for (let kdx = 0; kdx < numFailingUpkeepsArray.length; kdx++) { -// const numPassingConditionalUpkeeps = -// numPassingConditionalUpkeepsArray[idx] -// const numPassingLogUpkeeps = numPassingLogUpkeepsArray[jdx] -// const numFailingUpkeeps = numFailingUpkeepsArray[kdx] -// if ( -// numPassingConditionalUpkeeps == 0 && -// numPassingLogUpkeeps == 0 -// ) { -// continue -// } -// it( -// '[Conditional:' + -// numPassingConditionalUpkeeps + -// ',Log:' + -// numPassingLogUpkeeps + -// ',Failures:' + -// numFailingUpkeeps + -// '] performs successful upkeeps and does not charge failing upkeeps', -// async () => { -// const allUpkeeps = await getMultipleUpkeepsDeployedAndFunded( -// numPassingConditionalUpkeeps, -// numPassingLogUpkeeps, -// numFailingUpkeeps, -// ) -// const passingConditionalUpkeepIds = -// allUpkeeps.passingConditionalUpkeepIds -// const passingLogUpkeepIds = allUpkeeps.passingLogUpkeepIds -// const failingUpkeepIds = allUpkeeps.failingUpkeepIds -// -// const keeperBefore = await registry.getTransmitterInfo( -// await keeper1.getAddress(), -// ) -// const keeperLinkBefore = await linkToken.balanceOf( -// await keeper1.getAddress(), -// ) -// const registryLinkBefore = await linkToken.balanceOf( -// registry.address, -// ) -// const registryPremiumBefore = (await registry.getState()).state -// .totalPremium -// const registrationConditionalPassingBefore = await Promise.all( -// passingConditionalUpkeepIds.map(async (id) => { -// const reg = await registry.getUpkeep(BigNumber.from(id)) -// assert.equal(reg.lastPerformedBlockNumber.toString(), '0') -// return reg -// }), -// ) -// const registrationLogPassingBefore = await Promise.all( -// passingLogUpkeepIds.map(async (id) => { -// const reg = await registry.getUpkeep(BigNumber.from(id)) -// assert.equal(reg.lastPerformedBlockNumber.toString(), '0') -// return reg -// }), -// ) -// const registrationFailingBefore = await Promise.all( -// failingUpkeepIds.map(async (id) => { -// const reg = await registry.getUpkeep(BigNumber.from(id)) -// assert.equal(reg.lastPerformedBlockNumber.toString(), '0') -// return reg -// }), -// ) -// -// const tx = await getTransmitTx( -// registry, -// keeper1, -// passingConditionalUpkeepIds.concat( -// passingLogUpkeepIds.concat(failingUpkeepIds), -// ), -// ) -// -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly numPassingUpkeeps Upkeep Performed should be emitted -// assert.equal( -// upkeepPerformedLogs.length, -// numPassingConditionalUpkeeps + numPassingLogUpkeeps, -// ) -// const insufficientFundsLogs = -// parseInsufficientFundsUpkeepReportLogs(receipt) -// // exactly numFailingUpkeeps Upkeep Performed should be emitted -// assert.equal(insufficientFundsLogs.length, numFailingUpkeeps) -// -// const keeperAfter = await registry.getTransmitterInfo( -// await keeper1.getAddress(), -// ) -// const keeperLinkAfter = await linkToken.balanceOf( -// await keeper1.getAddress(), -// ) -// const registryLinkAfter = await linkToken.balanceOf( -// registry.address, -// ) -// const registrationConditionalPassingAfter = await Promise.all( -// passingConditionalUpkeepIds.map(async (id) => { -// return await registry.getUpkeep(BigNumber.from(id)) -// }), -// ) -// const registrationLogPassingAfter = await Promise.all( -// passingLogUpkeepIds.map(async (id) => { -// return await registry.getUpkeep(BigNumber.from(id)) -// }), -// ) -// const registrationFailingAfter = await Promise.all( -// failingUpkeepIds.map(async (id) => { -// return await registry.getUpkeep(BigNumber.from(id)) -// }), -// ) -// const registryPremiumAfter = (await registry.getState()).state -// .totalPremium -// const premium = registryPremiumAfter.sub(registryPremiumBefore) -// -// let netPayment = BigNumber.from('0') -// for (let i = 0; i < numPassingConditionalUpkeeps; i++) { -// const id = upkeepPerformedLogs[i].args.id -// const gasUsed = upkeepPerformedLogs[i].args.gasUsed -// const gasOverhead = upkeepPerformedLogs[i].args.gasOverhead -// const totalPayment = upkeepPerformedLogs[i].args.totalPayment -// -// expect(id).to.equal(passingConditionalUpkeepIds[i]) -// assert.isTrue(gasUsed.gt(BigNumber.from('0'))) -// assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) -// assert.isTrue(totalPayment.gt(BigNumber.from('0'))) -// -// // Balance should be deducted -// assert.equal( -// registrationConditionalPassingBefore[i].balance -// .sub(totalPayment) -// .toString(), -// registrationConditionalPassingAfter[i].balance.toString(), -// ) -// -// // Amount spent should be updated correctly -// assert.equal( -// registrationConditionalPassingAfter[i].amountSpent -// .sub(totalPayment) -// .toString(), -// registrationConditionalPassingBefore[ -// i -// ].amountSpent.toString(), -// ) -// -// // Last perform block number should be updated -// assert.equal( -// registrationConditionalPassingAfter[ -// i -// ].lastPerformedBlockNumber.toString(), -// tx.blockNumber?.toString(), -// ) -// -// netPayment = netPayment.add(totalPayment) -// } -// -// for (let i = 0; i < numPassingLogUpkeeps; i++) { -// const id = -// upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args -// .id -// const gasUsed = -// upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args -// .gasUsed -// const gasOverhead = -// upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args -// .gasOverhead -// const totalPayment = -// upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args -// .totalPayment -// -// expect(id).to.equal(passingLogUpkeepIds[i]) -// assert.isTrue(gasUsed.gt(BigNumber.from('0'))) -// assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) -// assert.isTrue(totalPayment.gt(BigNumber.from('0'))) -// -// // Balance should be deducted -// assert.equal( -// registrationLogPassingBefore[i].balance -// .sub(totalPayment) -// .toString(), -// registrationLogPassingAfter[i].balance.toString(), -// ) -// -// // Amount spent should be updated correctly -// assert.equal( -// registrationLogPassingAfter[i].amountSpent -// .sub(totalPayment) -// .toString(), -// registrationLogPassingBefore[i].amountSpent.toString(), -// ) -// -// // Last perform block number should not be updated for log triggers -// assert.equal( -// registrationLogPassingAfter[ -// i -// ].lastPerformedBlockNumber.toString(), -// '0', -// ) -// -// netPayment = netPayment.add(totalPayment) -// } -// -// for (let i = 0; i < numFailingUpkeeps; i++) { -// // InsufficientFunds log should be emitted -// const id = insufficientFundsLogs[i].args.id -// expect(id).to.equal(failingUpkeepIds[i]) -// -// // Balance and amount spent should be same -// assert.equal( -// registrationFailingBefore[i].balance.toString(), -// registrationFailingAfter[i].balance.toString(), -// ) -// assert.equal( -// registrationFailingBefore[i].amountSpent.toString(), -// registrationFailingAfter[i].amountSpent.toString(), -// ) -// -// // Last perform block number should not be updated -// assert.equal( -// registrationFailingAfter[ -// i -// ].lastPerformedBlockNumber.toString(), -// '0', -// ) -// } -// -// // Keeper payment is gasPayment + premium / num keepers -// const keeperPayment = netPayment -// .sub(premium) -// .add(premium.div(BigNumber.from(keeperAddresses.length))) -// -// // Keeper should be paid net payment for all passed upkeeps -// assert.equal( -// keeperAfter.balance.sub(keeperPayment).toString(), -// keeperBefore.balance.toString(), -// ) -// -// assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) -// assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) -// }, -// ) -// -// it( -// '[Conditional:' + -// numPassingConditionalUpkeeps + -// ',Log' + -// numPassingLogUpkeeps + -// ',Failures:' + -// numFailingUpkeeps + -// '] splits gas overhead appropriately among performed upkeeps [ @skip-coverage ]', -// async () => { -// const allUpkeeps = await getMultipleUpkeepsDeployedAndFunded( -// numPassingConditionalUpkeeps, -// numPassingLogUpkeeps, -// numFailingUpkeeps, -// ) -// const passingConditionalUpkeepIds = -// allUpkeeps.passingConditionalUpkeepIds -// const passingLogUpkeepIds = allUpkeeps.passingLogUpkeepIds -// const failingUpkeepIds = allUpkeeps.failingUpkeepIds -// -// // Perform the upkeeps once to remove non-zero storage slots and have predictable gas measurement -// let tx = await getTransmitTx( -// registry, -// keeper1, -// passingConditionalUpkeepIds.concat( -// passingLogUpkeepIds.concat(failingUpkeepIds), -// ), -// ) -// -// await tx.wait() -// -// // Do the actual thing -// -// tx = await getTransmitTx( -// registry, -// keeper1, -// passingConditionalUpkeepIds.concat( -// passingLogUpkeepIds.concat(failingUpkeepIds), -// ), -// ) -// -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly numPassingUpkeeps Upkeep Performed should be emitted -// assert.equal( -// upkeepPerformedLogs.length, -// numPassingConditionalUpkeeps + numPassingLogUpkeeps, -// ) -// -// const gasConditionalOverheadCap = -// registryConditionalOverhead.add( -// registryPerSignerGasOverhead.mul(BigNumber.from(f + 1)), -// ) -// const gasLogOverheadCap = registryLogOverhead.add( -// registryPerSignerGasOverhead.mul(BigNumber.from(f + 1)), -// ) -// -// const overheadCanGetCapped = -// numFailingUpkeeps > 0 && -// numPassingConditionalUpkeeps <= 1 && -// numPassingLogUpkeeps <= 1 -// // Can happen if there are failing upkeeps and only 1 successful upkeep of each type -// let netGasUsedPlusOverhead = BigNumber.from('0') -// -// for (let i = 0; i < numPassingConditionalUpkeeps; i++) { -// const gasUsed = upkeepPerformedLogs[i].args.gasUsed -// const gasOverhead = upkeepPerformedLogs[i].args.gasOverhead -// -// assert.isTrue(gasUsed.gt(BigNumber.from('0'))) -// assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) -// -// // Overhead should not exceed capped -// assert.isTrue(gasOverhead.lte(gasConditionalOverheadCap)) -// -// // Overhead should be same for every upkeep since they have equal performData, hence same caps -// assert.isTrue( -// gasOverhead.eq(upkeepPerformedLogs[0].args.gasOverhead), -// ) -// -// netGasUsedPlusOverhead = netGasUsedPlusOverhead -// .add(gasUsed) -// .add(gasOverhead) -// } -// for (let i = 0; i < numPassingLogUpkeeps; i++) { -// const gasUsed = -// upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args -// .gasUsed -// const gasOverhead = -// upkeepPerformedLogs[numPassingConditionalUpkeeps + i].args -// .gasOverhead -// -// assert.isTrue(gasUsed.gt(BigNumber.from('0'))) -// assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) -// -// // Overhead should not exceed capped -// assert.isTrue(gasOverhead.lte(gasLogOverheadCap)) -// -// // Overhead should be same for every upkeep since they have equal performData, hence same caps -// assert.isTrue( -// gasOverhead.eq( -// upkeepPerformedLogs[numPassingConditionalUpkeeps].args -// .gasOverhead, -// ), -// ) -// -// netGasUsedPlusOverhead = netGasUsedPlusOverhead -// .add(gasUsed) -// .add(gasOverhead) -// } -// -// const overheadsGotCapped = -// (numPassingConditionalUpkeeps > 0 && -// upkeepPerformedLogs[0].args.gasOverhead.eq( -// gasConditionalOverheadCap, -// )) || -// (numPassingLogUpkeeps > 0 && -// upkeepPerformedLogs[ -// numPassingConditionalUpkeeps -// ].args.gasOverhead.eq(gasLogOverheadCap)) -// // Should only get capped in certain scenarios -// if (overheadsGotCapped) { -// assert.isTrue( -// overheadCanGetCapped, -// 'Gas overhead got capped. Verify gas overhead variables in test match those in the registry. To not have the overheads capped increase REGISTRY_GAS_OVERHEAD', -// ) -// } -// -// console.log( -// 'Gas Benchmarking - batching (passedConditionalUpkeeps: ', -// numPassingConditionalUpkeeps, -// 'passedLogUpkeeps:', -// numPassingLogUpkeeps, -// 'failedUpkeeps:', -// numFailingUpkeeps, -// '): ', -// 'overheadsGotCapped', -// overheadsGotCapped, -// numPassingConditionalUpkeeps > 0 -// ? 'calculated conditional overhead' -// : '', -// numPassingConditionalUpkeeps > 0 -// ? upkeepPerformedLogs[0].args.gasOverhead.toString() -// : '', -// numPassingLogUpkeeps > 0 ? 'calculated log overhead' : '', -// numPassingLogUpkeeps > 0 -// ? upkeepPerformedLogs[ -// numPassingConditionalUpkeeps -// ].args.gasOverhead.toString() -// : '', -// ' margin over gasUsed', -// netGasUsedPlusOverhead.sub(receipt.gasUsed).toString(), -// ) -// -// // If overheads dont get capped then total gas charged should be greater than tx gas -// // We don't check whether the net is within gasMargin as the margin changes with numFailedUpkeeps -// // Which is ok, as long as individual gas overhead is capped -// if (!overheadsGotCapped) { -// assert.isTrue( -// netGasUsedPlusOverhead.gt(receipt.gasUsed), -// 'Gas overhead is too low, increase ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD', -// ) -// } -// }, -// ) -// } -// } -// } -// -// it('has enough perform gas overhead for large batches [ @skip-coverage ]', async () => { -// const numUpkeeps = 20 -// const upkeepIds: BigNumber[] = [] -// let totalPerformGas = BigNumber.from('0') -// for (let i = 0; i < numUpkeeps; i++) { -// const mock = await upkeepMockFactory.deploy() -// const tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// const testUpkeepId = await getUpkeepID(tx) -// upkeepIds.push(testUpkeepId) -// -// // Add funds to passing upkeeps -// await registry.connect(owner).addFunds(testUpkeepId, toWei('10')) -// -// await mock.setCanPerform(true) -// await mock.setPerformGasToBurn(performGas) -// -// totalPerformGas = totalPerformGas.add(performGas) -// } -// -// // Should revert with no overhead added -// await evmRevert( -// getTransmitTx(registry, keeper1, upkeepIds, { -// gasLimit: totalPerformGas, -// }), -// ) -// // Should not revert with overhead added -// await getTransmitTx(registry, keeper1, upkeepIds, { -// gasLimit: totalPerformGas.add(transmitGasOverhead), -// }) -// }) -// -// it('splits l2 payment among performed upkeeps', async () => { -// const numUpkeeps = 7 -// const upkeepIds: BigNumber[] = [] -// // Same as MockArbGasInfo.sol -// const l1CostWeiArb = BigNumber.from(1000000) -// -// for (let i = 0; i < numUpkeeps; i++) { -// const mock = await upkeepMockFactory.deploy() -// const tx = await arbRegistry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// const testUpkeepId = await getUpkeepID(tx) -// upkeepIds.push(testUpkeepId) -// -// // Add funds to passing upkeeps -// await arbRegistry.connect(owner).addFunds(testUpkeepId, toWei('100')) -// } -// -// // Do the thing -// const tx = await getTransmitTx( -// arbRegistry, -// keeper1, -// upkeepIds, -// -// { gasPrice: gasWei.mul('5') }, // High gas price so that it gets capped -// ) -// -// const receipt = await tx.wait() -// const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) -// // exactly numPassingUpkeeps Upkeep Performed should be emitted -// assert.equal(upkeepPerformedLogs.length, numUpkeeps) -// -// // Verify the payment calculation in upkeepPerformed[0] -// const upkeepPerformedLog = upkeepPerformedLogs[0] -// -// const gasUsed = upkeepPerformedLog.args.gasUsed -// const gasOverhead = upkeepPerformedLog.args.gasOverhead -// const totalPayment = upkeepPerformedLog.args.totalPayment -// -// assert.equal( -// linkForGas( -// gasUsed, -// gasOverhead, -// gasCeilingMultiplier, -// paymentPremiumPPB, -// flatFeeMicroLink, -// l1CostWeiArb.div(gasCeilingMultiplier), // Dividing by gasCeilingMultiplier as it gets multiplied later -// BigNumber.from(numUpkeeps), -// ).total.toString(), -// totalPayment.toString(), -// ) -// }) -// }, -// ) -// -// describe('#recoverFunds', () => { -// const sent = toWei('7') -// -// beforeEach(async () => { -// await linkToken.connect(admin).approve(registry.address, toWei('100')) -// await linkToken -// .connect(owner) -// .transfer(await keeper1.getAddress(), toWei('1000')) -// -// // add funds to upkeep 1 and perform and withdraw some payment -// const tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), emptyBytes, emptyBytes) -// -// const id1 = await getUpkeepID(tx) -// await registry.connect(admin).addFunds(id1, toWei('5')) -// -// await getTransmitTx(registry, keeper1, [id1]) -// await getTransmitTx(registry, keeper2, [id1]) -// await getTransmitTx(registry, keeper3, [id1]) -// -// await registry -// .connect(payee1) -// .withdrawPayment( -// await keeper1.getAddress(), -// await nonkeeper.getAddress(), -// ) -// -// // transfer funds directly to the registry -// await linkToken.connect(keeper1).transfer(registry.address, sent) -// -// // add funds to upkeep 2 and perform and withdraw some payment -// const tx2 = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), emptyBytes, emptyBytes) -// const id2 = await getUpkeepID(tx2) -// await registry.connect(admin).addFunds(id2, toWei('5')) -// -// await getTransmitTx(registry, keeper1, [id2]) -// await getTransmitTx(registry, keeper2, [id2]) -// await getTransmitTx(registry, keeper3, [id2]) -// -// await registry -// .connect(payee2) -// .withdrawPayment( -// await keeper2.getAddress(), -// await nonkeeper.getAddress(), -// ) -// -// // transfer funds using onTokenTransfer -// const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id2]) -// await linkToken -// .connect(owner) -// .transferAndCall(registry.address, toWei('1'), data) -// -// // withdraw some funds -// await registry.connect(owner).cancelUpkeep(id1) -// await registry -// .connect(admin) -// .withdrawFunds(id1, await nonkeeper.getAddress()) -// }) -// -// it('reverts if not called by owner', async () => { -// await evmRevert( -// registry.connect(keeper1).recoverFunds(), -// 'Only callable by owner', -// ) -// }) -// -// it('allows any funds that have been accidentally transfered to be moved', async () => { -// const balanceBefore = await linkToken.balanceOf(registry.address) -// const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) -// -// await registry.connect(owner).recoverFunds() -// -// const balanceAfter = await linkToken.balanceOf(registry.address) -// const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) -// -// assert.isTrue(balanceBefore.eq(balanceAfter.add(sent))) -// assert.isTrue(ownerAfter.eq(ownerBefore.add(sent))) -// }) -// }) -// -// describe('#getMinBalanceForUpkeep / #checkUpkeep / #transmit', () => { -// it('calculates the minimum balance appropriately', async () => { -// await mock.setCanCheck(true) -// -// const oneWei = BigNumber.from(1) -// const minBalance = await registry.getMinBalanceForUpkeep(upkeepId) -// const tooLow = minBalance.sub(oneWei) -// -// await registry.connect(admin).addFunds(upkeepId, tooLow) -// let checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.INSUFFICIENT_BALANCE, -// ) -// -// await registry.connect(admin).addFunds(upkeepId, oneWei) -// checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// assert.equal(checkUpkeepResult.upkeepNeeded, true) -// }) -// -// it('uses maxPerformData size in checkUpkeep but actual performDataSize in transmit', async () => { -// const tx1 = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// const upkeepID1 = await getUpkeepID(tx1) -// const tx2 = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// const upkeepID2 = await getUpkeepID(tx2) -// await mock.setCanCheck(true) -// await mock.setCanPerform(true) -// -// // upkeep 1 is underfunded, 2 is fully funded -// const minBalance1 = ( -// await registry.getMinBalanceForUpkeep(upkeepID1) -// ).sub(1) -// const minBalance2 = await registry.getMinBalanceForUpkeep(upkeepID2) -// await registry.connect(owner).addFunds(upkeepID1, minBalance1) -// await registry.connect(owner).addFunds(upkeepID2, minBalance2) -// -// // upkeep 1 check should return false, 2 should return true -// let checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepID1) -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.INSUFFICIENT_BALANCE, -// ) -// -// checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepID2) -// assert.equal(checkUpkeepResult.upkeepNeeded, true) -// -// // upkeep 1 perform should return with insufficient balance using max performData size -// let maxPerformData = '0x' -// for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { -// maxPerformData += '11' -// } -// -// const tx = await getTransmitTx(registry, keeper1, [upkeepID1], { -// gasPrice: gasWei.mul(gasCeilingMultiplier), -// performData: maxPerformData, -// }) -// -// const receipt = await tx.wait() -// const insufficientFundsUpkeepReportLogs = -// parseInsufficientFundsUpkeepReportLogs(receipt) -// // exactly 1 InsufficientFundsUpkeepReportLogs log should be emitted -// assert.equal(insufficientFundsUpkeepReportLogs.length, 1) -// -// // upkeep 1 perform should succeed with empty performData -// await getTransmitTx(registry, keeper1, [upkeepID1], { -// gasPrice: gasWei.mul(gasCeilingMultiplier), -// }), -// // upkeep 2 perform should succeed with max performData size -// await getTransmitTx(registry, keeper1, [upkeepID2], { -// gasPrice: gasWei.mul(gasCeilingMultiplier), -// performData: maxPerformData, -// }) -// }) -// }) -// -// describe('#withdrawFunds', () => { -// let upkeepId2: BigNumber -// -// beforeEach(async () => { -// const tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), randomBytes, '0x') -// upkeepId2 = await getUpkeepID(tx) -// -// await registry.connect(admin).addFunds(upkeepId, toWei('100')) -// await registry.connect(admin).addFunds(upkeepId2, toWei('100')) -// -// // Do a perform so that upkeep is charged some amount -// await getTransmitTx(registry, keeper1, [upkeepId]) -// await getTransmitTx(registry, keeper1, [upkeepId2]) -// }) -// -// it('reverts if called on a non existing ID', async () => { -// await evmRevert( -// registry -// .connect(admin) -// .withdrawFunds(upkeepId.add(1), await payee1.getAddress()), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if called by anyone but the admin', async () => { -// await evmRevert( -// registry -// .connect(owner) -// .withdrawFunds(upkeepId, await payee1.getAddress()), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if called on an uncanceled upkeep', async () => { -// await evmRevert( -// registry -// .connect(admin) -// .withdrawFunds(upkeepId, await payee1.getAddress()), -// 'UpkeepNotCanceled()', -// ) -// }) -// -// it('reverts if called with the 0 address', async () => { -// await evmRevert( -// registry.connect(admin).withdrawFunds(upkeepId, zeroAddress), -// 'InvalidRecipient()', -// ) -// }) -// -// describe('after the registration is paused, then cancelled', () => { -// it('allows the admin to withdraw', async () => { -// const balance = await registry.getBalance(upkeepId) -// const payee = await payee1.getAddress() -// await registry.connect(admin).pauseUpkeep(upkeepId) -// await registry.connect(owner).cancelUpkeep(upkeepId) -// await expect(() => -// registry.connect(admin).withdrawFunds(upkeepId, payee), -// ).to.changeTokenBalance(linkToken, payee1, balance) -// }) -// }) -// -// describe('after the registration is cancelled', () => { -// beforeEach(async () => { -// await registry.connect(owner).cancelUpkeep(upkeepId) -// await registry.connect(owner).cancelUpkeep(upkeepId2) -// }) -// -// it('can be called successively on two upkeeps', async () => { -// await registry -// .connect(admin) -// .withdrawFunds(upkeepId, await payee1.getAddress()) -// await registry -// .connect(admin) -// .withdrawFunds(upkeepId2, await payee1.getAddress()) -// }) -// -// it('moves the funds out and updates the balance and emits an event', async () => { -// const payee1Before = await linkToken.balanceOf( -// await payee1.getAddress(), -// ) -// const registryBefore = await linkToken.balanceOf(registry.address) -// -// let registration = await registry.getUpkeep(upkeepId) -// const previousBalance = registration.balance -// -// const tx = await registry -// .connect(admin) -// .withdrawFunds(upkeepId, await payee1.getAddress()) -// await expect(tx) -// .to.emit(registry, 'FundsWithdrawn') -// .withArgs(upkeepId, previousBalance, await payee1.getAddress()) -// -// const payee1After = await linkToken.balanceOf(await payee1.getAddress()) -// const registryAfter = await linkToken.balanceOf(registry.address) -// -// assert.isTrue(payee1Before.add(previousBalance).eq(payee1After)) -// assert.isTrue(registryBefore.sub(previousBalance).eq(registryAfter)) -// -// registration = await registry.getUpkeep(upkeepId) -// assert.equal(0, registration.balance.toNumber()) -// }) -// }) -// }) -// -// describe('#simulatePerformUpkeep', () => { -// it('reverts if called by non zero address', async () => { -// await evmRevert( -// registry -// .connect(await owner.getAddress()) -// .callStatic.simulatePerformUpkeep(upkeepId, '0x'), -// 'OnlySimulatedBackend()', -// ) -// }) -// -// it('reverts when registry is paused', async () => { -// await registry.connect(owner).pause() -// await evmRevert( -// registry -// .connect(zeroAddress) -// .callStatic.simulatePerformUpkeep(upkeepId, '0x'), -// 'RegistryPaused()', -// ) -// }) -// -// it('returns false and gasUsed when perform fails', async () => { -// await mock.setCanPerform(false) -// -// const simulatePerformResult = await registry -// .connect(zeroAddress) -// .callStatic.simulatePerformUpkeep(upkeepId, '0x') -// -// assert.equal(simulatePerformResult.success, false) -// assert.isTrue(simulatePerformResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// }) -// -// it('returns true, gasUsed, and performGas when perform succeeds', async () => { -// await mock.setCanPerform(true) -// -// const simulatePerformResult = await registry -// .connect(zeroAddress) -// .callStatic.simulatePerformUpkeep(upkeepId, '0x') -// -// assert.equal(simulatePerformResult.success, true) -// assert.isTrue(simulatePerformResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// }) -// -// it('returns correct amount of gasUsed when perform succeeds', async () => { -// await mock.setCanPerform(true) -// await mock.setPerformGasToBurn(performGas) -// -// const simulatePerformResult = await registry -// .connect(zeroAddress) -// .callStatic.simulatePerformUpkeep(upkeepId, '0x') -// -// assert.equal(simulatePerformResult.success, true) -// // Full execute gas should be used, with some performGasBuffer(1000) -// assert.isTrue( -// simulatePerformResult.gasUsed.gt( -// performGas.sub(BigNumber.from('1000')), -// ), -// ) -// }) -// }) -// -// describe('#checkUpkeep', () => { -// it('reverts if called by non zero address', async () => { -// await evmRevert( -// registry -// .connect(await owner.getAddress()) -// .callStatic['checkUpkeep(uint256)'](upkeepId), -// 'OnlySimulatedBackend()', -// ) -// }) -// -// it('returns false and error code if the upkeep is cancelled by admin', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.UPKEEP_CANCELLED, -// ) -// expect(checkUpkeepResult.gasUsed).to.equal(0) -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// it('returns false and error code if the upkeep is cancelled by owner', async () => { -// await registry.connect(owner).cancelUpkeep(upkeepId) -// -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.UPKEEP_CANCELLED, -// ) -// expect(checkUpkeepResult.gasUsed).to.equal(0) -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// it('returns false and error code if the registry is paused', async () => { -// await registry.connect(owner).pause() -// -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.REGISTRY_PAUSED, -// ) -// expect(checkUpkeepResult.gasUsed).to.equal(0) -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// it('returns false and error code if the upkeep is paused', async () => { -// await registry.connect(admin).pauseUpkeep(upkeepId) -// -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.UPKEEP_PAUSED, -// ) -// expect(checkUpkeepResult.gasUsed).to.equal(0) -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// it('returns false and error code if user is out of funds', async () => { -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.INSUFFICIENT_BALANCE, -// ) -// expect(checkUpkeepResult.gasUsed).to.equal(0) -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// context('when the registration is funded', () => { -// beforeEach(async () => { -// await linkToken.connect(admin).approve(registry.address, toWei('200')) -// await registry.connect(admin).addFunds(upkeepId, toWei('100')) -// await registry.connect(admin).addFunds(logUpkeepId, toWei('100')) -// }) -// -// it('returns false, error code, and revert data if the target check reverts', async () => { -// await mock.setShouldRevertCheck(true) -// await mock.setCheckRevertReason( -// 'custom revert error, clever way to insert offchain data', -// ) -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// -// const revertReasonBytes = `0x${checkUpkeepResult.performData.slice(10)}` // remove sighash -// assert.equal( -// ethers.utils.defaultAbiCoder.decode(['string'], revertReasonBytes)[0], -// 'custom revert error, clever way to insert offchain data', -// ) -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.TARGET_CHECK_REVERTED, -// ) -// assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// // Feed data should be returned here -// assert.isTrue(checkUpkeepResult.fastGasWei.gt(BigNumber.from('0'))) -// assert.isTrue(checkUpkeepResult.linkNative.gt(BigNumber.from('0'))) -// }) -// -// it('returns false, error code, and no revert data if the target check revert data exceeds maxRevertDataSize', async () => { -// await mock.setShouldRevertCheck(true) -// let longRevertReason = '' -// for (let i = 0; i <= maxRevertDataSize.toNumber(); i++) { -// longRevertReason += 'x' -// } -// await mock.setCheckRevertReason(longRevertReason) -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, -// ) -// assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// it('returns false and error code if the upkeep is not needed', async () => { -// await mock.setCanCheck(false) -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.UPKEEP_NOT_NEEDED, -// ) -// assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// it('returns false and error code if the performData exceeds limit', async () => { -// let longBytes = '0x' -// for (let i = 0; i < 5000; i++) { -// longBytes += '1' -// } -// await mock.setCanCheck(true) -// await mock.setPerformData(longBytes) -// -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, false) -// assert.equal(checkUpkeepResult.performData, '0x') -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, -// ) -// assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// }) -// -// it('returns true with gas used if the target can execute', async () => { -// await mock.setCanCheck(true) -// await mock.setPerformData(randomBytes) -// -// const latestBlock = await ethers.provider.getBlock('latest') -// -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId, { -// blockTag: latestBlock.number, -// }) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, true) -// assert.equal(checkUpkeepResult.performData, randomBytes) -// assert.equal( -// checkUpkeepResult.upkeepFailureReason, -// UpkeepFailureReason.NONE, -// ) -// assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// expect(checkUpkeepResult.gasLimit).to.equal(performGas) -// assert.isTrue(checkUpkeepResult.fastGasWei.eq(gasWei)) -// assert.isTrue(checkUpkeepResult.linkNative.eq(linkEth)) -// }) -// -// it('calls checkLog for log-trigger upkeeps', async () => { -// const log: Log = { -// index: 0, -// timestamp: 0, -// txHash: ethers.utils.randomBytes(32), -// blockNumber: 100, -// blockHash: ethers.utils.randomBytes(32), -// source: randomAddress(), -// topics: [ethers.utils.randomBytes(32), ethers.utils.randomBytes(32)], -// data: ethers.utils.randomBytes(1000), -// } -// -// await ltUpkeep.mock.checkLog.withArgs(log, '0x').returns(true, '0x1234') -// -// const checkData = encodeLog(log) -// -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256,bytes)'](logUpkeepId, checkData) -// -// expect(checkUpkeepResult.upkeepNeeded).to.be.true -// expect(checkUpkeepResult.performData).to.equal('0x1234') -// }) -// -// itMaybe( -// 'has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', -// async () => { -// await mock.setCanCheck(true) -// await mock.setCheckGasToBurn(checkGasLimit) -// const gas = checkGasLimit.add(checkGasOverhead) -// const checkUpkeepResult = await registry -// .connect(zeroAddress) -// .callStatic['checkUpkeep(uint256)'](upkeepId, { -// gasLimit: gas, -// }) -// -// assert.equal(checkUpkeepResult.upkeepNeeded, true) -// }, -// ) -// }) -// }) -// -// describe('#addFunds', () => { -// const amount = toWei('1') -// -// it('reverts if the registration does not exist', async () => { -// await evmRevert( -// registry.connect(keeper1).addFunds(upkeepId.add(1), amount), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('adds to the balance of the registration', async () => { -// await registry.connect(admin).addFunds(upkeepId, amount) -// const registration = await registry.getUpkeep(upkeepId) -// assert.isTrue(amount.eq(registration.balance)) -// }) -// -// it('lets anyone add funds to an upkeep not just admin', async () => { -// await linkToken.connect(owner).transfer(await payee1.getAddress(), amount) -// await linkToken.connect(payee1).approve(registry.address, amount) -// -// await registry.connect(payee1).addFunds(upkeepId, amount) -// const registration = await registry.getUpkeep(upkeepId) -// assert.isTrue(amount.eq(registration.balance)) -// }) -// -// it('emits a log', async () => { -// const tx = await registry.connect(admin).addFunds(upkeepId, amount) -// await expect(tx) -// .to.emit(registry, 'FundsAdded') -// .withArgs(upkeepId, await admin.getAddress(), amount) -// }) -// -// it('reverts if the upkeep is canceled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// await evmRevert( -// registry.connect(keeper1).addFunds(upkeepId, amount), -// 'UpkeepCancelled()', -// ) -// }) -// }) -// -// describe('#getActiveUpkeepIDs', () => { -// it('reverts if startIndex is out of bounds ', async () => { -// await evmRevert( -// registry.getActiveUpkeepIDs(numUpkeeps, 0), -// 'IndexOutOfRange()', -// ) -// await evmRevert( -// registry.getActiveUpkeepIDs(numUpkeeps + 1, 0), -// 'IndexOutOfRange()', -// ) -// }) -// -// it('returns upkeep IDs bounded by maxCount', async () => { -// let upkeepIds = await registry.getActiveUpkeepIDs(0, 1) -// assert(upkeepIds.length == 1) -// assert(upkeepIds[0].eq(upkeepId)) -// upkeepIds = await registry.getActiveUpkeepIDs(1, 3) -// assert(upkeepIds.length == 3) -// expect(upkeepIds).to.deep.equal([ -// afUpkeepId, -// logUpkeepId, -// streamsLookupUpkeepId, -// ]) -// }) -// -// it('returns as many ids as possible if maxCount > num available', async () => { -// const upkeepIds = await registry.getActiveUpkeepIDs(1, numUpkeeps + 100) -// assert(upkeepIds.length == numUpkeeps - 1) -// }) -// -// it('returns all upkeep IDs if maxCount is 0', async () => { -// let upkeepIds = await registry.getActiveUpkeepIDs(0, 0) -// assert(upkeepIds.length == numUpkeeps) -// upkeepIds = await registry.getActiveUpkeepIDs(2, 0) -// assert(upkeepIds.length == numUpkeeps - 2) -// }) -// }) -// -// describe('#getMaxPaymentForGas', () => { -// const arbL1PriceinWei = BigNumber.from(1000) // Same as MockArbGasInfo.sol -// const l1CostWeiArb = arbL1PriceinWei.mul(16).mul(maxPerformDataSize) -// const l1CostWeiOpt = BigNumber.from(2000000) // Same as MockOVMGasPriceOracle.sol -// itMaybe('calculates the max fee appropriately', async () => { -// await verifyMaxPayment(registry) -// }) -// -// itMaybe('calculates the max fee appropriately for Arbitrum', async () => { -// await verifyMaxPayment(arbRegistry, l1CostWeiArb) -// }) -// -// itMaybe('calculates the max fee appropriately for Optimism', async () => { -// await verifyMaxPayment(opRegistry, l1CostWeiOpt) -// }) -// -// it('uses the fallback gas price if the feed has issues', async () => { -// const expectedFallbackMaxPayment = linkForGas( -// performGas, -// registryConditionalOverhead -// .add(registryPerSignerGasOverhead.mul(f + 1)) -// .add(maxPerformDataSize.mul(registryPerPerformByteGasOverhead)), -// gasCeilingMultiplier.mul('2'), // fallbackGasPrice is 2x gas price -// paymentPremiumPPB, -// flatFeeMicroLink, -// ).total -// -// // Stale feed -// let roundId = 99 -// const answer = 100 -// let updatedAt = 946684800 // New Years 2000 🥳 -// let startedAt = 946684799 -// await gasPriceFeed -// .connect(owner) -// .updateRoundData(roundId, answer, updatedAt, startedAt) -// -// assert.equal( -// expectedFallbackMaxPayment.toString(), -// ( -// await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) -// ).toString(), -// ) -// -// // Negative feed price -// roundId = 100 -// updatedAt = now() -// startedAt = 946684799 -// await gasPriceFeed -// .connect(owner) -// .updateRoundData(roundId, -100, updatedAt, startedAt) -// -// assert.equal( -// expectedFallbackMaxPayment.toString(), -// ( -// await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) -// ).toString(), -// ) -// -// // Zero feed price -// roundId = 101 -// updatedAt = now() -// startedAt = 946684799 -// await gasPriceFeed -// .connect(owner) -// .updateRoundData(roundId, 0, updatedAt, startedAt) -// -// assert.equal( -// expectedFallbackMaxPayment.toString(), -// ( -// await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) -// ).toString(), -// ) -// }) -// -// it('uses the fallback link price if the feed has issues', async () => { -// const expectedFallbackMaxPayment = linkForGas( -// performGas, -// registryConditionalOverhead -// .add(registryPerSignerGasOverhead.mul(f + 1)) -// .add(maxPerformDataSize.mul(registryPerPerformByteGasOverhead)), -// gasCeilingMultiplier.mul('2'), // fallbackLinkPrice is 1/2 link price, so multiply by 2 -// paymentPremiumPPB, -// flatFeeMicroLink, -// ).total -// -// // Stale feed -// let roundId = 99 -// const answer = 100 -// let updatedAt = 946684800 // New Years 2000 🥳 -// let startedAt = 946684799 -// await linkEthFeed -// .connect(owner) -// .updateRoundData(roundId, answer, updatedAt, startedAt) -// -// assert.equal( -// expectedFallbackMaxPayment.toString(), -// ( -// await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) -// ).toString(), -// ) -// -// // Negative feed price -// roundId = 100 -// updatedAt = now() -// startedAt = 946684799 -// await linkEthFeed -// .connect(owner) -// .updateRoundData(roundId, -100, updatedAt, startedAt) -// -// assert.equal( -// expectedFallbackMaxPayment.toString(), -// ( -// await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) -// ).toString(), -// ) -// -// // Zero feed price -// roundId = 101 -// updatedAt = now() -// startedAt = 946684799 -// await linkEthFeed -// .connect(owner) -// .updateRoundData(roundId, 0, updatedAt, startedAt) -// -// assert.equal( -// expectedFallbackMaxPayment.toString(), -// ( -// await registry.getMaxPaymentForGas(Trigger.CONDITION, performGas) -// ).toString(), -// ) -// }) -// }) -// -// describe('#typeAndVersion', () => { -// it('uses the correct type and version', async () => { -// const typeAndVersion = await registry.typeAndVersion() -// assert.equal(typeAndVersion, 'KeeperRegistry 2.1.0') -// }) -// }) -// -// describe('#onTokenTransfer', () => { -// const amount = toWei('1') -// -// it('reverts if not called by the LINK token', async () => { -// const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) -// -// await evmRevert( -// registry -// .connect(keeper1) -// .onTokenTransfer(await keeper1.getAddress(), amount, data), -// 'OnlyCallableByLINKToken()', -// ) -// }) -// -// it('reverts if not called with more or less than 32 bytes', async () => { -// const longData = ethers.utils.defaultAbiCoder.encode( -// ['uint256', 'uint256'], -// ['33', '34'], -// ) -// const shortData = '0x12345678' -// -// await evmRevert( -// linkToken -// .connect(owner) -// .transferAndCall(registry.address, amount, longData), -// ) -// await evmRevert( -// linkToken -// .connect(owner) -// .transferAndCall(registry.address, amount, shortData), -// ) -// }) -// -// it('reverts if the upkeep is canceled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// await evmRevert( -// registry.connect(keeper1).addFunds(upkeepId, amount), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('updates the funds of the job id passed', async () => { -// const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) -// -// const before = (await registry.getUpkeep(upkeepId)).balance -// await linkToken -// .connect(owner) -// .transferAndCall(registry.address, amount, data) -// const after = (await registry.getUpkeep(upkeepId)).balance -// -// assert.isTrue(before.add(amount).eq(after)) -// }) -// }) -// -// describeMaybe('#setConfig - onchain', () => { -// const payment = BigNumber.from(1) -// const flatFee = BigNumber.from(2) -// const maxGas = BigNumber.from(6) -// const staleness = BigNumber.from(4) -// const ceiling = BigNumber.from(5) -// const newMinUpkeepSpend = BigNumber.from(9) -// const newMaxCheckDataSize = BigNumber.from(10000) -// const newMaxPerformDataSize = BigNumber.from(10000) -// const newMaxRevertDataSize = BigNumber.from(10000) -// const newMaxPerformGas = BigNumber.from(10000000) -// const fbGasEth = BigNumber.from(7) -// const fbLinkEth = BigNumber.from(8) -// const newTranscoder = randomAddress() -// const newRegistrars = [randomAddress(), randomAddress()] -// const upkeepManager = randomAddress() -// -// const newConfig: OnChainConfig = { -// paymentPremiumPPB: payment, -// flatFeeMicroLink: flatFee, -// checkGasLimit: maxGas, -// stalenessSeconds: staleness, -// gasCeilingMultiplier: ceiling, -// minUpkeepSpend: newMinUpkeepSpend, -// maxCheckDataSize: newMaxCheckDataSize, -// maxPerformDataSize: newMaxPerformDataSize, -// maxRevertDataSize: newMaxRevertDataSize, -// maxPerformGas: newMaxPerformGas, -// fallbackGasPrice: fbGasEth, -// fallbackLinkPrice: fbLinkEth, -// transcoder: newTranscoder, -// registrars: newRegistrars, -// upkeepPrivilegeManager: upkeepManager, -// } -// -// it('reverts when called by anyone but the proposed owner', async () => { -// await evmRevert( -// registry -// .connect(payee1) -// .setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// newConfig, -// offchainVersion, -// offchainBytes, -// ), -// 'Only callable by owner', -// ) -// }) -// -// it('reverts if signers or transmitters are the zero address', async () => { -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// [randomAddress(), randomAddress(), randomAddress(), zeroAddress], -// [ -// randomAddress(), -// randomAddress(), -// randomAddress(), -// randomAddress(), -// ], -// f, -// newConfig, -// offchainVersion, -// offchainBytes, -// ), -// 'InvalidSigner()', -// ) -// -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// [ -// randomAddress(), -// randomAddress(), -// randomAddress(), -// randomAddress(), -// ], -// [randomAddress(), randomAddress(), randomAddress(), zeroAddress], -// f, -// newConfig, -// offchainVersion, -// offchainBytes, -// ), -// 'InvalidTransmitter()', -// ) -// }) -// -// it('updates the onchainConfig and configDigest', async () => { -// const old = await registry.getState() -// const oldConfig = old.config -// const oldState = old.state -// assert.isTrue(paymentPremiumPPB.eq(oldConfig.paymentPremiumPPB)) -// assert.isTrue(flatFeeMicroLink.eq(oldConfig.flatFeeMicroLink)) -// assert.isTrue(stalenessSeconds.eq(oldConfig.stalenessSeconds)) -// assert.isTrue(gasCeilingMultiplier.eq(oldConfig.gasCeilingMultiplier)) -// -// await registry -// .connect(owner) -// .setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// newConfig, -// offchainVersion, -// offchainBytes, -// ) -// -// const updated = await registry.getState() -// const updatedConfig = updated.config -// const updatedState = updated.state -// assert.equal(updatedConfig.paymentPremiumPPB, payment.toNumber()) -// assert.equal(updatedConfig.flatFeeMicroLink, flatFee.toNumber()) -// assert.equal(updatedConfig.stalenessSeconds, staleness.toNumber()) -// assert.equal(updatedConfig.gasCeilingMultiplier, ceiling.toNumber()) -// assert.equal( -// updatedConfig.minUpkeepSpend.toString(), -// newMinUpkeepSpend.toString(), -// ) -// assert.equal( -// updatedConfig.maxCheckDataSize, -// newMaxCheckDataSize.toNumber(), -// ) -// assert.equal( -// updatedConfig.maxPerformDataSize, -// newMaxPerformDataSize.toNumber(), -// ) -// assert.equal( -// updatedConfig.maxRevertDataSize, -// newMaxRevertDataSize.toNumber(), -// ) -// assert.equal(updatedConfig.maxPerformGas, newMaxPerformGas.toNumber()) -// assert.equal(updatedConfig.checkGasLimit, maxGas.toNumber()) -// assert.equal( -// updatedConfig.fallbackGasPrice.toNumber(), -// fbGasEth.toNumber(), -// ) -// assert.equal( -// updatedConfig.fallbackLinkPrice.toNumber(), -// fbLinkEth.toNumber(), -// ) -// assert.equal(updatedState.latestEpoch, 0) -// -// assert(oldState.configCount + 1 == updatedState.configCount) -// assert( -// oldState.latestConfigBlockNumber != -// updatedState.latestConfigBlockNumber, -// ) -// assert(oldState.latestConfigDigest != updatedState.latestConfigDigest) -// -// assert.equal(updatedConfig.transcoder, newTranscoder) -// assert.deepEqual(updatedConfig.registrars, newRegistrars) -// assert.equal(updatedConfig.upkeepPrivilegeManager, upkeepManager) -// }) -// -// it('maintains paused state when config is changed', async () => { -// await registry.pause() -// const old = await registry.getState() -// assert.isTrue(old.state.paused) -// -// await registry -// .connect(owner) -// .setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// newConfig, -// offchainVersion, -// offchainBytes, -// ) -// -// const updated = await registry.getState() -// assert.isTrue(updated.state.paused) -// }) -// -// it('emits an event', async () => { -// const tx = await registry -// .connect(owner) -// .setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// newConfig, -// offchainVersion, -// offchainBytes, -// ) -// await expect(tx).to.emit(registry, 'ConfigSet') -// }) -// }) -// -// describe('#setConfig - offchain', () => { -// let newKeepers: string[] -// -// beforeEach(async () => { -// newKeepers = [ -// await personas.Eddy.getAddress(), -// await personas.Nick.getAddress(), -// await personas.Neil.getAddress(), -// await personas.Carol.getAddress(), -// ] -// }) -// -// it('reverts when called by anyone but the owner', async () => { -// await evmRevert( -// registry -// .connect(payee1) -// .setConfigTypeSafe( -// newKeepers, -// newKeepers, -// f, -// config, -// offchainVersion, -// offchainBytes, -// ), -// 'Only callable by owner', -// ) -// }) -// -// it('reverts if too many keeperAddresses set', async () => { -// for (let i = 0; i < 40; i++) { -// newKeepers.push(randomAddress()) -// } -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// newKeepers, -// newKeepers, -// f, -// config, -// offchainVersion, -// offchainBytes, -// ), -// 'TooManyOracles()', -// ) -// }) -// -// it('reverts if f=0', async () => { -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// newKeepers, -// newKeepers, -// 0, -// config, -// offchainVersion, -// offchainBytes, -// ), -// 'IncorrectNumberOfFaultyOracles()', -// ) -// }) -// -// it('reverts if signers != transmitters length', async () => { -// const signers = [randomAddress()] -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// signers, -// newKeepers, -// f, -// config, -// offchainVersion, -// offchainBytes, -// ), -// 'IncorrectNumberOfSigners()', -// ) -// }) -// -// it('reverts if signers <= 3f', async () => { -// newKeepers.pop() -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// newKeepers, -// newKeepers, -// f, -// config, -// offchainVersion, -// offchainBytes, -// ), -// 'IncorrectNumberOfSigners()', -// ) -// }) -// -// it('reverts on repeated signers', async () => { -// const newSigners = [ -// await personas.Eddy.getAddress(), -// await personas.Eddy.getAddress(), -// await personas.Eddy.getAddress(), -// await personas.Eddy.getAddress(), -// ] -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// newSigners, -// newKeepers, -// f, -// config, -// offchainVersion, -// offchainBytes, -// ), -// 'RepeatedSigner()', -// ) -// }) -// -// it('reverts on repeated transmitters', async () => { -// const newTransmitters = [ -// await personas.Eddy.getAddress(), -// await personas.Eddy.getAddress(), -// await personas.Eddy.getAddress(), -// await personas.Eddy.getAddress(), -// ] -// await evmRevert( -// registry -// .connect(owner) -// .setConfigTypeSafe( -// newKeepers, -// newTransmitters, -// f, -// config, -// offchainVersion, -// offchainBytes, -// ), -// 'RepeatedTransmitter()', -// ) -// }) -// -// itMaybe('stores new config and emits event', async () => { -// // Perform an upkeep so that totalPremium is updated -// await registry.connect(admin).addFunds(upkeepId, toWei('100')) -// let tx = await getTransmitTx(registry, keeper1, [upkeepId]) -// await tx.wait() -// -// const newOffChainVersion = BigNumber.from('2') -// const newOffChainConfig = '0x1122' -// -// const old = await registry.getState() -// const oldState = old.state -// assert(oldState.totalPremium.gt(BigNumber.from('0'))) -// -// const newSigners = newKeepers -// tx = await registry -// .connect(owner) -// .setConfigTypeSafe( -// newSigners, -// newKeepers, -// f, -// config, -// newOffChainVersion, -// newOffChainConfig, -// ) -// -// const updated = await registry.getState() -// const updatedState = updated.state -// assert(oldState.totalPremium.eq(updatedState.totalPremium)) -// -// // Old signer addresses which are not in new signers should be non active -// for (let i = 0; i < signerAddresses.length; i++) { -// const signer = signerAddresses[i] -// if (!newSigners.includes(signer)) { -// assert((await registry.getSignerInfo(signer)).active == false) -// assert((await registry.getSignerInfo(signer)).index == 0) -// } -// } -// // New signer addresses should be active -// for (let i = 0; i < newSigners.length; i++) { -// const signer = newSigners[i] -// assert((await registry.getSignerInfo(signer)).active == true) -// assert((await registry.getSignerInfo(signer)).index == i) -// } -// // Old transmitter addresses which are not in new transmitter should be non active, update lastCollected but retain other info -// for (let i = 0; i < keeperAddresses.length; i++) { -// const transmitter = keeperAddresses[i] -// if (!newKeepers.includes(transmitter)) { -// assert( -// (await registry.getTransmitterInfo(transmitter)).active == false, -// ) -// assert((await registry.getTransmitterInfo(transmitter)).index == i) -// assert( -// (await registry.getTransmitterInfo(transmitter)).lastCollected.eq( -// oldState.totalPremium.sub( -// oldState.totalPremium.mod(keeperAddresses.length), -// ), -// ), -// ) -// } -// } -// // New transmitter addresses should be active -// for (let i = 0; i < newKeepers.length; i++) { -// const transmitter = newKeepers[i] -// assert((await registry.getTransmitterInfo(transmitter)).active == true) -// assert((await registry.getTransmitterInfo(transmitter)).index == i) -// assert( -// (await registry.getTransmitterInfo(transmitter)).lastCollected.eq( -// oldState.totalPremium, -// ), -// ) -// } -// -// // config digest should be updated -// assert(oldState.configCount + 1 == updatedState.configCount) -// assert( -// oldState.latestConfigBlockNumber != -// updatedState.latestConfigBlockNumber, -// ) -// assert(oldState.latestConfigDigest != updatedState.latestConfigDigest) -// -// //New config should be updated -// assert.deepEqual(updated.signers, newKeepers) -// assert.deepEqual(updated.transmitters, newKeepers) -// -// // Event should have been emitted -// await expect(tx).to.emit(registry, 'ConfigSet') -// }) -// }) -// -// describe('#setPeerRegistryMigrationPermission() / #getPeerRegistryMigrationPermission()', () => { -// const peer = randomAddress() -// it('allows the owner to set the peer registries', async () => { -// let permission = await registry.getPeerRegistryMigrationPermission(peer) -// expect(permission).to.equal(0) -// await registry.setPeerRegistryMigrationPermission(peer, 1) -// permission = await registry.getPeerRegistryMigrationPermission(peer) -// expect(permission).to.equal(1) -// await registry.setPeerRegistryMigrationPermission(peer, 2) -// permission = await registry.getPeerRegistryMigrationPermission(peer) -// expect(permission).to.equal(2) -// await registry.setPeerRegistryMigrationPermission(peer, 0) -// permission = await registry.getPeerRegistryMigrationPermission(peer) -// expect(permission).to.equal(0) -// }) -// it('reverts if passed an unsupported permission', async () => { -// await expect( -// registry.connect(admin).setPeerRegistryMigrationPermission(peer, 10), -// ).to.be.reverted -// }) -// it('reverts if not called by the owner', async () => { -// await expect( -// registry.connect(admin).setPeerRegistryMigrationPermission(peer, 1), -// ).to.be.revertedWith('Only callable by owner') -// }) -// }) -// -// describe('#registerUpkeep', () => { -// it('reverts when registry is paused', async () => { -// await registry.connect(owner).pause() -// await evmRevert( -// registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), emptyBytes, '0x'), -// 'RegistryPaused()', -// ) -// }) -// -// it('reverts if the target is not a contract', async () => { -// await evmRevert( -// registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](zeroAddress, performGas, await admin.getAddress(), emptyBytes, '0x'), -// 'NotAContract()', -// ) -// }) -// -// it('reverts if called by a non-owner', async () => { -// await evmRevert( -// registry -// .connect(keeper1) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), emptyBytes, '0x'), -// 'OnlyCallableByOwnerOrRegistrar()', -// ) -// }) -// -// it('reverts if execute gas is too low', async () => { -// await evmRevert( -// registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, 2299, await admin.getAddress(), emptyBytes, '0x'), -// 'GasLimitOutsideRange()', -// ) -// }) -// -// it('reverts if execute gas is too high', async () => { -// await evmRevert( -// registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, 5000001, await admin.getAddress(), emptyBytes, '0x'), -// 'GasLimitOutsideRange()', -// ) -// }) -// -// it('reverts if checkData is too long', async () => { -// let longBytes = '0x' -// for (let i = 0; i < 10000; i++) { -// longBytes += '1' -// } -// await evmRevert( -// registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), longBytes, '0x'), -// 'CheckDataExceedsLimit()', -// ) -// }) -// -// it('creates a record of the registration', async () => { -// const performGases = [100000, 500000] -// const checkDatas = [emptyBytes, '0x12'] -// -// for (let jdx = 0; jdx < performGases.length; jdx++) { -// const performGas = performGases[jdx] -// for (let kdx = 0; kdx < checkDatas.length; kdx++) { -// const checkData = checkDatas[kdx] -// const tx = await registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), checkData, '0x') -// -// //confirm the upkeep details and verify emitted events -// const testUpkeepId = await getUpkeepID(tx) -// await expect(tx) -// .to.emit(registry, 'UpkeepRegistered') -// .withArgs(testUpkeepId, performGas, await admin.getAddress()) -// -// await expect(tx) -// .to.emit(registry, 'UpkeepCheckDataSet') -// .withArgs(testUpkeepId, checkData) -// await expect(tx) -// .to.emit(registry, 'UpkeepTriggerConfigSet') -// .withArgs(testUpkeepId, '0x') -// -// const registration = await registry.getUpkeep(testUpkeepId) -// -// assert.equal(mock.address, registration.target) -// assert.notEqual( -// ethers.constants.AddressZero, -// await registry.getForwarder(testUpkeepId), -// ) -// assert.equal( -// performGas.toString(), -// registration.performGas.toString(), -// ) -// assert.equal(await admin.getAddress(), registration.admin) -// assert.equal(0, registration.balance.toNumber()) -// assert.equal(0, registration.amountSpent.toNumber()) -// assert.equal(0, registration.lastPerformedBlockNumber) -// assert.equal(checkData, registration.checkData) -// assert.equal(registration.paused, false) -// assert.equal(registration.offchainConfig, '0x') -// assert(registration.maxValidBlocknumber.eq('0xffffffff')) -// } -// } -// }) -// }) -// -// describe('#pauseUpkeep', () => { -// it('reverts if the registration does not exist', async () => { -// await evmRevert( -// registry.connect(keeper1).pauseUpkeep(upkeepId.add(1)), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if the upkeep is already canceled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// await evmRevert( -// registry.connect(admin).pauseUpkeep(upkeepId), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('reverts if the upkeep is already paused', async () => { -// await registry.connect(admin).pauseUpkeep(upkeepId) -// -// await evmRevert( -// registry.connect(admin).pauseUpkeep(upkeepId), -// 'OnlyUnpausedUpkeep()', -// ) -// }) -// -// it('reverts if the caller is not the upkeep admin', async () => { -// await evmRevert( -// registry.connect(keeper1).pauseUpkeep(upkeepId), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('pauses the upkeep and emits an event', async () => { -// const tx = await registry.connect(admin).pauseUpkeep(upkeepId) -// await expect(tx).to.emit(registry, 'UpkeepPaused').withArgs(upkeepId) -// -// const registration = await registry.getUpkeep(upkeepId) -// assert.equal(registration.paused, true) -// }) -// }) -// -// describe('#unpauseUpkeep', () => { -// it('reverts if the registration does not exist', async () => { -// await evmRevert( -// registry.connect(keeper1).unpauseUpkeep(upkeepId.add(1)), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if the upkeep is already canceled', async () => { -// await registry.connect(owner).cancelUpkeep(upkeepId) -// -// await evmRevert( -// registry.connect(admin).unpauseUpkeep(upkeepId), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('marks the contract as paused', async () => { -// assert.isFalse((await registry.getState()).state.paused) -// -// await registry.connect(owner).pause() -// -// assert.isTrue((await registry.getState()).state.paused) -// }) -// -// it('reverts if the upkeep is not paused', async () => { -// await evmRevert( -// registry.connect(admin).unpauseUpkeep(upkeepId), -// 'OnlyPausedUpkeep()', -// ) -// }) -// -// it('reverts if the caller is not the upkeep admin', async () => { -// await registry.connect(admin).pauseUpkeep(upkeepId) -// -// const registration = await registry.getUpkeep(upkeepId) -// -// assert.equal(registration.paused, true) -// -// await evmRevert( -// registry.connect(keeper1).unpauseUpkeep(upkeepId), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('unpauses the upkeep and emits an event', async () => { -// const originalCount = (await registry.getActiveUpkeepIDs(0, 0)).length -// -// await registry.connect(admin).pauseUpkeep(upkeepId) -// -// const tx = await registry.connect(admin).unpauseUpkeep(upkeepId) -// -// await expect(tx).to.emit(registry, 'UpkeepUnpaused').withArgs(upkeepId) -// -// const registration = await registry.getUpkeep(upkeepId) -// assert.equal(registration.paused, false) -// -// const upkeepIds = await registry.getActiveUpkeepIDs(0, 0) -// assert.equal(upkeepIds.length, originalCount) -// }) -// }) -// -// describe('#setUpkeepCheckData', () => { -// it('reverts if the registration does not exist', async () => { -// await evmRevert( -// registry -// .connect(keeper1) -// .setUpkeepCheckData(upkeepId.add(1), randomBytes), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if the caller is not upkeep admin', async () => { -// await evmRevert( -// registry.connect(keeper1).setUpkeepCheckData(upkeepId, randomBytes), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if the upkeep is cancelled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// await evmRevert( -// registry.connect(admin).setUpkeepCheckData(upkeepId, randomBytes), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('is allowed to update on paused upkeep', async () => { -// await registry.connect(admin).pauseUpkeep(upkeepId) -// await registry.connect(admin).setUpkeepCheckData(upkeepId, randomBytes) -// -// const registration = await registry.getUpkeep(upkeepId) -// assert.equal(randomBytes, registration.checkData) -// }) -// -// it('reverts if new data exceeds limit', async () => { -// let longBytes = '0x' -// for (let i = 0; i < 10000; i++) { -// longBytes += '1' -// } -// -// await evmRevert( -// registry.connect(admin).setUpkeepCheckData(upkeepId, longBytes), -// 'CheckDataExceedsLimit()', -// ) -// }) -// -// it('updates the upkeep check data and emits an event', async () => { -// const tx = await registry -// .connect(admin) -// .setUpkeepCheckData(upkeepId, randomBytes) -// await expect(tx) -// .to.emit(registry, 'UpkeepCheckDataSet') -// .withArgs(upkeepId, randomBytes) -// -// const registration = await registry.getUpkeep(upkeepId) -// assert.equal(randomBytes, registration.checkData) -// }) -// }) -// -// describe('#setUpkeepGasLimit', () => { -// const newGasLimit = BigNumber.from('300000') -// -// it('reverts if the registration does not exist', async () => { -// await evmRevert( -// registry.connect(admin).setUpkeepGasLimit(upkeepId.add(1), newGasLimit), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if the upkeep is canceled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// await evmRevert( -// registry.connect(admin).setUpkeepGasLimit(upkeepId, newGasLimit), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('reverts if called by anyone but the admin', async () => { -// await evmRevert( -// registry.connect(owner).setUpkeepGasLimit(upkeepId, newGasLimit), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if new gas limit is out of bounds', async () => { -// await evmRevert( -// registry -// .connect(admin) -// .setUpkeepGasLimit(upkeepId, BigNumber.from('100')), -// 'GasLimitOutsideRange()', -// ) -// await evmRevert( -// registry -// .connect(admin) -// .setUpkeepGasLimit(upkeepId, BigNumber.from('6000000')), -// 'GasLimitOutsideRange()', -// ) -// }) -// -// it('updates the gas limit successfully', async () => { -// const initialGasLimit = (await registry.getUpkeep(upkeepId)).performGas -// assert.equal(initialGasLimit, performGas.toNumber()) -// await registry.connect(admin).setUpkeepGasLimit(upkeepId, newGasLimit) -// const updatedGasLimit = (await registry.getUpkeep(upkeepId)).performGas -// assert.equal(updatedGasLimit, newGasLimit.toNumber()) -// }) -// -// it('emits a log', async () => { -// const tx = await registry -// .connect(admin) -// .setUpkeepGasLimit(upkeepId, newGasLimit) -// await expect(tx) -// .to.emit(registry, 'UpkeepGasLimitSet') -// .withArgs(upkeepId, newGasLimit) -// }) -// }) -// -// describe('#setUpkeepOffchainConfig', () => { -// const newConfig = '0xc0ffeec0ffee' -// -// it('reverts if the registration does not exist', async () => { -// await evmRevert( -// registry -// .connect(admin) -// .setUpkeepOffchainConfig(upkeepId.add(1), newConfig), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if the upkeep is canceled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// await evmRevert( -// registry.connect(admin).setUpkeepOffchainConfig(upkeepId, newConfig), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('reverts if called by anyone but the admin', async () => { -// await evmRevert( -// registry.connect(owner).setUpkeepOffchainConfig(upkeepId, newConfig), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('updates the config successfully', async () => { -// const initialConfig = (await registry.getUpkeep(upkeepId)).offchainConfig -// assert.equal(initialConfig, '0x') -// await registry.connect(admin).setUpkeepOffchainConfig(upkeepId, newConfig) -// const updatedConfig = (await registry.getUpkeep(upkeepId)).offchainConfig -// assert.equal(newConfig, updatedConfig) -// }) -// -// it('emits a log', async () => { -// const tx = await registry -// .connect(admin) -// .setUpkeepOffchainConfig(upkeepId, newConfig) -// await expect(tx) -// .to.emit(registry, 'UpkeepOffchainConfigSet') -// .withArgs(upkeepId, newConfig) -// }) -// }) -// -// describe('#setUpkeepTriggerConfig', () => { -// const newConfig = '0xdeadbeef' -// -// it('reverts if the registration does not exist', async () => { -// await evmRevert( -// registry -// .connect(admin) -// .setUpkeepTriggerConfig(upkeepId.add(1), newConfig), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts if the upkeep is canceled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// await evmRevert( -// registry.connect(admin).setUpkeepTriggerConfig(upkeepId, newConfig), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('reverts if called by anyone but the admin', async () => { -// await evmRevert( -// registry.connect(owner).setUpkeepTriggerConfig(upkeepId, newConfig), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('emits a log', async () => { -// const tx = await registry -// .connect(admin) -// .setUpkeepTriggerConfig(upkeepId, newConfig) -// await expect(tx) -// .to.emit(registry, 'UpkeepTriggerConfigSet') -// .withArgs(upkeepId, newConfig) -// }) -// }) -// -// describe('#transferUpkeepAdmin', () => { -// it('reverts when called by anyone but the current upkeep admin', async () => { -// await evmRevert( -// registry -// .connect(payee1) -// .transferUpkeepAdmin(upkeepId, await payee2.getAddress()), -// 'OnlyCallableByAdmin()', -// ) -// }) -// -// it('reverts when transferring to self', async () => { -// await evmRevert( -// registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await admin.getAddress()), -// 'ValueNotChanged()', -// ) -// }) -// -// it('reverts when the upkeep is cancelled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// await evmRevert( -// registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await keeper1.getAddress()), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('allows cancelling transfer by reverting to zero address', async () => { -// await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) -// const tx = await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, ethers.constants.AddressZero) -// -// await expect(tx) -// .to.emit(registry, 'UpkeepAdminTransferRequested') -// .withArgs( -// upkeepId, -// await admin.getAddress(), -// ethers.constants.AddressZero, -// ) -// }) -// -// it('does not change the upkeep admin', async () => { -// await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) -// -// const upkeep = await registry.getUpkeep(upkeepId) -// assert.equal(await admin.getAddress(), upkeep.admin) -// }) -// -// it('emits an event announcing the new upkeep admin', async () => { -// const tx = await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) -// -// await expect(tx) -// .to.emit(registry, 'UpkeepAdminTransferRequested') -// .withArgs(upkeepId, await admin.getAddress(), await payee1.getAddress()) -// }) -// -// it('does not emit an event when called with the same proposed upkeep admin', async () => { -// await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) -// -// const tx = await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) -// const receipt = await tx.wait() -// assert.equal(0, receipt.logs.length) -// }) -// }) -// -// describe('#acceptUpkeepAdmin', () => { -// beforeEach(async () => { -// // Start admin transfer to payee1 -// await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) -// }) -// -// it('reverts when not called by the proposed upkeep admin', async () => { -// await evmRevert( -// registry.connect(payee2).acceptUpkeepAdmin(upkeepId), -// 'OnlyCallableByProposedAdmin()', -// ) -// }) -// -// it('reverts when the upkeep is cancelled', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// await evmRevert( -// registry.connect(payee1).acceptUpkeepAdmin(upkeepId), -// 'UpkeepCancelled()', -// ) -// }) -// -// it('does change the admin', async () => { -// await registry.connect(payee1).acceptUpkeepAdmin(upkeepId) -// -// const upkeep = await registry.getUpkeep(upkeepId) -// assert.equal(await payee1.getAddress(), upkeep.admin) -// }) -// -// it('emits an event announcing the new upkeep admin', async () => { -// const tx = await registry.connect(payee1).acceptUpkeepAdmin(upkeepId) -// await expect(tx) -// .to.emit(registry, 'UpkeepAdminTransferred') -// .withArgs(upkeepId, await admin.getAddress(), await payee1.getAddress()) -// }) -// }) -// -// describe('#withdrawOwnerFunds', () => { -// it('can only be called by owner', async () => { -// await evmRevert( -// registry.connect(keeper1).withdrawOwnerFunds(), -// 'Only callable by owner', -// ) -// }) -// -// itMaybe('withdraws the collected fees to owner', async () => { -// await registry.connect(admin).addFunds(upkeepId, toWei('100')) -// // Very high min spend, whole balance as cancellation fees -// const minUpkeepSpend = toWei('1000') -// await registry.connect(owner).setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// { -// paymentPremiumPPB, -// flatFeeMicroLink, -// checkGasLimit, -// stalenessSeconds, -// gasCeilingMultiplier, -// minUpkeepSpend, -// maxCheckDataSize, -// maxPerformDataSize, -// maxRevertDataSize, -// maxPerformGas, -// fallbackGasPrice, -// fallbackLinkPrice, -// transcoder: transcoder.address, -// registrars: [], -// upkeepPrivilegeManager: upkeepManager, -// }, -// offchainVersion, -// offchainBytes, -// ) -// const upkeepBalance = (await registry.getUpkeep(upkeepId)).balance -// const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) -// -// await registry.connect(owner).cancelUpkeep(upkeepId) -// -// // Transfered to owner balance on registry -// let ownerRegistryBalance = (await registry.getState()).state -// .ownerLinkBalance -// assert.isTrue(ownerRegistryBalance.eq(upkeepBalance)) -// -// // Now withdraw -// await registry.connect(owner).withdrawOwnerFunds() -// -// ownerRegistryBalance = (await registry.getState()).state.ownerLinkBalance -// const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) -// -// // Owner registry balance should be changed to 0 -// assert.isTrue(ownerRegistryBalance.eq(BigNumber.from('0'))) -// -// // Owner should be credited with the balance -// assert.isTrue(ownerBefore.add(upkeepBalance).eq(ownerAfter)) -// }) -// }) -// -// describe('#transferPayeeship', () => { -// it('reverts when called by anyone but the current payee', async () => { -// await evmRevert( -// registry -// .connect(payee2) -// .transferPayeeship( -// await keeper1.getAddress(), -// await payee2.getAddress(), -// ), -// 'OnlyCallableByPayee()', -// ) -// }) -// -// it('reverts when transferring to self', async () => { -// await evmRevert( -// registry -// .connect(payee1) -// .transferPayeeship( -// await keeper1.getAddress(), -// await payee1.getAddress(), -// ), -// 'ValueNotChanged()', -// ) -// }) -// -// it('does not change the payee', async () => { -// await registry -// .connect(payee1) -// .transferPayeeship( -// await keeper1.getAddress(), -// await payee2.getAddress(), -// ) -// -// const info = await registry.getTransmitterInfo(await keeper1.getAddress()) -// assert.equal(await payee1.getAddress(), info.payee) -// }) -// -// it('emits an event announcing the new payee', async () => { -// const tx = await registry -// .connect(payee1) -// .transferPayeeship( -// await keeper1.getAddress(), -// await payee2.getAddress(), -// ) -// await expect(tx) -// .to.emit(registry, 'PayeeshipTransferRequested') -// .withArgs( -// await keeper1.getAddress(), -// await payee1.getAddress(), -// await payee2.getAddress(), -// ) -// }) -// -// it('does not emit an event when called with the same proposal', async () => { -// await registry -// .connect(payee1) -// .transferPayeeship( -// await keeper1.getAddress(), -// await payee2.getAddress(), -// ) -// -// const tx = await registry -// .connect(payee1) -// .transferPayeeship( -// await keeper1.getAddress(), -// await payee2.getAddress(), -// ) -// const receipt = await tx.wait() -// assert.equal(0, receipt.logs.length) -// }) -// }) -// -// describe('#acceptPayeeship', () => { -// beforeEach(async () => { -// await registry -// .connect(payee1) -// .transferPayeeship( -// await keeper1.getAddress(), -// await payee2.getAddress(), -// ) -// }) -// -// it('reverts when called by anyone but the proposed payee', async () => { -// await evmRevert( -// registry.connect(payee1).acceptPayeeship(await keeper1.getAddress()), -// 'OnlyCallableByProposedPayee()', -// ) -// }) -// -// it('emits an event announcing the new payee', async () => { -// const tx = await registry -// .connect(payee2) -// .acceptPayeeship(await keeper1.getAddress()) -// await expect(tx) -// .to.emit(registry, 'PayeeshipTransferred') -// .withArgs( -// await keeper1.getAddress(), -// await payee1.getAddress(), -// await payee2.getAddress(), -// ) -// }) -// -// it('does change the payee', async () => { -// await registry.connect(payee2).acceptPayeeship(await keeper1.getAddress()) -// -// const info = await registry.getTransmitterInfo(await keeper1.getAddress()) -// assert.equal(await payee2.getAddress(), info.payee) -// }) -// }) -// -// describe('#pause', () => { -// it('reverts if called by a non-owner', async () => { -// await evmRevert( -// registry.connect(keeper1).pause(), -// 'Only callable by owner', -// ) -// }) -// -// it('marks the contract as paused', async () => { -// assert.isFalse((await registry.getState()).state.paused) -// -// await registry.connect(owner).pause() -// -// assert.isTrue((await registry.getState()).state.paused) -// }) -// -// it('Does not allow transmits when paused', async () => { -// await registry.connect(owner).pause() -// -// await evmRevert( -// getTransmitTx(registry, keeper1, [upkeepId]), -// 'RegistryPaused()', -// ) -// }) -// -// it('Does not allow creation of new upkeeps when paused', async () => { -// await registry.connect(owner).pause() -// -// await evmRevert( -// registry -// .connect(owner) -// [ -// 'registerUpkeep(address,uint32,address,bytes,bytes)' -// ](mock.address, performGas, await admin.getAddress(), emptyBytes, '0x'), -// 'RegistryPaused()', -// ) -// }) -// }) -// -// describe('#unpause', () => { -// beforeEach(async () => { -// await registry.connect(owner).pause() -// }) -// -// it('reverts if called by a non-owner', async () => { -// await evmRevert( -// registry.connect(keeper1).unpause(), -// 'Only callable by owner', -// ) -// }) -// -// it('marks the contract as not paused', async () => { -// assert.isTrue((await registry.getState()).state.paused) -// -// await registry.connect(owner).unpause() -// -// assert.isFalse((await registry.getState()).state.paused) -// }) -// }) -// -// describe('#migrateUpkeeps() / #receiveUpkeeps()', async () => { -// context('when permissions are set', () => { -// beforeEach(async () => { -// await linkToken.connect(owner).approve(registry.address, toWei('100')) -// await registry.connect(owner).addFunds(upkeepId, toWei('100')) -// await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 1) -// await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 2) -// }) -// -// it('migrates an upkeep', async () => { -// const offchainBytes = '0x987654abcd' -// await registry -// .connect(admin) -// .setUpkeepOffchainConfig(upkeepId, offchainBytes) -// const reg1Upkeep = await registry.getUpkeep(upkeepId) -// const forwarderAddress = await registry.getForwarder(upkeepId) -// expect(reg1Upkeep.balance).to.equal(toWei('100')) -// expect(reg1Upkeep.checkData).to.equal(randomBytes) -// expect(forwarderAddress).to.not.equal(ethers.constants.AddressZero) -// expect(reg1Upkeep.offchainConfig).to.equal(offchainBytes) -// expect((await registry.getState()).state.numUpkeeps).to.equal( -// numUpkeeps, -// ) -// const forwarder = await IAutomationForwarderFactory.connect( -// forwarderAddress, -// owner, -// ) -// expect(await forwarder.getRegistry()).to.equal(registry.address) -// // Set an upkeep admin transfer in progress too -// await registry -// .connect(admin) -// .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) -// -// // migrate -// await registry -// .connect(admin) -// .migrateUpkeeps([upkeepId], mgRegistry.address) -// expect((await registry.getState()).state.numUpkeeps).to.equal( -// numUpkeeps - 1, -// ) -// expect((await mgRegistry.getState()).state.numUpkeeps).to.equal(1) -// expect((await registry.getUpkeep(upkeepId)).balance).to.equal(0) -// expect((await registry.getUpkeep(upkeepId)).checkData).to.equal('0x') -// expect((await mgRegistry.getUpkeep(upkeepId)).balance).to.equal( -// toWei('100'), -// ) -// expect( -// (await mgRegistry.getState()).state.expectedLinkBalance, -// ).to.equal(toWei('100')) -// expect((await mgRegistry.getUpkeep(upkeepId)).checkData).to.equal( -// randomBytes, -// ) -// expect((await mgRegistry.getUpkeep(upkeepId)).offchainConfig).to.equal( -// offchainBytes, -// ) -// expect(await mgRegistry.getForwarder(upkeepId)).to.equal( -// forwarderAddress, -// ) -// // test that registry is updated on forwarder -// expect(await forwarder.getRegistry()).to.equal(mgRegistry.address) -// // migration will delete the upkeep and nullify admin transfer -// await expect( -// registry.connect(payee1).acceptUpkeepAdmin(upkeepId), -// ).to.be.revertedWith('UpkeepCancelled()') -// await expect( -// mgRegistry.connect(payee1).acceptUpkeepAdmin(upkeepId), -// ).to.be.revertedWith('OnlyCallableByProposedAdmin()') -// }) -// -// it('migrates a paused upkeep', async () => { -// expect((await registry.getUpkeep(upkeepId)).balance).to.equal( -// toWei('100'), -// ) -// expect((await registry.getUpkeep(upkeepId)).checkData).to.equal( -// randomBytes, -// ) -// expect((await registry.getState()).state.numUpkeeps).to.equal( -// numUpkeeps, -// ) -// await registry.connect(admin).pauseUpkeep(upkeepId) -// // verify the upkeep is paused -// expect((await registry.getUpkeep(upkeepId)).paused).to.equal(true) -// // migrate -// await registry -// .connect(admin) -// .migrateUpkeeps([upkeepId], mgRegistry.address) -// expect((await registry.getState()).state.numUpkeeps).to.equal( -// numUpkeeps - 1, -// ) -// expect((await mgRegistry.getState()).state.numUpkeeps).to.equal(1) -// expect((await registry.getUpkeep(upkeepId)).balance).to.equal(0) -// expect((await mgRegistry.getUpkeep(upkeepId)).balance).to.equal( -// toWei('100'), -// ) -// expect((await registry.getUpkeep(upkeepId)).checkData).to.equal('0x') -// expect((await mgRegistry.getUpkeep(upkeepId)).checkData).to.equal( -// randomBytes, -// ) -// expect( -// (await mgRegistry.getState()).state.expectedLinkBalance, -// ).to.equal(toWei('100')) -// // verify the upkeep is still paused after migration -// expect((await mgRegistry.getUpkeep(upkeepId)).paused).to.equal(true) -// }) -// -// it('emits an event on both contracts', async () => { -// expect((await registry.getUpkeep(upkeepId)).balance).to.equal( -// toWei('100'), -// ) -// expect((await registry.getUpkeep(upkeepId)).checkData).to.equal( -// randomBytes, -// ) -// expect((await registry.getState()).state.numUpkeeps).to.equal( -// numUpkeeps, -// ) -// const tx = registry -// .connect(admin) -// .migrateUpkeeps([upkeepId], mgRegistry.address) -// await expect(tx) -// .to.emit(registry, 'UpkeepMigrated') -// .withArgs(upkeepId, toWei('100'), mgRegistry.address) -// await expect(tx) -// .to.emit(mgRegistry, 'UpkeepReceived') -// .withArgs(upkeepId, toWei('100'), registry.address) -// }) -// -// it('is only migratable by the admin', async () => { -// await expect( -// registry -// .connect(owner) -// .migrateUpkeeps([upkeepId], mgRegistry.address), -// ).to.be.revertedWith('OnlyCallableByAdmin()') -// await registry -// .connect(admin) -// .migrateUpkeeps([upkeepId], mgRegistry.address) -// }) -// }) -// -// context('when permissions are not set', () => { -// it('reverts', async () => { -// // no permissions -// await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 0) -// await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 0) -// await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to -// .be.reverted -// // only outgoing permissions -// await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 1) -// await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 0) -// await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to -// .be.reverted -// // only incoming permissions -// await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 0) -// await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 2) -// await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to -// .be.reverted -// // permissions opposite direction -// await registry.setPeerRegistryMigrationPermission(mgRegistry.address, 2) -// await mgRegistry.setPeerRegistryMigrationPermission(registry.address, 1) -// await expect(registry.migrateUpkeeps([upkeepId], mgRegistry.address)).to -// .be.reverted -// }) -// }) -// }) -// -// describe('#setPayees', () => { -// const IGNORE_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF' -// -// it('reverts when not called by the owner', async () => { -// await evmRevert( -// registry.connect(keeper1).setPayees(payees), -// 'Only callable by owner', -// ) -// }) -// -// it('reverts with different numbers of payees than transmitters', async () => { -// await evmRevert( -// registry.connect(owner).setPayees([...payees, randomAddress()]), -// 'ParameterLengthError()', -// ) -// }) -// -// it('reverts if the payee is the zero address', async () => { -// await blankRegistry.connect(owner).setConfig(...baseConfig) // used to test initial config -// -// await evmRevert( -// blankRegistry // used to test initial config -// .connect(owner) -// .setPayees([ethers.constants.AddressZero, ...payees.slice(1)]), -// 'InvalidPayee()', -// ) -// }) -// -// itMaybe( -// 'sets the payees when exisitng payees are zero address', -// async () => { -// //Initial payees should be zero address -// await blankRegistry.connect(owner).setConfig(...baseConfig) // used to test initial config -// -// for (let i = 0; i < keeperAddresses.length; i++) { -// const payee = ( -// await blankRegistry.getTransmitterInfo(keeperAddresses[i]) -// ).payee // used to test initial config -// assert.equal(payee, zeroAddress) -// } -// -// await blankRegistry.connect(owner).setPayees(payees) // used to test initial config -// -// for (let i = 0; i < keeperAddresses.length; i++) { -// const payee = ( -// await blankRegistry.getTransmitterInfo(keeperAddresses[i]) -// ).payee -// assert.equal(payee, payees[i]) -// } -// }, -// ) -// -// it('does not change the payee if IGNORE_ADDRESS is used as payee', async () => { -// const signers = Array.from({ length: 5 }, randomAddress) -// const keepers = Array.from({ length: 5 }, randomAddress) -// const payees = Array.from({ length: 5 }, randomAddress) -// const newTransmitter = randomAddress() -// const newPayee = randomAddress() -// const ignoreAddresses = new Array(payees.length).fill(IGNORE_ADDRESS) -// const newPayees = [...ignoreAddresses, newPayee] -// // arbitrum registry -// // configure registry with 5 keepers // optimism registry -// await blankRegistry // used to test initial configurations -// .connect(owner) -// .setConfigTypeSafe( -// signers, -// keepers, -// f, -// config, -// offchainVersion, -// offchainBytes, -// ) -// // arbitrum registry -// // set initial payees // optimism registry -// await blankRegistry.connect(owner).setPayees(payees) // used to test initial configurations -// // arbitrum registry -// // add another keeper // optimism registry -// await blankRegistry // used to test initial configurations -// .connect(owner) -// .setConfigTypeSafe( -// [...signers, randomAddress()], -// [...keepers, newTransmitter], -// f, -// config, -// offchainVersion, -// offchainBytes, -// ) -// // arbitrum registry -// // update payee list // optimism registry // arbitrum registry -// await blankRegistry.connect(owner).setPayees(newPayees) // used to test initial configurations // optimism registry -// const ignored = await blankRegistry.getTransmitterInfo(newTransmitter) // used to test initial configurations -// assert.equal(newPayee, ignored.payee) -// assert.equal(true, ignored.active) -// }) -// -// it('reverts if payee is non zero and owner tries to change payee', async () => { -// const newPayees = [randomAddress(), ...payees.slice(1)] -// -// await evmRevert( -// registry.connect(owner).setPayees(newPayees), -// 'InvalidPayee()', -// ) -// }) -// -// it('emits events for every payee added and removed', async () => { -// const tx = await registry.connect(owner).setPayees(payees) -// await expect(tx) -// .to.emit(registry, 'PayeesUpdated') -// .withArgs(keeperAddresses, payees) -// }) -// }) -// -// describe('#cancelUpkeep', () => { -// it('reverts if the ID is not valid', async () => { -// await evmRevert( -// registry.connect(owner).cancelUpkeep(upkeepId.add(1)), -// 'CannotCancel()', -// ) -// }) -// -// it('reverts if called by a non-owner/non-admin', async () => { -// await evmRevert( -// registry.connect(keeper1).cancelUpkeep(upkeepId), -// 'OnlyCallableByOwnerOrAdmin()', -// ) -// }) -// -// describe('when called by the owner', async () => { -// it('sets the registration to invalid immediately', async () => { -// const tx = await registry.connect(owner).cancelUpkeep(upkeepId) -// const receipt = await tx.wait() -// const registration = await registry.getUpkeep(upkeepId) -// assert.equal( -// registration.maxValidBlocknumber.toNumber(), -// receipt.blockNumber, -// ) -// }) -// -// it('emits an event', async () => { -// const tx = await registry.connect(owner).cancelUpkeep(upkeepId) -// const receipt = await tx.wait() -// await expect(tx) -// .to.emit(registry, 'UpkeepCanceled') -// .withArgs(upkeepId, BigNumber.from(receipt.blockNumber)) -// }) -// -// it('immediately prevents upkeep', async () => { -// await registry.connect(owner).cancelUpkeep(upkeepId) -// -// const tx = await getTransmitTx(registry, keeper1, [upkeepId]) -// const receipt = await tx.wait() -// const cancelledUpkeepReportLogs = -// parseCancelledUpkeepReportLogs(receipt) -// // exactly 1 CancelledUpkeepReport log should be emitted -// assert.equal(cancelledUpkeepReportLogs.length, 1) -// }) -// -// it('does not revert if reverts if called multiple times', async () => { -// await registry.connect(owner).cancelUpkeep(upkeepId) -// await evmRevert( -// registry.connect(owner).cancelUpkeep(upkeepId), -// 'CannotCancel()', -// ) -// }) -// -// describe('when called by the owner when the admin has just canceled', () => { -// let oldExpiration: BigNumber -// -// beforeEach(async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// const registration = await registry.getUpkeep(upkeepId) -// oldExpiration = registration.maxValidBlocknumber -// }) -// -// it('allows the owner to cancel it more quickly', async () => { -// await registry.connect(owner).cancelUpkeep(upkeepId) -// -// const registration = await registry.getUpkeep(upkeepId) -// const newExpiration = registration.maxValidBlocknumber -// assert.isTrue(newExpiration.lt(oldExpiration)) -// }) -// }) -// }) -// -// describe('when called by the admin', async () => { -// it('reverts if called again by the admin', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// await evmRevert( -// registry.connect(admin).cancelUpkeep(upkeepId), -// 'CannotCancel()', -// ) -// }) -// -// it('reverts if called by the owner after the timeout', async () => { -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// for (let i = 0; i < cancellationDelay; i++) { -// await ethers.provider.send('evm_mine', []) -// } -// -// await evmRevert( -// registry.connect(owner).cancelUpkeep(upkeepId), -// 'CannotCancel()', -// ) -// }) -// -// it('sets the registration to invalid in 50 blocks', async () => { -// const tx = await registry.connect(admin).cancelUpkeep(upkeepId) -// const receipt = await tx.wait() -// const registration = await registry.getUpkeep(upkeepId) -// assert.equal( -// registration.maxValidBlocknumber.toNumber(), -// receipt.blockNumber + 50, -// ) -// }) -// -// it('emits an event', async () => { -// const tx = await registry.connect(admin).cancelUpkeep(upkeepId) -// const receipt = await tx.wait() -// await expect(tx) -// .to.emit(registry, 'UpkeepCanceled') -// .withArgs( -// upkeepId, -// BigNumber.from(receipt.blockNumber + cancellationDelay), -// ) -// }) -// -// it('immediately prevents upkeep', async () => { -// await linkToken.connect(owner).approve(registry.address, toWei('100')) -// await registry.connect(owner).addFunds(upkeepId, toWei('100')) -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// await getTransmitTx(registry, keeper1, [upkeepId]) -// -// for (let i = 0; i < cancellationDelay; i++) { -// await ethers.provider.send('evm_mine', []) -// } -// -// const tx = await getTransmitTx(registry, keeper1, [upkeepId]) -// -// const receipt = await tx.wait() -// const cancelledUpkeepReportLogs = -// parseCancelledUpkeepReportLogs(receipt) -// // exactly 1 CancelledUpkeepReport log should be emitted -// assert.equal(cancelledUpkeepReportLogs.length, 1) -// }) -// -// describeMaybe('when an upkeep has been performed', async () => { -// beforeEach(async () => { -// await linkToken.connect(owner).approve(registry.address, toWei('100')) -// await registry.connect(owner).addFunds(upkeepId, toWei('100')) -// await getTransmitTx(registry, keeper1, [upkeepId]) -// }) -// -// it('deducts a cancellation fee from the upkeep and gives to owner', async () => { -// const minUpkeepSpend = toWei('10') -// -// await registry.connect(owner).setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// { -// paymentPremiumPPB, -// flatFeeMicroLink, -// checkGasLimit, -// stalenessSeconds, -// gasCeilingMultiplier, -// minUpkeepSpend, -// maxCheckDataSize, -// maxPerformDataSize, -// maxRevertDataSize, -// maxPerformGas, -// fallbackGasPrice, -// fallbackLinkPrice, -// transcoder: transcoder.address, -// registrars: [], -// upkeepPrivilegeManager: upkeepManager, -// }, -// offchainVersion, -// offchainBytes, -// ) -// -// const payee1Before = await linkToken.balanceOf( -// await payee1.getAddress(), -// ) -// const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance -// const ownerBefore = (await registry.getState()).state.ownerLinkBalance -// -// const amountSpent = toWei('100').sub(upkeepBefore) -// const cancellationFee = minUpkeepSpend.sub(amountSpent) -// -// await registry.connect(admin).cancelUpkeep(upkeepId) -// -// const payee1After = await linkToken.balanceOf( -// await payee1.getAddress(), -// ) -// const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance -// const ownerAfter = (await registry.getState()).state.ownerLinkBalance -// -// // post upkeep balance should be previous balance minus cancellation fee -// assert.isTrue(upkeepBefore.sub(cancellationFee).eq(upkeepAfter)) -// // payee balance should not change -// assert.isTrue(payee1Before.eq(payee1After)) -// // owner should receive the cancellation fee -// assert.isTrue(ownerAfter.sub(ownerBefore).eq(cancellationFee)) -// }) -// -// it('deducts up to balance as cancellation fee', async () => { -// // Very high min spend, should deduct whole balance as cancellation fees -// const minUpkeepSpend = toWei('1000') -// await registry.connect(owner).setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// { -// paymentPremiumPPB, -// flatFeeMicroLink, -// checkGasLimit, -// stalenessSeconds, -// gasCeilingMultiplier, -// minUpkeepSpend, -// maxCheckDataSize, -// maxPerformDataSize, -// maxRevertDataSize, -// maxPerformGas, -// fallbackGasPrice, -// fallbackLinkPrice, -// transcoder: transcoder.address, -// registrars: [], -// upkeepPrivilegeManager: upkeepManager, -// }, -// offchainVersion, -// offchainBytes, -// ) -// const payee1Before = await linkToken.balanceOf( -// await payee1.getAddress(), -// ) -// const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance -// const ownerBefore = (await registry.getState()).state.ownerLinkBalance -// -// await registry.connect(admin).cancelUpkeep(upkeepId) -// const payee1After = await linkToken.balanceOf( -// await payee1.getAddress(), -// ) -// const ownerAfter = (await registry.getState()).state.ownerLinkBalance -// const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance -// -// // all upkeep balance is deducted for cancellation fee -// assert.equal(0, upkeepAfter.toNumber()) -// // payee balance should not change -// assert.isTrue(payee1After.eq(payee1Before)) -// // all upkeep balance is transferred to the owner -// assert.isTrue(ownerAfter.sub(ownerBefore).eq(upkeepBefore)) -// }) -// -// it('does not deduct cancellation fee if more than minUpkeepSpend is spent', async () => { -// // Very low min spend, already spent in one perform upkeep -// const minUpkeepSpend = BigNumber.from(420) -// await registry.connect(owner).setConfigTypeSafe( -// signerAddresses, -// keeperAddresses, -// f, -// { -// paymentPremiumPPB, -// flatFeeMicroLink, -// checkGasLimit, -// stalenessSeconds, -// gasCeilingMultiplier, -// minUpkeepSpend, -// maxCheckDataSize, -// maxPerformDataSize, -// maxRevertDataSize, -// maxPerformGas, -// fallbackGasPrice, -// fallbackLinkPrice, -// transcoder: transcoder.address, -// registrars: [], -// upkeepPrivilegeManager: upkeepManager, -// }, -// offchainVersion, -// offchainBytes, -// ) -// const payee1Before = await linkToken.balanceOf( -// await payee1.getAddress(), -// ) -// const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance -// const ownerBefore = (await registry.getState()).state.ownerLinkBalance -// -// await registry.connect(admin).cancelUpkeep(upkeepId) -// const payee1After = await linkToken.balanceOf( -// await payee1.getAddress(), -// ) -// const ownerAfter = (await registry.getState()).state.ownerLinkBalance -// const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance -// -// // upkeep does not pay cancellation fee after cancellation because minimum upkeep spent is met -// assert.isTrue(upkeepBefore.eq(upkeepAfter)) -// // owner balance does not change -// assert.isTrue(ownerAfter.eq(ownerBefore)) -// // payee balance does not change -// assert.isTrue(payee1Before.eq(payee1After)) -// }) -// }) -// }) -// }) -// -// describe('#withdrawPayment', () => { -// beforeEach(async () => { -// await linkToken.connect(owner).approve(registry.address, toWei('100')) -// await registry.connect(owner).addFunds(upkeepId, toWei('100')) -// await getTransmitTx(registry, keeper1, [upkeepId]) -// }) -// -// it('reverts if called by anyone but the payee', async () => { -// await evmRevert( -// registry -// .connect(payee2) -// .withdrawPayment( -// await keeper1.getAddress(), -// await nonkeeper.getAddress(), -// ), -// 'OnlyCallableByPayee()', -// ) -// }) -// -// it('reverts if called with the 0 address', async () => { -// await evmRevert( -// registry -// .connect(payee2) -// .withdrawPayment(await keeper1.getAddress(), zeroAddress), -// 'InvalidRecipient()', -// ) -// }) -// -// it('updates the balances', async () => { -// const to = await nonkeeper.getAddress() -// const keeperBefore = await registry.getTransmitterInfo( -// await keeper1.getAddress(), -// ) -// const registrationBefore = (await registry.getUpkeep(upkeepId)).balance -// const toLinkBefore = await linkToken.balanceOf(to) -// const registryLinkBefore = await linkToken.balanceOf(registry.address) -// const registryPremiumBefore = (await registry.getState()).state -// .totalPremium -// const ownerBefore = (await registry.getState()).state.ownerLinkBalance -// -// // Withdrawing for first time, last collected = 0 -// assert.equal(keeperBefore.lastCollected.toString(), '0') -// -// //// Do the thing -// await registry -// .connect(payee1) -// .withdrawPayment(await keeper1.getAddress(), to) -// -// const keeperAfter = await registry.getTransmitterInfo( -// await keeper1.getAddress(), -// ) -// const registrationAfter = (await registry.getUpkeep(upkeepId)).balance -// const toLinkAfter = await linkToken.balanceOf(to) -// const registryLinkAfter = await linkToken.balanceOf(registry.address) -// const registryPremiumAfter = (await registry.getState()).state -// .totalPremium -// const ownerAfter = (await registry.getState()).state.ownerLinkBalance -// -// // registry total premium should not change -// assert.isTrue(registryPremiumBefore.eq(registryPremiumAfter)) -// -// // Last collected should be updated to premium-change -// assert.isTrue( -// keeperAfter.lastCollected.eq( -// registryPremiumBefore.sub( -// registryPremiumBefore.mod(keeperAddresses.length), -// ), -// ), -// ) -// -// // owner balance should remain unchanged -// assert.isTrue(ownerAfter.eq(ownerBefore)) -// -// assert.isTrue(keeperAfter.balance.eq(BigNumber.from(0))) -// assert.isTrue(registrationBefore.eq(registrationAfter)) -// assert.isTrue(toLinkBefore.add(keeperBefore.balance).eq(toLinkAfter)) -// assert.isTrue( -// registryLinkBefore.sub(keeperBefore.balance).eq(registryLinkAfter), -// ) -// }) -// -// it('emits a log announcing the withdrawal', async () => { -// const balance = ( -// await registry.getTransmitterInfo(await keeper1.getAddress()) -// ).balance -// const tx = await registry -// .connect(payee1) -// .withdrawPayment( -// await keeper1.getAddress(), -// await nonkeeper.getAddress(), -// ) -// await expect(tx) -// .to.emit(registry, 'PaymentWithdrawn') -// .withArgs( -// await keeper1.getAddress(), -// balance, -// await nonkeeper.getAddress(), -// await payee1.getAddress(), -// ) -// }) -// }) -// -// describe('#checkCallback', () => { -// it('returns false with appropriate failure reason when target callback reverts', async () => { -// await streamsLookupUpkeep.setShouldRevertCallback(true) -// -// const values: any[] = ['0x1234', '0xabcd'] -// const res = await registry -// .connect(zeroAddress) -// .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') -// -// assert.isFalse(res.upkeepNeeded) -// assert.equal(res.performData, '0x') -// assert.equal( -// res.upkeepFailureReason, -// UpkeepFailureReason.CHECK_CALLBACK_REVERTED, -// ) -// assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// }) -// -// it('returns false with appropriate failure reason when target callback returns big performData', async () => { -// let longBytes = '0x' -// for (let i = 0; i <= maxPerformDataSize.toNumber(); i++) { -// longBytes += '11' -// } -// const values: any[] = [longBytes, longBytes] -// const res = await registry -// .connect(zeroAddress) -// .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') -// -// assert.isFalse(res.upkeepNeeded) -// assert.equal(res.performData, '0x') -// assert.equal( -// res.upkeepFailureReason, -// UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, -// ) -// assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// }) -// -// it('returns false with appropriate failure reason when target callback returns false', async () => { -// await streamsLookupUpkeep.setCallbackReturnBool(false) -// const values: any[] = ['0x1234', '0xabcd'] -// const res = await registry -// .connect(zeroAddress) -// .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') -// -// assert.isFalse(res.upkeepNeeded) -// assert.equal(res.performData, '0x') -// assert.equal( -// res.upkeepFailureReason, -// UpkeepFailureReason.UPKEEP_NOT_NEEDED, -// ) -// assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// }) -// -// it('succeeds with upkeep needed', async () => { -// const values: any[] = ['0x1234', '0xabcd'] -// -// const res = await registry -// .connect(zeroAddress) -// .callStatic.checkCallback(streamsLookupUpkeepId, values, '0x') -// const expectedPerformData = ethers.utils.defaultAbiCoder.encode( -// ['bytes[]', 'bytes'], -// [values, '0x'], -// ) -// -// assert.isTrue(res.upkeepNeeded) -// assert.equal(res.performData, expectedPerformData) -// assert.equal(res.upkeepFailureReason, UpkeepFailureReason.NONE) -// assert.isTrue(res.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used -// }) -// }) -// -// describe('#setUpkeepPrivilegeConfig() / #getUpkeepPrivilegeConfig()', () => { -// it('reverts when non manager tries to set privilege config', async () => { -// await evmRevert( -// registry.connect(payee3).setUpkeepPrivilegeConfig(upkeepId, '0x1234'), -// 'OnlyCallableByUpkeepPrivilegeManager()', -// ) -// }) -// -// it('returns empty bytes for upkeep privilege config before setting', async () => { -// const cfg = await registry.getUpkeepPrivilegeConfig(upkeepId) -// assert.equal(cfg, '0x') -// }) -// -// it('allows upkeep manager to set privilege config', async () => { -// const tx = await registry -// .connect(personas.Norbert) -// .setUpkeepPrivilegeConfig(upkeepId, '0x1234') -// await expect(tx) -// .to.emit(registry, 'UpkeepPrivilegeConfigSet') -// .withArgs(upkeepId, '0x1234') -// -// const cfg = await registry.getUpkeepPrivilegeConfig(upkeepId) -// assert.equal(cfg, '0x1234') -// }) -// }) -// -// describe('#setAdminPrivilegeConfig() / #getAdminPrivilegeConfig()', () => { -// const admin = randomAddress() -// -// it('reverts when non manager tries to set privilege config', async () => { -// await evmRevert( -// registry.connect(payee3).setAdminPrivilegeConfig(admin, '0x1234'), -// 'OnlyCallableByUpkeepPrivilegeManager()', -// ) -// }) -// -// it('returns empty bytes for upkeep privilege config before setting', async () => { -// const cfg = await registry.getAdminPrivilegeConfig(admin) -// assert.equal(cfg, '0x') -// }) -// -// it('allows upkeep manager to set privilege config', async () => { -// const tx = await registry -// .connect(personas.Norbert) -// .setAdminPrivilegeConfig(admin, '0x1234') -// await expect(tx) -// .to.emit(registry, 'AdminPrivilegeConfigSet') -// .withArgs(admin, '0x1234') -// -// const cfg = await registry.getAdminPrivilegeConfig(admin) -// assert.equal(cfg, '0x1234') -// }) -// }) -// -// describe('transmitterPremiumSplit [ @skip-coverage ]', () => { -// beforeEach(async () => { -// await linkToken.connect(owner).approve(registry.address, toWei('100')) -// await registry.connect(owner).addFunds(upkeepId, toWei('100')) -// }) -// -// it('splits premium evenly across transmitters', async () => { -// // Do a transmit from keeper1 -// await getTransmitTx(registry, keeper1, [upkeepId]) -// -// const registryPremium = (await registry.getState()).state.totalPremium -// assert.isTrue(registryPremium.gt(BigNumber.from(0))) -// -// const premiumPerTransmitter = registryPremium.div( -// BigNumber.from(keeperAddresses.length), -// ) -// const k1Balance = ( -// await registry.getTransmitterInfo(await keeper1.getAddress()) -// ).balance -// // transmitter should be reimbursed for gas and get the premium -// assert.isTrue(k1Balance.gt(premiumPerTransmitter)) -// const k1GasReimbursement = k1Balance.sub(premiumPerTransmitter) -// -// const k2Balance = ( -// await registry.getTransmitterInfo(await keeper2.getAddress()) -// ).balance -// // non transmitter should get its share of premium -// assert.isTrue(k2Balance.eq(premiumPerTransmitter)) -// -// // Now do a transmit from keeper 2 -// await getTransmitTx(registry, keeper2, [upkeepId]) -// const registryPremiumNew = (await registry.getState()).state.totalPremium -// assert.isTrue(registryPremiumNew.gt(registryPremium)) -// const premiumPerTransmitterNew = registryPremiumNew.div( -// BigNumber.from(keeperAddresses.length), -// ) -// const additionalPremium = premiumPerTransmitterNew.sub( -// premiumPerTransmitter, -// ) -// -// const k1BalanceNew = ( -// await registry.getTransmitterInfo(await keeper1.getAddress()) -// ).balance -// // k1 should get the new premium -// assert.isTrue( -// k1BalanceNew.eq(k1GasReimbursement.add(premiumPerTransmitterNew)), -// ) -// -// const k2BalanceNew = ( -// await registry.getTransmitterInfo(await keeper2.getAddress()) -// ).balance -// // k2 should get gas reimbursement in addition to new premium -// assert.isTrue(k2BalanceNew.gt(k2Balance.add(additionalPremium))) -// }) -// -// it('updates last collected upon payment withdrawn', async () => { -// // Do a transmit from keeper1 -// await getTransmitTx(registry, keeper1, [upkeepId]) -// -// const registryPremium = (await registry.getState()).state.totalPremium -// const k1 = await registry.getTransmitterInfo(await keeper1.getAddress()) -// const k2 = await registry.getTransmitterInfo(await keeper2.getAddress()) -// -// // Withdrawing for first time, last collected = 0 -// assert.isTrue(k1.lastCollected.eq(BigNumber.from(0))) -// assert.isTrue(k2.lastCollected.eq(BigNumber.from(0))) -// -// //// Do the thing -// await registry -// .connect(payee1) -// .withdrawPayment( -// await keeper1.getAddress(), -// await nonkeeper.getAddress(), -// ) -// -// const k1New = await registry.getTransmitterInfo( -// await keeper1.getAddress(), -// ) -// const k2New = await registry.getTransmitterInfo( -// await keeper2.getAddress(), -// ) -// -// // transmitter info lastCollected should be updated for k1, not for k2 -// assert.isTrue( -// k1New.lastCollected.eq( -// registryPremium.sub(registryPremium.mod(keeperAddresses.length)), -// ), -// ) -// assert.isTrue(k2New.lastCollected.eq(BigNumber.from(0))) -// }) -// -// itMaybe( -// 'maintains consistent balance information across all parties', -// async () => { -// // throughout transmits, withdrawals, setConfigs total claim on balances should remain less than expected balance -// // some spare change can get lost but it should be less than maxAllowedSpareChange -// -// let maxAllowedSpareChange = BigNumber.from('0') -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await getTransmitTx(registry, keeper1, [upkeepId]) -// maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('31')) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await registry -// .connect(payee1) -// .withdrawPayment( -// await keeper1.getAddress(), -// await nonkeeper.getAddress(), -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await registry -// .connect(payee2) -// .withdrawPayment( -// await keeper2.getAddress(), -// await nonkeeper.getAddress(), -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await getTransmitTx(registry, keeper1, [upkeepId]) -// maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('31')) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await registry.connect(owner).setConfigTypeSafe( -// signerAddresses.slice(2, 15), // only use 2-14th index keepers -// keeperAddresses.slice(2, 15), -// f, -// config, -// offchainVersion, -// offchainBytes, -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await getTransmitTx(registry, keeper3, [upkeepId], { -// startingSignerIndex: 2, -// }) -// maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('13')) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await registry -// .connect(payee1) -// .withdrawPayment( -// await keeper1.getAddress(), -// await nonkeeper.getAddress(), -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await registry -// .connect(payee3) -// .withdrawPayment( -// await keeper3.getAddress(), -// await nonkeeper.getAddress(), -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await registry.connect(owner).setConfigTypeSafe( -// signerAddresses.slice(0, 4), // only use 0-3rd index keepers -// keeperAddresses.slice(0, 4), -// f, -// config, -// offchainVersion, -// offchainBytes, -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// await getTransmitTx(registry, keeper1, [upkeepId]) -// maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('4')) -// await getTransmitTx(registry, keeper3, [upkeepId]) -// maxAllowedSpareChange = maxAllowedSpareChange.add(BigNumber.from('4')) -// -// await verifyConsistentAccounting(maxAllowedSpareChange) -// await registry -// .connect(payee5) -// .withdrawPayment( -// await keeper5.getAddress(), -// await nonkeeper.getAddress(), -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// -// await registry -// .connect(payee1) -// .withdrawPayment( -// await keeper1.getAddress(), -// await nonkeeper.getAddress(), -// ) -// await verifyConsistentAccounting(maxAllowedSpareChange) -// }, -// ) -// }) -// }) diff --git a/contracts/test/v0.8/automation/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts b/contracts/test/v0.8/automation/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts deleted file mode 100644 index 9187487a8f..0000000000 --- a/contracts/test/v0.8/automation/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber, Signer } from 'ethers' -import { assert } from 'chai' -import { KeeperRegistryCheckUpkeepGasUsageWrapper12 as GasWrapper } from '../../../typechain/KeeperRegistryCheckUpkeepGasUsageWrapper12' -import { KeeperRegistryCheckUpkeepGasUsageWrapper1_2__factory as GasWrapperFactory } from '../../../typechain/factories/KeeperRegistryCheckUpkeepGasUsageWrapper1_2__factory' -import { getUsers, Personas } from '../../test-helpers/setup' -import { - deployMockContract, - MockContract, -} from '@ethereum-waffle/mock-contract' -import { KeeperRegistry1_2__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry1_2__factory' - -let personas: Personas -let owner: Signer -let caller: Signer -let nelly: Signer -let registryMockContract: MockContract -let gasWrapper: GasWrapper -let gasWrapperFactory: GasWrapperFactory - -const upkeepId = 123 - -describe('KeeperRegistryCheckUpkeepGasUsageWrapper1_2', () => { - before(async () => { - personas = (await getUsers()).personas - owner = personas.Default - caller = personas.Carol - nelly = personas.Nelly - - registryMockContract = await deployMockContract( - owner as any, - KeeperRegistryFactory.abi, - ) - // @ts-ignore bug in autogen file - gasWrapperFactory = await ethers.getContractFactory( - 'KeeperRegistryCheckUpkeepGasUsageWrapper1_2', - ) - gasWrapper = await gasWrapperFactory - .connect(owner) - .deploy(registryMockContract.address) - await gasWrapper.deployed() - }) - - describe('measureCheckGas()', () => { - it("returns gas used when registry's checkUpkeep executes successfully", async () => { - await registryMockContract.mock.checkUpkeep - .withArgs(upkeepId, await nelly.getAddress()) - .returns( - '0xabcd' /* performData */, - BigNumber.from(1000) /* maxLinkPayment */, - BigNumber.from(2000) /* gasLimit */, - BigNumber.from(3000) /* adjustedGasWei */, - BigNumber.from(4000) /* linkEth */, - ) - - const response = await gasWrapper - .connect(caller) - .callStatic.measureCheckGas( - BigNumber.from(upkeepId), - await nelly.getAddress(), - ) - - assert.isTrue(response[0], 'The checkUpkeepSuccess should be true') - assert.equal( - response[1], - '0xabcd', - 'The performData should be forwarded correctly', - ) - assert.isTrue( - response[2] > BigNumber.from(0), - 'The gasUsed value must be larger than 0', - ) - }) - - it("returns gas used when registry's checkUpkeep reverts", async () => { - await registryMockContract.mock.checkUpkeep - .withArgs(upkeepId, await nelly.getAddress()) - .revertsWithReason('Error') - - const response = await gasWrapper - .connect(caller) - .callStatic.measureCheckGas( - BigNumber.from(upkeepId), - await nelly.getAddress(), - ) - - assert.isFalse(response[0], 'The checkUpkeepSuccess should be false') - assert.equal( - response[1], - '0x', - 'The performData should be forwarded correctly', - ) - assert.isTrue( - response[2] > BigNumber.from(0), - 'The gasUsed value must be larger than 0', - ) - }) - }) - - describe('getKeeperRegistry()', () => { - it('returns the underlying keeper registry', async () => { - const registry = await gasWrapper.connect(caller).getKeeperRegistry() - assert.equal( - registry, - registryMockContract.address, - 'The underlying keeper registry is incorrect', - ) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/UpkeepTranscoder.test.ts b/contracts/test/v0.8/automation/UpkeepTranscoder.test.ts deleted file mode 100644 index fc3a200956..0000000000 --- a/contracts/test/v0.8/automation/UpkeepTranscoder.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { ethers } from 'hardhat' -import { assert } from 'chai' -import { evmRevert, evmRevertCustomError } from '../../test-helpers/matchers' -import { UpkeepTranscoder__factory as UpkeepTranscoderFactory } from '../../../typechain/factories/UpkeepTranscoder__factory' -import { UpkeepTranscoder } from '../../../typechain' - -let upkeepTranscoderFactory: UpkeepTranscoderFactory -let transcoder: UpkeepTranscoder - -before(async () => { - upkeepTranscoderFactory = await ethers.getContractFactory('UpkeepTranscoder') -}) - -describe('UpkeepTranscoder', () => { - const formatV1 = 0 - const formatV2 = 1 - const formatV3 = 2 - - beforeEach(async () => { - transcoder = await upkeepTranscoderFactory.deploy() - }) - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await transcoder.typeAndVersion() - assert.equal(typeAndVersion, 'UpkeepTranscoder 1.0.0') - }) - }) - - describe('#transcodeUpkeeps', () => { - const encodedData = '0xc0ffee' - - it('reverts if the from type is not an enum value', async () => { - await evmRevert(transcoder.transcodeUpkeeps(3, 1, encodedData)) - }) - - it('reverts if the from type != to type', async () => { - await evmRevertCustomError( - transcoder.transcodeUpkeeps(1, 2, encodedData), - transcoder, - 'InvalidTranscoding', - ) - }) - - context('when from and to versions equal', () => { - it('returns the data that was passed in', async () => { - let response = await transcoder.transcodeUpkeeps( - formatV1, - formatV1, - encodedData, - ) - assert.equal(encodedData, response) - - response = await transcoder.transcodeUpkeeps( - formatV2, - formatV2, - encodedData, - ) - assert.equal(encodedData, response) - - response = await transcoder.transcodeUpkeeps( - formatV3, - formatV3, - encodedData, - ) - assert.equal(encodedData, response) - }) - }) - }) -}) From ec3eac5ff1d2befc58c369cdab281562ae3784d7 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Tue, 25 Jun 2024 13:12:29 -0500 Subject: [PATCH 06/61] add ci-protobuf gha workflow (#13677) * add ci-protobuf gha workflow * fetch-depth: 0 checkout * add env REPO_URL and BASE_BRANCH * use https * use buf actions * add github_token to action and change .proto file for test * fix codeowner bug * fix * add more explicit *.proto files * move catch-all foundations owner * another try * revert back to original * revert test --- .github/workflows/ci-protobuf.yml | 36 +++++++++++++++++++++++++++++++ CODEOWNERS | 1 + 2 files changed, 37 insertions(+) create mode 100644 .github/workflows/ci-protobuf.yml diff --git a/.github/workflows/ci-protobuf.yml b/.github/workflows/ci-protobuf.yml new file mode 100644 index 0000000000..d832939ded --- /dev/null +++ b/.github/workflows/ci-protobuf.yml @@ -0,0 +1,36 @@ +name: CI ProtoBuf + +on: + pull_request: + +jobs: + buf-breaking: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + + - name: Setup buf + uses: bufbuild/buf-setup-action@35c243d7f2a909b1d4e40399b348a7fdab27d78d # v1.34.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Run buf breaking + uses: bufbuild/buf-breaking-action@c57b3d842a5c3f3b454756ef65305a50a587c5ba # v1.1.4 + env: + REPO_URL: https://github.com/${{ github.repository }} + BASE_BRANCH: ${{ github.base_ref }} + with: + against: "${REPO_URL}.git#branch=${BASE_BRANCH}" + + - name: Collect Metrics + if: always() + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + with: + id: ci-protobuf + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: buf-breaking + continue-on-error: true diff --git a/CODEOWNERS b/CODEOWNERS index 8741cb7a68..5b80a90b27 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -12,6 +12,7 @@ # Services /core/services/directrequest @smartcontractkit/keepers /core/services/feeds @smartcontractkit/FMS +/core/services/synchronization/telem @smartcontractkit/realtime # To be deprecated in Chainlink V3 /core/services/fluxmonitorv2 @smartcontractkit/foundations From f2630b280d917313c6d3af468d9a7c039d5e179e Mon Sep 17 00:00:00 2001 From: Nick Corin Date: Wed, 26 Jun 2024 03:13:14 +0200 Subject: [PATCH 07/61] [BCI-3381] Implement `GetTransactionStatus` for the EVM `ChainWriter`. (#13691) * evm: Implement get transaction status * evm: Implement get transaction status * evm: Fix linting issues --- .changeset/purple-poets-film.md | 5 ++++ core/services/relay/evm/chain_writer.go | 2 +- core/services/relay/evm/chain_writer_test.go | 27 +++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 .changeset/purple-poets-film.md diff --git a/.changeset/purple-poets-film.md b/.changeset/purple-poets-film.md new file mode 100644 index 0000000000..cc858c72f0 --- /dev/null +++ b/.changeset/purple-poets-film.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Implemented the `GetTransactionStatus` method on the EVM implementation of the `ChainWriter`. diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index d0e76526dc..3f2d0da499 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -167,7 +167,7 @@ func (w *chainWriter) parseContracts() error { } func (w *chainWriter) GetTransactionStatus(ctx context.Context, transactionID string) (commontypes.TransactionStatus, error) { - return commontypes.Unknown, fmt.Errorf("not implemented") + return w.txm.GetTransactionStatus(ctx, transactionID) } // GetFeeComponents the execution and data availability (L1Oracle) fees for the chain. diff --git a/core/services/relay/evm/chain_writer_test.go b/core/services/relay/evm/chain_writer_test.go index 9344279da6..66c85bfc2c 100644 --- a/core/services/relay/evm/chain_writer_test.go +++ b/core/services/relay/evm/chain_writer_test.go @@ -5,11 +5,13 @@ import ( "math/big" "testing" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/types" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -33,7 +35,6 @@ func TestChainWriter(t *testing.T) { chainWriterConfig := newBaseChainWriterConfig() cw, err := NewChainWriterService(lggr, client, txm, ge, chainWriterConfig) - require.NoError(t, err) t.Run("Initialization", func(t *testing.T) { @@ -60,6 +61,30 @@ func TestChainWriter(t *testing.T) { // TODO: implement }) + t.Run("GetTransactionStatus", func(t *testing.T) { + txs := []struct { + txid string + status commontypes.TransactionStatus + }{ + {uuid.NewString(), commontypes.Unknown}, + {uuid.NewString(), commontypes.Unconfirmed}, + {uuid.NewString(), commontypes.Finalized}, + {uuid.NewString(), commontypes.Failed}, + {uuid.NewString(), commontypes.Fatal}, + } + + for _, tx := range txs { + txm.On("GetTransactionStatus", mock.Anything, tx.txid).Return(tx.status, nil).Once() + } + + for _, tx := range txs { + var status commontypes.TransactionStatus + status, err = cw.GetTransactionStatus(ctx, tx.txid) + require.NoError(t, err) + require.Equal(t, tx.status, status) + } + }) + t.Run("GetFeeComponents", func(t *testing.T) { ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: assets.NewWei(big.NewInt(1000000001)), From f1d4cd37262b7311bd10af1474a54fa09a92d51d Mon Sep 17 00:00:00 2001 From: Lee Yik Jiun Date: Wed, 26 Jun 2024 17:19:20 +0800 Subject: [PATCH 08/61] vrfv2plus: Add batch coordinator tests (#13497) * vrfv2plus: Add batch coordinator tests * Add function comment for print generate proof v2 plus --- .../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol | 1 + .../vrf/test/BatchVRFCoordinatorV2Plus.t.sol | 178 ++++++++++++++++++ .../vrf/test/FixtureVRFCoordinatorV2_5.t.sol | 134 +++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol create mode 100644 contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol diff --git a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol index 1d74128085..86578fb140 100644 --- a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol +++ b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol @@ -232,6 +232,7 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume * @param _fulfillmentFlatFeeLinkDiscountPPM is the flat fee discount in millionths of native that VRFCoordinatorV2Plus * charges for link payment. */ + /// @dev This function while having only 12 parameters is causing a Stack too deep error when running forge coverage. function setConfig( uint32 _wrapperGasOverhead, uint32 _coordinatorGasOverheadNative, diff --git a/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol b/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol new file mode 100644 index 0000000000..298af8c76e --- /dev/null +++ b/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol @@ -0,0 +1,178 @@ +pragma solidity 0.8.19; + +import {console} from "forge-std/console.sol"; +import {VRF} from "../VRF.sol"; +import {VRFTypes} from "../VRFTypes.sol"; +import {BatchVRFCoordinatorV2Plus} from "../dev/BatchVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import "./BaseTest.t.sol"; +import {FixtureVRFCoordinatorV2_5} from "./FixtureVRFCoordinatorV2_5.t.sol"; + +contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { + BatchVRFCoordinatorV2Plus private s_batchCoordinator; + + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + function setUp() public override { + FixtureVRFCoordinatorV2_5.setUp(); + + s_batchCoordinator = new BatchVRFCoordinatorV2Plus(address(s_coordinator)); + } + + function test_fulfillRandomWords() public { + _setUpConfig(); + _setUpProvingKey(); + _setUpSubscription(); + + uint32 requestBlock = 10; + vm.roll(requestBlock); + + vm.startPrank(SUBSCRIPTION_OWNER); + vm.deal(SUBSCRIPTION_OWNER, 10 ether); + s_coordinator.fundSubscriptionWithNative{value: 10 ether}(s_subId); + + // Request random words. + s_consumer.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, VRF_KEY_HASH, true); + vm.stopPrank(); + + // Move on to the next block. + // Store the previous block's blockhash. + vm.roll(requestBlock + 1); + s_bhs.store(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); + /* + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 33855227690351884611579800220581891477580182035146587491531555927634180294480 \ + -block-hash 0x0a \ + -block-num 10 \ + -sender 0xdc90e8ce61c1af8a638b95264037c8e67ee5765c \ + -native-payment true + + */ + proofs[0] = VRFTypes.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 80420391742429647505172101941811820476888293644816377569181566466584288434705, + 24046736031266889997051641830469514057863365715722268340801477580836256044582 + ], + c: 74775128390693502914275156263410881155583102046081919417827483535122161050585, + s: 69563235412360165148368009853509434870917653835330501139204071967997764190111, + seed: 33855227690351884611579800220581891477580182035146587491531555927634180294480, + uWitness: 0xfB0663eaf48785540dE0FD0F837FD9c09BF4B80A, + cGammaWitness: [ + 53711159452748734758194447734939737695995909567499536035707522847057731697403, + 113650002631484103366420937668971311744887820666944514581352028601506700116835 + ], + sHashWitness: [ + 89656531714223714144489731263049239277719465105516547297952288438117443488525, + 90859682705760125677895017864538514058733199985667976488434404721197234427011 + ], + zInv: 97275608653505690744303242942631893944856831559408852202478373762878300587548 + }); + rcs[0] = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: s_subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: 1, + sender: address(s_consumer), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) + }); + + VRFCoordinatorV2_5.Output memory output = s_coordinator.getRandomnessFromProofExternal( + abi.decode(abi.encode(proofs[0]), (VRF.Proof)), + rcs[0] + ); + + requestBlock = 20; + vm.roll(requestBlock); + + vm.startPrank(SUBSCRIPTION_OWNER); + s_linkToken.setBalance(address(SUBSCRIPTION_OWNER), 10 ether); + s_linkToken.transferAndCall(address(s_coordinator), 10 ether, abi.encode(s_subId)); + + // Request random words. + s_consumer1.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, VRF_KEY_HASH, false); + vm.stopPrank(); + + // Move on to the next block. + // Store the previous block's blockhash. + vm.roll(requestBlock + 1); + s_bhs.store(requestBlock); + + // Proof generated via the generate-proof-v2-plus script command. Example usage: + // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); + /* + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 76568185840201037774581758921393822690942290841865097674309745036496166431060 \ + -block-hash 0x14 \ + -block-num 20 \ + -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ + -native-payment false + */ + proofs[1] = VRFTypes.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 21323932463597506192387578758854201988004673105893105492473194972397109828006, + 96834737826889397196571646974355352644437196500310392203712129010026003355112 + ], + c: 8775807990949224376582975115621037245862755412370175152581490650310350359728, + s: 6805708577951013810918872616271445638109899206333819877111740872779453350091, + seed: 76568185840201037774581758921393822690942290841865097674309745036496166431060, + uWitness: 0xE82fF24Fecfbe73d682f38308bE3E039Dfabdf5c, + cGammaWitness: [ + 92810770919624535241476539842820168209710445519252592382122118536598338376923, + 17271305664006119131434661141858450289379246199095231636439133258170648418554 + ], + sHashWitness: [ + 29540023305939374439696120003978246982707698669656874393367212257432197207536, + 93902323936532381028323379401739289810874348405259732508442252936582467730050 + ], + zInv: 88845170436601946907659333156418518556235340365885668267853966404617557948692 + }); + rcs[1] = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: s_subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: 1, + sender: address(s_consumer1), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) + }); + + VRFCoordinatorV2_5.Output memory output1 = s_coordinator.getRandomnessFromProofExternal( + abi.decode(abi.encode(proofs[1]), (VRF.Proof)), + rcs[1] + ); + + // 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, 500000000000142215, true, true, false); + vm.expectEmit(true, true, false, true, address(s_coordinator)); + emit RandomWordsFulfilled(output1.requestId, output1.randomness, s_subId, 800000000000304103, false, true, false); + + // Fulfill the requests. + s_batchCoordinator.fulfillRandomWords(proofs, rcs); + } +} diff --git a/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol b/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol new file mode 100644 index 0000000000..c1c2c7eb27 --- /dev/null +++ b/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol @@ -0,0 +1,134 @@ +pragma solidity ^0.8.19; + +import {console} from "forge-std/console.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import {VRF} from "../VRF.sol"; +import {VRFTypes} from "../VRFTypes.sol"; +import {BlockhashStore} from "../dev/BlockhashStore.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import "./BaseTest.t.sol"; + +contract FixtureVRFCoordinatorV2_5 is BaseTest, VRF { + address internal SUBSCRIPTION_OWNER = makeAddr("SUBSCRIPTION_OWNER"); + + uint64 internal constant GAS_LANE_MAX_GAS = 5000 gwei; + uint16 internal constant MIN_CONFIRMATIONS = 0; + uint32 internal constant CALLBACK_GAS_LIMIT = 1_000_000; + uint32 internal constant NUM_WORDS = 1; + + // VRF KeyV2 generated from a node; not sensitive information. + // The secret key used to generate this key is: 10. + bytes internal constant VRF_UNCOMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; + bytes internal constant VRF_COMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; + bytes32 internal constant VRF_KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + + BlockhashStore internal s_bhs; + ExposedVRFCoordinatorV2_5 internal s_coordinator; + + // Use multiple consumers because VRFV2PlusConsumerExample cannot have multiple pending requests. + uint256 internal s_subId; + VRFV2PlusConsumerExample internal s_consumer; + VRFV2PlusConsumerExample internal s_consumer1; + + MockLinkToken internal s_linkToken; + MockV3Aggregator internal s_linkNativeFeed; + + function setUp() public virtual override { + BaseTest.setUp(); + vm.stopPrank(); + + vm.startPrank(OWNER); + s_bhs = new BlockhashStore(); + + // Deploy coordinator. + s_coordinator = new ExposedVRFCoordinatorV2_5(address(s_bhs)); + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Configure the coordinator. + s_coordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); + vm.stopPrank(); + + // Deploy consumers. + vm.startPrank(SUBSCRIPTION_OWNER); + s_consumer = new VRFV2PlusConsumerExample(address(s_coordinator), address(s_linkToken)); + s_consumer1 = new VRFV2PlusConsumerExample(address(s_coordinator), address(s_linkToken)); + vm.stopPrank(); + } + + function _setUpConfig() internal { + vm.prank(OWNER); + s_coordinator.setConfig( + 0, // minRequestConfirmations + 2_500_000, // maxGasLimit + 1, // stalenessSeconds + 50_000, // gasAfterPaymentCalculation + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + } + + function _setUpProvingKey() internal { + uint256[2] memory uncompressedKeyParts = this._getProvingKeyParts(VRF_UNCOMPRESSED_PUBLIC_KEY); + vm.prank(OWNER); + s_coordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); + } + + function _setUpSubscription() internal { + vm.startPrank(SUBSCRIPTION_OWNER); + s_subId = s_coordinator.createSubscription(); + s_coordinator.addConsumer(s_subId, address(s_consumer)); + s_consumer.setSubId(s_subId); + s_coordinator.addConsumer(s_subId, address(s_consumer1)); + s_consumer1.setSubId(s_subId); + vm.stopPrank(); + } + + // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and + // index over the byte array. + function _getProvingKeyParts(bytes calldata uncompressedKey) public pure returns (uint256[2] memory) { + uint256 keyPart1 = uint256(bytes32(uncompressedKey[0:32])); + uint256 keyPart2 = uint256(bytes32(uncompressedKey[32:64])); + return [keyPart1, keyPart2]; + } + + /** + * Prints the command to generate a proof for a VRF request. + * + * This function provides a convenient way to generate the proof off-chain to be copied into the tests. + * + * An example of the command looks like this: + * go run . generate-proof-v2-plus \ + * -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + * -pre-seed 76568185840201037774581758921393822690942290841865097674309745036496166431060 \ + * -block-hash 0x14 \ + * -block-num 20 \ + * -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ + * -native-payment false + */ + function _printGenerateProofV2PlusCommand( + address sender, + uint64 nonce, + uint256 requestBlock, + bool nativePayment + ) internal { + (, uint256 preSeed) = s_coordinator.computeRequestIdExternal(VRF_KEY_HASH, sender, s_subId, nonce); + + console.log("go run . generate-proof-v2-plus \\"); + console.log(string.concat(" -key-hash ", Strings.toHexString(uint256(VRF_KEY_HASH)), " \\")); + console.log(string.concat(" -pre-seed ", Strings.toString(preSeed), " \\")); + console.log(string.concat(" -block-hash ", Strings.toHexString(uint256(blockhash(requestBlock))), " \\")); + console.log(string.concat(" -block-num ", Strings.toString(requestBlock), " \\")); + console.log(string.concat(" -sender ", Strings.toHexString(sender), " \\")); + console.log(string.concat(" -native-payment ", nativePayment ? "true" : "false")); + } +} From 99fa0e68d11f4bbc5bc54c6c65edb1db024b21a9 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Wed, 26 Jun 2024 09:24:38 -0400 Subject: [PATCH 09/61] keystone/workflow engine logging (#13563) * Remove unused logger arg * Make capability id logging consistent * Clean up init logs * Normalize executionID and capabilityID * Adding store level logging * Add changeset * Add custom errors to workflow engine * Remove wrapped variants of logging * Simplify error handling for workflow engine errors * Change indentation * Run linter * Remove trailing newline --- .changeset/popular-candles-mix.md | 5 + .../transmission/local_target_capability.go | 8 +- .../local_target_capability_test.go | 2 +- core/services/chainlink/application.go | 2 +- core/services/workflows/engine.go | 169 ++++++++++++++---- core/services/workflows/engine_test.go | 115 ++++++++++-- core/services/workflows/store/store_db.go | 11 +- .../services/workflows/store/store_db_test.go | 27 ++- 8 files changed, 270 insertions(+), 69 deletions(-) create mode 100644 .changeset/popular-candles-mix.md diff --git a/.changeset/popular-candles-mix.md b/.changeset/popular-candles-mix.md new file mode 100644 index 0000000000..4822188582 --- /dev/null +++ b/.changeset/popular-candles-mix.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Clean up workflow engine logging diff --git a/core/capabilities/transmission/local_target_capability.go b/core/capabilities/transmission/local_target_capability.go index c040e6ed43..83b5d57613 100644 --- a/core/capabilities/transmission/local_target_capability.go +++ b/core/capabilities/transmission/local_target_capability.go @@ -14,12 +14,14 @@ import ( type LocalTargetCapability struct { lggr logger.Logger capabilities.TargetCapability - localNode capabilities.Node + localNode capabilities.Node + capabilityID string } -func NewLocalTargetCapability(lggr logger.Logger, localDON capabilities.Node, underlying capabilities.TargetCapability) *LocalTargetCapability { +func NewLocalTargetCapability(lggr logger.Logger, capabilityID string, localDON capabilities.Node, underlying capabilities.TargetCapability) *LocalTargetCapability { return &LocalTargetCapability{ TargetCapability: underlying, + capabilityID: capabilityID, lggr: lggr, localNode: localDON, } @@ -38,7 +40,7 @@ func (l *LocalTargetCapability) Execute(ctx context.Context, req capabilities.Ca peerIDToTransmissionDelay, err := GetPeerIDToTransmissionDelay(l.localNode.WorkflowDON.Members, req) if err != nil { - return nil, fmt.Errorf("failed to get peer ID to transmission delay map: %w", err) + return nil, fmt.Errorf("capability id: %s failed to get peer ID to transmission delay map: %w", l.capabilityID, err) } delay, existsForPeerID := peerIDToTransmissionDelay[*l.localNode.PeerID] diff --git a/core/capabilities/transmission/local_target_capability_test.go b/core/capabilities/transmission/local_target_capability_test.go index ded4b5c30f..d1ac9b0ead 100644 --- a/core/capabilities/transmission/local_target_capability_test.go +++ b/core/capabilities/transmission/local_target_capability_test.go @@ -139,7 +139,7 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { }, PeerID: &ids[tc.position], } - localTargetCapability := NewLocalTargetCapability(log, localDON, mt) + localTargetCapability := NewLocalTargetCapability(log, "capabilityID", localDON, mt) _, err = localTargetCapability.Execute(tests.Context(t), req) diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 1a626bc07f..7a928c46b8 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -353,7 +353,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { jobORM = job.NewORM(opts.DS, pipelineORM, bridgeORM, keyStore, globalLogger) txmORM = txmgr.NewTxStore(opts.DS, globalLogger) streamRegistry = streams.NewRegistry(globalLogger, pipelineRunner) - workflowORM = workflowstore.NewDBStore(opts.DS, clockwork.NewRealClock()) + workflowORM = workflowstore.NewDBStore(opts.DS, globalLogger, clockwork.NewRealClock()) ) for _, chain := range legacyEVMChains.Slice() { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 28f37cd7c4..a2cb3f72e3 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -83,7 +83,7 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { for _, t := range e.workflow.triggers { tg, err := e.registry.GetTrigger(ctx, t.ID) if err != nil { - e.logger.Errorf("failed to get trigger capability: %s", err) + e.logger.With(cIDKey, t.ID).Errorf("failed to get trigger capability: %s", err) // we don't immediately return here, since we want to retry all triggers // to notify the user of all errors at once. triggersInitialized = false @@ -92,7 +92,9 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { } } if !triggersInitialized { - return fmt.Errorf("failed to resolve triggers") + return &workflowError{reason: "failed to resolve triggers", labels: map[string]string{ + wIDKey: e.workflow.id, + }} } // Step 2. Walk the graph and register each step's capability to this workflow @@ -111,7 +113,12 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { err := e.initializeCapability(ctx, s) if err != nil { - return fmt.Errorf("failed to initialize capability for step %s: %w", s.Ref, err) + return &workflowError{err: err, reason: "failed to initialize capability for step", + labels: map[string]string{ + wIDKey: e.workflow.id, + sIDKey: s.ID, + sRKey: s.Ref, + }} } return nil @@ -121,6 +128,20 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { } func (e *Engine) initializeCapability(ctx context.Context, step *step) error { + // We use varadic err here so that err can be optional, but we assume that + // its length is either 0 or 1 + newCPErr := func(reason string, errs ...error) *workflowError { + var err error + if len(errs) > 0 { + err = errs[0] + } + + return &workflowError{reason: reason, err: err, labels: map[string]string{ + wIDKey: e.workflow.id, + sIDKey: step.ID, + }} + } + // If the capability already exists, that means we've already registered it if step.capability != nil { return nil @@ -128,20 +149,22 @@ func (e *Engine) initializeCapability(ctx context.Context, step *step) error { cp, err := e.registry.Get(ctx, step.ID) if err != nil { - return fmt.Errorf("failed to get capability with ref %s: %s", step.ID, err) + return newCPErr("failed to get capability", err) } info, err := cp.Info(ctx) if err != nil { - return fmt.Errorf("failed to get info of capability with id %s: %w", step.ID, err) + return newCPErr("failed to get capability info", err) } // 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 { - e.logger.Debugf("wrapping capability %s in local transmission protocol", info.ID) + l := e.logger.With("capabilityID", step.ID) + l.Debug("wrapping capability in local transmission protocol") cp = transmission.NewLocalTargetCapability( e.logger, + step.ID, e.localNode, cp.(capabilities.TargetCapability), ) @@ -151,13 +174,13 @@ func (e *Engine) initializeCapability(ctx context.Context, step *step) error { // they all satisfy the `CallbackCapability` interface cc, ok := cp.(capabilities.CallbackCapability) if !ok { - return fmt.Errorf("could not coerce capability %s to CallbackCapability", step.ID) + return newCPErr("capability does not satisfy CallbackCapability") } if step.config == nil { configMap, newMapErr := values.NewMap(step.Config) if newMapErr != nil { - return fmt.Errorf("failed to convert config to values.Map: %s", newMapErr) + return newCPErr("failed to convert config to values.Map", newMapErr) } step.config = configMap } @@ -171,7 +194,7 @@ func (e *Engine) initializeCapability(ctx context.Context, step *step) error { err = cc.RegisterToWorkflow(ctx, registrationRequest) if err != nil { - return fmt.Errorf("failed to register to workflow (%+v): %w", registrationRequest, err) + return newCPErr(fmt.Sprintf("failed to register capability to workflow (%+v)", registrationRequest), err) } step.capability = cc @@ -200,7 +223,10 @@ func (e *Engine) init(ctx context.Context) { err = e.resolveWorkflowCapabilities(ctx) if err != nil { - return fmt.Errorf("failed to resolve workflow: %s", err) + return &workflowError{err: err, reason: "failed to resolve workflow capabilities", + labels: map[string]string{ + wIDKey: e.workflow.id, + }} } return nil }) @@ -214,14 +240,14 @@ func (e *Engine) init(ctx context.Context) { e.logger.Debug("capabilities resolved, resuming in-progress workflows") err := e.resumeInProgressExecutions(ctx) if err != nil { - e.logger.Errorf("failed to resume workflows: %v", err) + e.logger.Errorf("failed to resume in-progress workflows: %v", err) } e.logger.Debug("registering triggers") for idx, t := range e.workflow.triggers { err := e.registerTrigger(ctx, t, idx) if err != nil { - e.logger.Errorf("failed to register trigger: %s", err) + e.logger.With(cIDKey, t.ID).Errorf("failed to register trigger: %s", err) } } @@ -241,7 +267,7 @@ func (e *Engine) resumeInProgressExecutions(ctx context.Context) error { // TODO: paginate properly if len(wipExecutions) >= defaultLimit { - e.logger.Warnf("possible execution overflow during resumption") + e.logger.Warnf("possible execution overflow during resumption, work in progress executions: %d >= %d", len(wipExecutions), defaultLimit) } // Cache the dependents associated with a step. @@ -284,9 +310,10 @@ func generateTriggerId(workflowID string, triggerIdx int) string { // registerTrigger is used during the initialization phase to bind a trigger to this workflow func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, triggerIdx int) error { + triggerID := generateTriggerId(e.workflow.id, triggerIdx) triggerInputs, err := values.NewMap( map[string]any{ - "triggerId": generateTriggerId(e.workflow.id, triggerIdx), + "triggerId": triggerID, }, ) if err != nil { @@ -312,7 +339,20 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig } eventsCh, err := t.trigger.RegisterTrigger(ctx, triggerRegRequest) if err != nil { - return fmt.Errorf("failed to instantiate trigger %s, %s", t.ID, err) + // It's confusing that t.ID is different from triggerID, but + // t.ID is the capability ID, and triggerID is the trigger ID. + // + // The capability ID is globally scoped, whereas the trigger ID + // is scoped to this workflow. + // + // For example, t.ID might be "streams-trigger:network=mainnet@1.0.0" + // and triggerID might be "wf_123_trigger_0" + return &workflowError{err: err, reason: fmt.Sprintf("failed to register trigger: %+v", triggerRegRequest), + labels: map[string]string{ + wIDKey: e.workflow.id, + cIDKey: t.ID, + tIDKey: triggerID, + }} } go func() { @@ -344,11 +384,11 @@ func (e *Engine) loop(ctx context.Context) { for { select { case <-ctx.Done(): - e.logger.Debugw("shutting down loop") + e.logger.Debug("shutting down loop") return case resp, isOpen := <-e.triggerEvents: if !isOpen { - e.logger.Errorf("trigger events channel is no longer open, skipping") + e.logger.Error("trigger events channel is no longer open, skipping") continue } @@ -366,13 +406,13 @@ func (e *Engine) loop(ctx context.Context) { executionID, err := generateExecutionID(e.workflow.id, te.ID) if err != nil { - e.logger.Errorf("could not generate execution ID; error %v", resp.Err) + e.logger.With(tIDKey, te.ID).Errorf("could not generate execution ID: %v", err) continue } err = e.startExecution(ctx, executionID, resp.Value) if err != nil { - e.logger.Errorf("failed to start execution: %v", err) + e.logger.With(eIDKey, executionID).Errorf("failed to start execution: %v", err) } case pendingStepRequest := <-e.pendingStepRequests: // Wait for a new worker to be available before dispatching a new one. @@ -384,7 +424,8 @@ func (e *Engine) loop(ctx context.Context) { e.wg.Add(1) go e.workerForStepRequest(ctx, pendingStepRequest) case <-t.Chan(): - e.logger.Errorf("timed out when spinning off worker for pending step request %+v", pendingStepRequest) + e.logger.With(eIDKey, pendingStepRequest.state.ExecutionID, sRKey, pendingStepRequest.stepRef). + Errorf("timed out when spinning off worker for pending step request %+v", pendingStepRequest) e.pendingStepRequests <- pendingStepRequest } t.Stop() @@ -392,7 +433,8 @@ func (e *Engine) loop(ctx context.Context) { // Executed synchronously to ensure we correctly schedule subsequent tasks. err := e.handleStepUpdate(ctx, stepUpdate) if err != nil { - e.logger.Errorf("failed to update step state: %+v, %s", stepUpdate, err) + e.logger.With(eIDKey, stepUpdate.ExecutionID, sRKey, stepUpdate.Ref). + Errorf("failed to update step state: %+v, %s", stepUpdate, err) } } } @@ -415,7 +457,7 @@ func generateExecutionID(workflowID, eventID string) (string, error) { // startExecution kicks off a new workflow execution when a trigger event is received. func (e *Engine) startExecution(ctx context.Context, executionID string, event values.Value) error { - e.logger.Debugw("executing on a trigger event", "event", event, "executionID", executionID) + e.logger.With("event", event, eIDKey, executionID).Debug("executing on a trigger event") ec := &store.WorkflowExecution{ Steps: map[string]*store.WorkflowExecutionStep{ workflows.KeywordTrigger: { @@ -457,6 +499,7 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.Workflow if err != nil { return err } + l := e.logger.With(eIDKey, state.ExecutionID, sRKey, stepUpdate.Ref) switch stepUpdate.Status { case store.StatusCompleted: @@ -499,7 +542,7 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.Workflow // We haven't completed the workflow, but should we continue? // If we've been executing for too long, let's time the workflow out and stop here. if state.CreatedAt != nil && e.clock.Since(*state.CreatedAt) > e.maxExecutionDuration { - e.logger.Infow("execution timed out", "executionID", state.ExecutionID) + l.Info("execution timed out") return e.finishExecution(ctx, state.ExecutionID, store.StatusTimeout) } @@ -509,7 +552,7 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.Workflow e.queueIfReady(state, sd) } case store.StatusCompletedEarlyExit: - e.logger.Infow("execution terminated early", "executionID", state.ExecutionID) + l.Info("execution terminated early") // NOTE: even though this marks the workflow as completed, any branches of the DAG // that don't depend on the step that signaled for an early exit will still complete. // This is to ensure that any side effects are executed consistently, since otherwise @@ -519,7 +562,7 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.Workflow return err } case store.StatusErrored: - e.logger.Infow("execution errored", "executionID", state.ExecutionID) + l.Info("execution errored") err := e.finishExecution(ctx, state.ExecutionID, store.StatusErrored) if err != nil { return err @@ -551,7 +594,8 @@ func (e *Engine) queueIfReady(state store.WorkflowExecution, step *step) { // If all dependencies are completed, enqueue the step. if !waitingOnDependencies { - e.logger.Debugw("step request enqueued", "ref", step.Ref, "state", copyState(state)) + e.logger.With(sRKey, step.Ref, eIDKey, state.ExecutionID, "state", copyState(state)). + Debug("step request enqueued") e.pendingStepRequests <- stepRequest{ state: copyState(state), stepRef: step.Ref, @@ -560,7 +604,7 @@ func (e *Engine) queueIfReady(state store.WorkflowExecution, step *step) { } func (e *Engine) finishExecution(ctx context.Context, executionID string, status string) error { - e.logger.Infow("finishing execution", "executionID", executionID, "status", status) + e.logger.With(eIDKey, executionID, "status", status).Info("finishing execution") err := e.executionStates.UpdateStatus(ctx, executionID, status) if err != nil { return err @@ -576,26 +620,26 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // Instantiate a child logger; in addition to the WorkflowID field the workflow // logger will already have, this adds the `stepRef` and `executionID` - l := e.logger.With("stepRef", msg.stepRef, "executionID", msg.state.ExecutionID) + l := e.logger.With(sRKey, msg.stepRef, eIDKey, msg.state.ExecutionID) - l.Debugw("executing on a step event") + l.Debug("executing on a step event") stepState := &store.WorkflowExecutionStep{ Outputs: store.StepOutput{}, ExecutionID: msg.state.ExecutionID, Ref: msg.stepRef, } - inputs, outputs, err := e.executeStep(ctx, l, msg) + inputs, outputs, err := e.executeStep(ctx, msg) var stepStatus string switch { case errors.Is(capabilities.ErrStopExecution, err): - l.Infow("step executed successfully with a termination") + l.Info("step executed successfully with a termination") stepStatus = store.StatusCompletedEarlyExit case err != nil: l.Errorf("error executing step request: %s", err) stepStatus = store.StatusErrored default: - l.Infow("step executed successfully", "outputs", outputs) + l.With("outputs", outputs).Info("step executed successfully") stepStatus = store.StatusCompleted } @@ -618,7 +662,7 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { } // executeStep executes the referenced capability within a step and returns the result. -func (e *Engine) executeStep(ctx context.Context, l logger.Logger, msg stepRequest) (*values.Map, values.Value, error) { +func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, values.Value, error) { step, err := e.workflow.Vertex(msg.stepRef) if err != nil { return nil, nil, err @@ -723,7 +767,13 @@ func (e *Engine) Close() error { innerErr := s.capability.UnregisterFromWorkflow(ctx, reg) if innerErr != nil { - return fmt.Errorf("failed to unregister from workflow: %+v", reg) + return &workflowError{err: innerErr, + reason: fmt.Sprintf("failed to unregister capability from workflow: %+v", reg), + labels: map[string]string{ + wIDKey: e.workflow.id, + sIDKey: s.ID, + sRKey: s.Ref, + }} } return nil @@ -767,7 +817,11 @@ const ( func NewEngine(cfg Config) (engine *Engine, err error) { if cfg.Store == nil { - return nil, errors.New("must provide store") + return nil, &workflowError{reason: "store is nil", + labels: map[string]string{ + wIDKey: cfg.WorkflowID, + }, + } } if cfg.MaxWorkerLimit == 0 { @@ -871,3 +925,48 @@ func executeSyncAndUnwrapSingleValue(ctx context.Context, cap capabilities.Callb return l.Underlying[0], nil } + +// Logging keys +const ( + cIDKey = "capabilityID" + tIDKey = "triggerID" + wIDKey = "workflowID" + eIDKey = "executionID" + sIDKey = "stepID" + sRKey = "stepRef" +) + +type workflowError struct { + labels map[string]string + // err is the underlying error that caused this error + err error + // reason is a human-readable string that describes the error + reason string +} + +func (e *workflowError) Error() string { + // declare in reverse order so that the error message is ordered correctly + orderedLabels := []string{sRKey, sIDKey, tIDKey, cIDKey, eIDKey, wIDKey} + + errStr := "" + if e.err != nil { + if e.reason != "" { + errStr = fmt.Sprintf("%s: %v", e.reason, e.err) + } else { + errStr = e.err.Error() + } + } else { + errStr = e.reason + } + + // prefix the error with the labels + for _, label := range orderedLabels { + // This will silently ignore any labels that are not present in the map + // are we ok with this? + if value, ok := e.labels[label]; ok { + errStr = fmt.Sprintf("%s %s: %s", label, value, errStr) + } + } + + return errStr +} diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 09af6d6358..50ee0c36eb 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -20,10 +20,12 @@ import ( "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/job" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) +const testWorkflowId = "" const hardcodedWorkflow = ` triggers: - id: "mercury-trigger@1.0.0" @@ -78,6 +80,25 @@ type testHooks struct { executionFinished chan string } +func newTestDBStore(t *testing.T, clock clockwork.Clock) store.Store { + // Taken from https://github.com/smartcontractkit/chainlink/blob/d736d9e0838983a021677bc608556b3994f46690/core/services/job/orm.go#L412 + // We need to insert this row so that we dont get foreign key constraint errors + // based on the workflow_id + db := pgtest.NewSqlxDB(t) + sql := `INSERT INTO workflow_specs (workflow, workflow_id, workflow_owner, workflow_name, created_at, updated_at) + VALUES (:workflow, :workflow_id, :workflow_owner, :workflow_name, NOW(), NOW()) + RETURNING id;` + var wfSpec job.WorkflowSpec + wfSpec.Workflow = simpleWorkflow + wfSpec.WorkflowID = testWorkflowId + wfSpec.WorkflowOwner = "testowner" + wfSpec.WorkflowName = "testworkflow" + _, err := db.NamedExec(sql, wfSpec) + require.NoError(t, err) + + return store.NewDBStore(db, logger.TestLogger(t), clock) +} + // 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{} @@ -86,9 +107,10 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...fun executionFinished := make(chan string, 100) clock := clockwork.NewFakeClock() cfg := Config{ - Lggr: logger.TestLogger(t), - Registry: reg, - Spec: spec, + WorkflowID: testWorkflowId, + Lggr: logger.TestLogger(t), + Registry: reg, + Spec: spec, GetLocalNode: func(ctx context.Context) (capabilities.Node, error) { return capabilities.Node{ WorkflowDON: capabilities.DON{ @@ -110,11 +132,14 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...fun executionFinished <- weid }, clock: clock, - Store: store.NewDBStore(pgtest.NewSqlxDB(t), clock), } for _, o := range opts { o(&cfg) } + // We use the cfg clock incase they override it + if cfg.Store == nil { + cfg.Store = newTestDBStore(t, cfg.clock) + } eng, err := NewEngine(cfg) require.NoError(t, err) return eng, &testHooks{initSuccessful: initSuccessful, initFailed: initFailed, executionFinished: executionFinished} @@ -193,7 +218,6 @@ func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capab } func TestEngineWithHardcodedWorkflow(t *testing.T) { - dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()) ctx := testutils.Context(t) reg := coreCap.NewRegistry(logger.TestLogger(t)) @@ -223,7 +247,6 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { t, reg, hardcodedWorkflow, - func(c *Config) { c.Store = dbstore }, ) servicetest.Run(t, eng) @@ -559,8 +582,7 @@ func TestEngine_ResumesPendingExecutions(t *testing.T) { action, _ := mockAction() require.NoError(t, reg.Add(ctx, action)) - - dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()) + dbstore := newTestDBStore(t, clockwork.NewFakeClock()) ec := &store.WorkflowExecution{ Steps: map[string]*store.WorkflowExecutionStep{ workflows.KeywordTrigger: { @@ -572,7 +594,7 @@ func TestEngine_ResumesPendingExecutions(t *testing.T) { Ref: workflows.KeywordTrigger, }, }, - WorkflowID: "", + WorkflowID: testWorkflowId, ExecutionID: "", Status: store.StatusStarted, } @@ -614,7 +636,7 @@ func TestEngine_TimesOutOldExecutions(t *testing.T) { require.NoError(t, reg.Add(ctx, action)) clock := clockwork.NewFakeClock() - dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clock) + dbstore := newTestDBStore(t, clock) ec := &store.WorkflowExecution{ Steps: map[string]*store.WorkflowExecutionStep{ workflows.KeywordTrigger: { @@ -626,7 +648,7 @@ func TestEngine_TimesOutOldExecutions(t *testing.T) { Ref: workflows.KeywordTrigger, }, }, - WorkflowID: "", + WorkflowID: testWorkflowId, ExecutionID: "", Status: store.StatusStarted, } @@ -708,7 +730,7 @@ func TestEngine_WrapsTargets(t *testing.T) { require.NoError(t, reg.Add(ctx, mockTarget())) clock := clockwork.NewFakeClock() - dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clock) + dbstore := newTestDBStore(t, clock) eng, hooks := newTestEngine( t, @@ -754,7 +776,7 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { require.NoError(t, reg.Add(ctx, mockTarget())) clock := clockwork.NewFakeClock() - dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clock) + dbstore := newTestDBStore(t, clock) var peerID p2ptypes.PeerID node := capabilities.Node{ @@ -791,3 +813,70 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { assert.Equal(t, node, eng.localNode) } + +func TestEngine_Error(t *testing.T) { + err := errors.New("some error") + tests := []struct { + name string + labels map[string]string + err error + reason string + want string + }{ + { + name: "Error with error and reason", + labels: map[string]string{wIDKey: "my-workflow-id"}, + err: err, + reason: "some reason", + want: "workflowID my-workflow-id: some reason: some error", + }, + { + name: "Error with error and no reason", + labels: map[string]string{eIDKey: "dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751"}, + err: err, + want: "executionID dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751: some error", + }, + { + name: "Error with no error and reason", + labels: map[string]string{cIDKey: "streams-trigger:network_eth@1.0.0"}, + reason: "some reason", + want: "capabilityID streams-trigger:network_eth@1.0.0: some reason", + }, + { + name: "Error with no error and no reason", + labels: map[string]string{tIDKey: "wf_123_trigger_456"}, + want: "triggerID wf_123_trigger_456: ", + }, + { + name: "Error with no labels", + labels: map[string]string{}, + err: err, + reason: "some reason", + want: "some reason: some error", + }, + { + name: "Multiple labels", + labels: map[string]string{ + wIDKey: "my-workflow-id", + eIDKey: "dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751", + cIDKey: "streams-trigger:network_eth@1.0.0", + }, + err: err, + reason: "some reason", + want: "workflowID my-workflow-id: executionID dd3708ac7d8dd6fa4fae0fb87b73f318a4da2526c123e159b72435e3b2fe8751: capabilityID streams-trigger:network_eth@1.0.0: some reason: some error", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &workflowError{ + labels: tt.labels, + err: tt.err, + reason: tt.reason, + } + if got := e.Error(); got != tt.want { + t.Errorf("err string mismatch\ngot = %v\nwant = %v", got, tt.want) + } + }) + } +} diff --git a/core/services/workflows/store/store_db.go b/core/services/workflows/store/store_db.go index e9204efd7b..e1d0862905 100644 --- a/core/services/workflows/store/store_db.go +++ b/core/services/workflows/store/store_db.go @@ -14,11 +14,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/values" valuespb "github.com/smartcontractkit/chainlink-common/pkg/values/pb" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) // `DBStore` is a postgres-backed // data store that persists workflow progress. type DBStore struct { + lggr logger.Logger db sqlutil.DataSource clock clockwork.Clock } @@ -197,16 +199,20 @@ func stateToStep(state *WorkflowExecutionStep) (workflowStepRow, error) { // `Add` creates the relevant workflow_execution and workflow_step entries // to persist the passed in ExecutionState. func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) error { + l := d.lggr.With("executionID", state.ExecutionID, "workflowID", state.WorkflowID, "status", state.Status) return d.transact(ctx, func(db *DBStore) error { var wid *string if state.WorkflowID != "" { wid = &state.WorkflowID } + wex := &workflowExecutionRow{ ID: state.ExecutionID, WorkflowID: wid, Status: state.Status, } + l.Debug("Adding workflow execution") + err := db.insertWorkflowExecution(ctx, wex) if err != nil { return fmt.Errorf("could not insert workflow execution %s: %w", state.ExecutionID, err) @@ -218,6 +224,7 @@ func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) error { if err != nil { return err } + l.With("stepRef", step.Ref).Debug("Adding workflow step") ws = append(ws, step) } if len(ws) > 0 { @@ -368,6 +375,6 @@ func (d *DBStore) GetUnfinished(ctx context.Context, offset, limit int) ([]Workf return states, nil } -func NewDBStore(ds sqlutil.DataSource, clock clockwork.Clock) *DBStore { - return &DBStore{db: ds, clock: clock} +func NewDBStore(ds sqlutil.DataSource, lggr logger.Logger, clock clockwork.Clock) *DBStore { + return &DBStore{db: ds, lggr: lggr.Named("WorkflowDBStore"), clock: clock} } diff --git a/core/services/workflows/store/store_db_test.go b/core/services/workflows/store/store_db_test.go index 7ae139b943..9a98db3056 100644 --- a/core/services/workflows/store/store_db_test.go +++ b/core/services/workflows/store/store_db_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) func randomID() string { @@ -24,9 +25,13 @@ func randomID() string { return hex.EncodeToString(b) } -func Test_StoreDB(t *testing.T) { +func newTestDBStore(t *testing.T) *DBStore { db := pgtest.NewSqlxDB(t) - store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + return &DBStore{db: db, lggr: logger.TestLogger(t), clock: clockwork.NewFakeClock()} +} + +func Test_StoreDB(t *testing.T) { + store := newTestDBStore(t) id := randomID() es := WorkflowExecution{ @@ -58,8 +63,7 @@ func Test_StoreDB(t *testing.T) { } func Test_StoreDB_DuplicateEntry(t *testing.T) { - db := pgtest.NewSqlxDB(t) - store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + store := newTestDBStore(t) id := randomID() es := WorkflowExecution{ @@ -87,8 +91,7 @@ func Test_StoreDB_DuplicateEntry(t *testing.T) { } func Test_StoreDB_UpdateStatus(t *testing.T) { - db := pgtest.NewSqlxDB(t) - store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + store := newTestDBStore(t) id := randomID() es := WorkflowExecution{ @@ -122,8 +125,7 @@ func Test_StoreDB_UpdateStatus(t *testing.T) { } func Test_StoreDB_UpdateStep(t *testing.T) { - db := pgtest.NewSqlxDB(t) - store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + store := newTestDBStore(t) id := randomID() stepOne := &WorkflowExecutionStep{ @@ -170,8 +172,7 @@ func Test_StoreDB_UpdateStep(t *testing.T) { } func Test_StoreDB_WorkflowStatus(t *testing.T) { - db := pgtest.NewSqlxDB(t) - store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + store := newTestDBStore(t) for s := range ValidStatuses { id := randomID() @@ -200,8 +201,7 @@ func Test_StoreDB_WorkflowStatus(t *testing.T) { } func Test_StoreDB_WorkflowStepStatus(t *testing.T) { - db := pgtest.NewSqlxDB(t) - store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + store := newTestDBStore(t) id := randomID() stepOne := &WorkflowExecutionStep{ @@ -234,8 +234,7 @@ func Test_StoreDB_WorkflowStepStatus(t *testing.T) { } func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { - db := pgtest.NewSqlxDB(t) - store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + store := newTestDBStore(t) id := randomID() stepOne := &WorkflowExecutionStep{ From 850834742e0f959308119137f67c9b581dc4f831 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Wed, 26 Jun 2024 16:44:40 +0200 Subject: [PATCH 10/61] fix double namespace creation in OCR soak tests (#13696) * remove merge artifact * embed more configs * fix embedded file name --- integration-tests/soak/ocr_test.go | 3 --- integration-tests/testconfig/configs_embed.go | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go index 0e7b50d15b..ab6051ee94 100644 --- a/integration-tests/soak/ocr_test.go +++ b/integration-tests/soak/ocr_test.go @@ -149,9 +149,6 @@ func executeOCRSoakTest(t *testing.T, test *testsetups.OCRSoakTest, config *tc.T require.NoError(t, err, "Error creating seth client") } - if !test.Interrupted() { - test.DeployEnvironment(config) - } l.Info().Str("test", t.Name()).Msg("Starting OCR soak test") if !test.Interrupted() { test.DeployEnvironment(config) diff --git a/integration-tests/testconfig/configs_embed.go b/integration-tests/testconfig/configs_embed.go index 67e954ff50..0dbd2b29e6 100644 --- a/integration-tests/testconfig/configs_embed.go +++ b/integration-tests/testconfig/configs_embed.go @@ -7,12 +7,17 @@ import "embed" //go:embed default.toml //go:embed automation/automation.toml +//go:embed forwarder_ocr/forwarder_ocr.toml +//go:embed forwarder_ocr2/forwarder_ocr2.toml //go:embed functions/functions.toml //go:embed keeper/keeper.toml //go:embed log_poller/log_poller.toml //go:embed node/node.toml //go:embed ocr/ocr.toml +//go:embed ocr2/ocr2.toml +//go:embed vrf/vrf.toml //go:embed vrfv2/vrfv2.toml +//go:embed ocr2vrf/ocr2vrf.toml //go:embed vrfv2plus/vrfv2plus.toml var embeddedConfigsFs embed.FS From 8863e3535f4c67f00fe6b380132bf72d78141215 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 26 Jun 2024 11:53:12 -0500 Subject: [PATCH 11/61] bump mockery to v2.43.2 (#13594) * bump mockery to v2.43.2 * make generate --- .tool-versions | 2 +- GNUmakefile | 2 +- common/client/mock_head_test.go | 2 +- common/client/mock_node_client_test.go | 2 +- common/client/mock_node_selector_test.go | 2 +- common/client/mock_node_test.go | 2 +- common/client/mock_rpc_test.go | 2 +- common/client/mock_send_only_client_test.go | 2 +- common/client/mock_send_only_node_test.go | 2 +- common/headtracker/mocks/head_broadcaster.go | 2 +- common/headtracker/mocks/head_trackable.go | 2 +- common/headtracker/mocks/head_tracker.go | 2 +- common/txmgr/mocks/tx_manager.go | 2 +- common/txmgr/types/mocks/forwarder_manager.go | 2 +- common/txmgr/types/mocks/key_store.go | 2 +- common/txmgr/types/mocks/reaper_chain_config.go | 2 +- common/txmgr/types/mocks/tx_attempt_builder.go | 2 +- common/txmgr/types/mocks/tx_store.go | 2 +- common/txmgr/types/mocks/tx_strategy.go | 2 +- common/types/mocks/head.go | 2 +- common/types/mocks/subscription.go | 2 +- contracts/GNUmakefile | 2 +- core/bridges/mocks/orm.go | 2 +- core/capabilities/remote/types/mocks/dispatcher.go | 2 +- core/capabilities/remote/types/mocks/receiver.go | 2 +- core/capabilities/targets/mocks/chain_reader.go | 2 +- core/capabilities/targets/mocks/chain_writer.go | 2 +- core/chains/evm/client/mocks/client.go | 2 +- core/chains/evm/client/mocks/rpc_client.go | 2 +- core/chains/evm/config/mocks/chain_scoped_config.go | 2 +- core/chains/evm/config/mocks/gas_estimator.go | 2 +- core/chains/evm/forwarders/mocks/orm.go | 2 +- core/chains/evm/gas/mocks/config.go | 2 +- core/chains/evm/gas/mocks/evm_estimator.go | 2 +- core/chains/evm/gas/mocks/evm_fee_estimator.go | 2 +- core/chains/evm/gas/mocks/fee_estimator_client.go | 2 +- core/chains/evm/gas/rollups/mocks/l1_oracle.go | 2 +- core/chains/evm/gas/rollups/mocks/l1_oracle_client.go | 2 +- core/chains/evm/keystore/mocks/eth.go | 2 +- core/chains/evm/log/mocks/abigen_contract.go | 2 +- core/chains/evm/log/mocks/broadcast.go | 2 +- core/chains/evm/log/mocks/broadcaster.go | 2 +- core/chains/evm/logpoller/mocks/log_poller.go | 2 +- core/chains/evm/mocks/balance_monitor.go | 2 +- core/chains/evm/txmgr/mocks/config.go | 2 +- core/chains/evm/txmgr/mocks/evm_tx_store.go | 2 +- core/chains/legacyevm/mocks/chain.go | 2 +- core/chains/legacyevm/mocks/legacy_chain_container.go | 2 +- core/cmd/mocks/prompter.go | 2 +- core/config/mocks/telemetry_ingress.go | 2 +- core/config/mocks/telemetry_ingress_endpoint.go | 2 +- core/internal/mocks/application.go | 2 +- core/internal/mocks/flags.go | 2 +- core/internal/mocks/flux_aggregator.go | 2 +- core/internal/mocks/prometheus_backend.go | 2 +- core/logger/logger_mock_test.go | 2 +- core/logger/mocks/logger.go | 2 +- core/services/blockhashstore/mocks/bhs.go | 2 +- core/services/blockhashstore/mocks/timer.go | 2 +- core/services/ccip/mocks/orm.go | 2 +- core/services/chainlink/mocks/general_config.go | 2 +- core/services/feeds/mocks/connections_manager.go | 2 +- core/services/feeds/mocks/feeds_manager_client.go | 2 +- core/services/feeds/mocks/orm.go | 2 +- core/services/feeds/mocks/service.go | 2 +- core/services/fluxmonitorv2/mocks/contract_submitter.go | 2 +- core/services/fluxmonitorv2/mocks/flags.go | 2 +- core/services/fluxmonitorv2/mocks/key_store_interface.go | 2 +- core/services/fluxmonitorv2/mocks/orm.go | 2 +- core/services/functions/mocks/bridge_accessor.go | 2 +- core/services/functions/mocks/external_adapter_client.go | 2 +- core/services/functions/mocks/functions_listener.go | 2 +- core/services/functions/mocks/offchain_transmitter.go | 2 +- core/services/functions/mocks/orm.go | 2 +- core/services/gateway/connector/mocks/gateway_connector.go | 2 +- .../gateway/connector/mocks/gateway_connector_handler.go | 2 +- core/services/gateway/connector/mocks/signer.go | 2 +- .../handlers/functions/allowlist/mocks/onchain_allowlist.go | 2 +- core/services/gateway/handlers/functions/allowlist/mocks/orm.go | 2 +- .../functions/subscriptions/mocks/onchain_subscriptions.go | 2 +- .../gateway/handlers/functions/subscriptions/mocks/orm.go | 2 +- core/services/gateway/handlers/mocks/don.go | 2 +- core/services/gateway/handlers/mocks/handler.go | 2 +- core/services/gateway/network/mocks/connection_acceptor.go | 2 +- core/services/gateway/network/mocks/connection_initiator.go | 2 +- core/services/gateway/network/mocks/http_request_handler.go | 2 +- core/services/gateway/network/mocks/http_server.go | 2 +- core/services/gateway/network/mocks/web_socket_server.go | 2 +- core/services/job/mocks/kv_store.go | 2 +- core/services/job/mocks/orm.go | 2 +- core/services/job/mocks/service_ctx.go | 2 +- core/services/job/mocks/spawner.go | 2 +- core/services/keystore/mocks/cosmos.go | 2 +- core/services/keystore/mocks/csa.go | 2 +- core/services/keystore/mocks/dkg_encrypt.go | 2 +- core/services/keystore/mocks/dkg_sign.go | 2 +- core/services/keystore/mocks/eth.go | 2 +- core/services/keystore/mocks/master.go | 2 +- core/services/keystore/mocks/ocr.go | 2 +- core/services/keystore/mocks/ocr2.go | 2 +- core/services/keystore/mocks/p2p.go | 2 +- core/services/keystore/mocks/solana.go | 2 +- core/services/keystore/mocks/starknet.go | 2 +- core/services/keystore/mocks/vrf.go | 2 +- core/services/mocks/checker.go | 2 +- core/services/ocr/mocks/ocr_contract_tracker_db.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go | 2 +- .../evmregistry/v21/core/mocks/upkeep_state_reader.go | 2 +- .../plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go | 2 +- .../ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go | 2 +- .../plugins/ocr2vrf/coordinator/mocks/vrf_beacon_coordinator.go | 2 +- .../ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go | 2 +- .../ocr2/plugins/promwrapper/mocks/prometheus_backend.go | 2 +- core/services/ocr2/plugins/threshold/mocks/decryptor.go | 2 +- core/services/p2p/types/mocks/peer.go | 2 +- core/services/p2p/types/mocks/peer_wrapper.go | 2 +- core/services/p2p/types/mocks/signer.go | 2 +- core/services/pipeline/mocks/config.go | 2 +- core/services/pipeline/mocks/orm.go | 2 +- core/services/pipeline/mocks/pipeline_param_unmarshaler.go | 2 +- core/services/pipeline/mocks/runner.go | 2 +- core/services/relay/evm/mercury/mocks/async_deleter.go | 2 +- core/services/relay/evm/mocks/loop_relay_adapter.go | 2 +- core/services/relay/evm/mocks/request_round_db.go | 2 +- core/services/relay/evm/types/mocks/log_poller_wrapper.go | 2 +- core/services/s4/mocks/orm.go | 2 +- core/services/s4/mocks/storage.go | 2 +- core/services/synchronization/mocks/telem_client.go | 2 +- core/services/synchronization/mocks/telemetry_service.go | 2 +- core/services/vrf/mocks/aggregator_v3_interface.go | 2 +- core/services/vrf/mocks/config.go | 2 +- core/services/vrf/mocks/fee_config.go | 2 +- core/services/vrf/mocks/vrf_coordinator_v2.go | 2 +- core/services/webhook/mocks/external_initiator_manager.go | 2 +- core/services/webhook/mocks/http_client.go | 2 +- core/sessions/ldapauth/mocks/ldap_client.go | 2 +- core/sessions/ldapauth/mocks/ldap_conn.go | 2 +- core/sessions/mocks/authentication_provider.go | 2 +- core/sessions/mocks/basic_admin_users_orm.go | 2 +- 140 files changed, 140 insertions(+), 140 deletions(-) diff --git a/.tool-versions b/.tool-versions index ca10fd5f6a..f660f2ac11 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,5 +1,5 @@ golang 1.21.7 -mockery 2.42.2 +mockery 2.43.2 nodejs 20.13.1 pnpm 9.4.0 postgres 15.1 diff --git a/GNUmakefile b/GNUmakefile index 711a41840a..b3077278a1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -135,7 +135,7 @@ gomods: ## Install gomods .PHONY: mockery mockery: $(mockery) ## Install mockery. - go install github.com/vektra/mockery/v2@v2.42.2 + go install github.com/vektra/mockery/v2@v2.43.2 .PHONY: codecgen codecgen: $(codecgen) ## Install codecgen diff --git a/common/client/mock_head_test.go b/common/client/mock_head_test.go index 9a66e164aa..64c6dbcb0a 100644 --- a/common/client/mock_head_test.go +++ b/common/client/mock_head_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package client diff --git a/common/client/mock_node_client_test.go b/common/client/mock_node_client_test.go index ec83158a5f..b9b9470de2 100644 --- a/common/client/mock_node_client_test.go +++ b/common/client/mock_node_client_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package client diff --git a/common/client/mock_node_selector_test.go b/common/client/mock_node_selector_test.go index 996d064daa..783fc50c29 100644 --- a/common/client/mock_node_selector_test.go +++ b/common/client/mock_node_selector_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package client diff --git a/common/client/mock_node_test.go b/common/client/mock_node_test.go index ee2cacb927..67ee5a4ba9 100644 --- a/common/client/mock_node_test.go +++ b/common/client/mock_node_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package client diff --git a/common/client/mock_rpc_test.go b/common/client/mock_rpc_test.go index 54f57e81f6..e3e7c59f2e 100644 --- a/common/client/mock_rpc_test.go +++ b/common/client/mock_rpc_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package client diff --git a/common/client/mock_send_only_client_test.go b/common/client/mock_send_only_client_test.go index b07e10ed8c..606506e657 100644 --- a/common/client/mock_send_only_client_test.go +++ b/common/client/mock_send_only_client_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package client diff --git a/common/client/mock_send_only_node_test.go b/common/client/mock_send_only_node_test.go index 4822c2620b..a39df992ae 100644 --- a/common/client/mock_send_only_node_test.go +++ b/common/client/mock_send_only_node_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package client diff --git a/common/headtracker/mocks/head_broadcaster.go b/common/headtracker/mocks/head_broadcaster.go index c3a9fba97b..e11adb715f 100644 --- a/common/headtracker/mocks/head_broadcaster.go +++ b/common/headtracker/mocks/head_broadcaster.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/headtracker/mocks/head_trackable.go b/common/headtracker/mocks/head_trackable.go index 417152d8cb..9b70938512 100644 --- a/common/headtracker/mocks/head_trackable.go +++ b/common/headtracker/mocks/head_trackable.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/headtracker/mocks/head_tracker.go b/common/headtracker/mocks/head_tracker.go index 2321c3bfdc..0e30b44154 100644 --- a/common/headtracker/mocks/head_tracker.go +++ b/common/headtracker/mocks/head_tracker.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/txmgr/mocks/tx_manager.go b/common/txmgr/mocks/tx_manager.go index 502f6fe8a2..c7380b7687 100644 --- a/common/txmgr/mocks/tx_manager.go +++ b/common/txmgr/mocks/tx_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/txmgr/types/mocks/forwarder_manager.go b/common/txmgr/types/mocks/forwarder_manager.go index b2cf9bc9d3..366fd27015 100644 --- a/common/txmgr/types/mocks/forwarder_manager.go +++ b/common/txmgr/types/mocks/forwarder_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/txmgr/types/mocks/key_store.go b/common/txmgr/types/mocks/key_store.go index f6f572a35f..0a14acfbed 100644 --- a/common/txmgr/types/mocks/key_store.go +++ b/common/txmgr/types/mocks/key_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/txmgr/types/mocks/reaper_chain_config.go b/common/txmgr/types/mocks/reaper_chain_config.go index 716b3e5175..30f58c1000 100644 --- a/common/txmgr/types/mocks/reaper_chain_config.go +++ b/common/txmgr/types/mocks/reaper_chain_config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/txmgr/types/mocks/tx_attempt_builder.go b/common/txmgr/types/mocks/tx_attempt_builder.go index 4761467433..692b71e739 100644 --- a/common/txmgr/types/mocks/tx_attempt_builder.go +++ b/common/txmgr/types/mocks/tx_attempt_builder.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go index bb8fabf1a7..9c2edfa963 100644 --- a/common/txmgr/types/mocks/tx_store.go +++ b/common/txmgr/types/mocks/tx_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/txmgr/types/mocks/tx_strategy.go b/common/txmgr/types/mocks/tx_strategy.go index 414fdb44cb..1034e00e54 100644 --- a/common/txmgr/types/mocks/tx_strategy.go +++ b/common/txmgr/types/mocks/tx_strategy.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go index 8fcd57a33c..1234fd3893 100644 --- a/common/types/mocks/head.go +++ b/common/types/mocks/head.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/common/types/mocks/subscription.go b/common/types/mocks/subscription.go index e52fafa7ca..6abf2acdb5 100644 --- a/common/types/mocks/subscription.go +++ b/common/types/mocks/subscription.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index ba11b396e8..69666024d9 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -39,7 +39,7 @@ abigen: ## Build & install abigen. .PHONY: mockery mockery: $(mockery) ## Install mockery. - go install github.com/vektra/mockery/v2@v2.35.4 + go install github.com/vektra/mockery/v2@v2.43.2 .PHONY: foundry foundry: ## Install foundry. diff --git a/core/bridges/mocks/orm.go b/core/bridges/mocks/orm.go index cda12a9045..db8553fb21 100644 --- a/core/bridges/mocks/orm.go +++ b/core/bridges/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/capabilities/remote/types/mocks/dispatcher.go b/core/capabilities/remote/types/mocks/dispatcher.go index 9ef7cee78d..f36515f4fe 100644 --- a/core/capabilities/remote/types/mocks/dispatcher.go +++ b/core/capabilities/remote/types/mocks/dispatcher.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/capabilities/remote/types/mocks/receiver.go b/core/capabilities/remote/types/mocks/receiver.go index b232912353..701ab0f011 100644 --- a/core/capabilities/remote/types/mocks/receiver.go +++ b/core/capabilities/remote/types/mocks/receiver.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/capabilities/targets/mocks/chain_reader.go b/core/capabilities/targets/mocks/chain_reader.go index 14748c16bb..6ad40c7159 100644 --- a/core/capabilities/targets/mocks/chain_reader.go +++ b/core/capabilities/targets/mocks/chain_reader.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/capabilities/targets/mocks/chain_writer.go b/core/capabilities/targets/mocks/chain_writer.go index 8fe9a0585f..ef3613305b 100644 --- a/core/capabilities/targets/mocks/chain_writer.go +++ b/core/capabilities/targets/mocks/chain_writer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go index 58d5152662..8a5b29cf4c 100644 --- a/core/chains/evm/client/mocks/client.go +++ b/core/chains/evm/client/mocks/client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/client/mocks/rpc_client.go b/core/chains/evm/client/mocks/rpc_client.go index 980a215ccf..1c39d22136 100644 --- a/core/chains/evm/client/mocks/rpc_client.go +++ b/core/chains/evm/client/mocks/rpc_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/config/mocks/chain_scoped_config.go b/core/chains/evm/config/mocks/chain_scoped_config.go index 7f5f9666ae..730c6c61c4 100644 --- a/core/chains/evm/config/mocks/chain_scoped_config.go +++ b/core/chains/evm/config/mocks/chain_scoped_config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/config/mocks/gas_estimator.go b/core/chains/evm/config/mocks/gas_estimator.go index 549f16fe55..9ad7420977 100644 --- a/core/chains/evm/config/mocks/gas_estimator.go +++ b/core/chains/evm/config/mocks/gas_estimator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/forwarders/mocks/orm.go b/core/chains/evm/forwarders/mocks/orm.go index 04e252fa7d..7cffdf171c 100644 --- a/core/chains/evm/forwarders/mocks/orm.go +++ b/core/chains/evm/forwarders/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/mocks/config.go b/core/chains/evm/gas/mocks/config.go index 5daac21176..b4a5e40f2f 100644 --- a/core/chains/evm/gas/mocks/config.go +++ b/core/chains/evm/gas/mocks/config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/mocks/evm_estimator.go b/core/chains/evm/gas/mocks/evm_estimator.go index 1213a71742..8c8693413f 100644 --- a/core/chains/evm/gas/mocks/evm_estimator.go +++ b/core/chains/evm/gas/mocks/evm_estimator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/mocks/evm_fee_estimator.go b/core/chains/evm/gas/mocks/evm_fee_estimator.go index 5179a2560d..7382133561 100644 --- a/core/chains/evm/gas/mocks/evm_fee_estimator.go +++ b/core/chains/evm/gas/mocks/evm_fee_estimator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/mocks/fee_estimator_client.go b/core/chains/evm/gas/mocks/fee_estimator_client.go index d81120e2ed..d375b478a7 100644 --- a/core/chains/evm/gas/mocks/fee_estimator_client.go +++ b/core/chains/evm/gas/mocks/fee_estimator_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/rollups/mocks/l1_oracle.go b/core/chains/evm/gas/rollups/mocks/l1_oracle.go index 79d4d64ecd..f9f0a34b8a 100644 --- a/core/chains/evm/gas/rollups/mocks/l1_oracle.go +++ b/core/chains/evm/gas/rollups/mocks/l1_oracle.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go b/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go index 146f2cd680..9225c247ca 100644 --- a/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go +++ b/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/keystore/mocks/eth.go b/core/chains/evm/keystore/mocks/eth.go index 9c11551e2c..df46adb202 100644 --- a/core/chains/evm/keystore/mocks/eth.go +++ b/core/chains/evm/keystore/mocks/eth.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/log/mocks/abigen_contract.go b/core/chains/evm/log/mocks/abigen_contract.go index 3ab5e35050..31e268cd85 100644 --- a/core/chains/evm/log/mocks/abigen_contract.go +++ b/core/chains/evm/log/mocks/abigen_contract.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/log/mocks/broadcast.go b/core/chains/evm/log/mocks/broadcast.go index 1f1817474e..c7dfb90055 100644 --- a/core/chains/evm/log/mocks/broadcast.go +++ b/core/chains/evm/log/mocks/broadcast.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/log/mocks/broadcaster.go b/core/chains/evm/log/mocks/broadcaster.go index 221456c508..4571ba4bab 100644 --- a/core/chains/evm/log/mocks/broadcaster.go +++ b/core/chains/evm/log/mocks/broadcaster.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go index 3c8f445df5..76442c8e94 100644 --- a/core/chains/evm/logpoller/mocks/log_poller.go +++ b/core/chains/evm/logpoller/mocks/log_poller.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/mocks/balance_monitor.go b/core/chains/evm/mocks/balance_monitor.go index 7c55cd78eb..2bf4898ef2 100644 --- a/core/chains/evm/mocks/balance_monitor.go +++ b/core/chains/evm/mocks/balance_monitor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/txmgr/mocks/config.go b/core/chains/evm/txmgr/mocks/config.go index 5ec00e960a..efaaab68af 100644 --- a/core/chains/evm/txmgr/mocks/config.go +++ b/core/chains/evm/txmgr/mocks/config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go index 465681247e..5a699f71bf 100644 --- a/core/chains/evm/txmgr/mocks/evm_tx_store.go +++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/legacyevm/mocks/chain.go b/core/chains/legacyevm/mocks/chain.go index 8f313ee45e..93f7c40fe0 100644 --- a/core/chains/legacyevm/mocks/chain.go +++ b/core/chains/legacyevm/mocks/chain.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/chains/legacyevm/mocks/legacy_chain_container.go b/core/chains/legacyevm/mocks/legacy_chain_container.go index 527544de60..ff73a4e139 100644 --- a/core/chains/legacyevm/mocks/legacy_chain_container.go +++ b/core/chains/legacyevm/mocks/legacy_chain_container.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/cmd/mocks/prompter.go b/core/cmd/mocks/prompter.go index 38c1d327fb..c2dff9fa61 100644 --- a/core/cmd/mocks/prompter.go +++ b/core/cmd/mocks/prompter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/config/mocks/telemetry_ingress.go b/core/config/mocks/telemetry_ingress.go index fb01cc29cd..43889566c7 100644 --- a/core/config/mocks/telemetry_ingress.go +++ b/core/config/mocks/telemetry_ingress.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/config/mocks/telemetry_ingress_endpoint.go b/core/config/mocks/telemetry_ingress_endpoint.go index e5f8c3106e..11eebd373e 100644 --- a/core/config/mocks/telemetry_ingress_endpoint.go +++ b/core/config/mocks/telemetry_ingress_endpoint.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/internal/mocks/application.go b/core/internal/mocks/application.go index f845d46ca8..cbb8ebaaa0 100644 --- a/core/internal/mocks/application.go +++ b/core/internal/mocks/application.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/internal/mocks/flags.go b/core/internal/mocks/flags.go index 3f9e47095e..7d38a96d92 100644 --- a/core/internal/mocks/flags.go +++ b/core/internal/mocks/flags.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/internal/mocks/flux_aggregator.go b/core/internal/mocks/flux_aggregator.go index c1e35f41e2..1501e36e94 100644 --- a/core/internal/mocks/flux_aggregator.go +++ b/core/internal/mocks/flux_aggregator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/internal/mocks/prometheus_backend.go b/core/internal/mocks/prometheus_backend.go index 81ff22d9d5..65cc739030 100644 --- a/core/internal/mocks/prometheus_backend.go +++ b/core/internal/mocks/prometheus_backend.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/logger/logger_mock_test.go b/core/logger/logger_mock_test.go index 8d52734fe5..0c901c7eb2 100644 --- a/core/logger/logger_mock_test.go +++ b/core/logger/logger_mock_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package logger diff --git a/core/logger/mocks/logger.go b/core/logger/mocks/logger.go index 7e56bf8d22..da881894d1 100644 --- a/core/logger/mocks/logger.go +++ b/core/logger/mocks/logger.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/blockhashstore/mocks/bhs.go b/core/services/blockhashstore/mocks/bhs.go index 43b4769c02..40b73aba0d 100644 --- a/core/services/blockhashstore/mocks/bhs.go +++ b/core/services/blockhashstore/mocks/bhs.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/blockhashstore/mocks/timer.go b/core/services/blockhashstore/mocks/timer.go index 46212b4c02..bf593f7691 100644 --- a/core/services/blockhashstore/mocks/timer.go +++ b/core/services/blockhashstore/mocks/timer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ccip/mocks/orm.go b/core/services/ccip/mocks/orm.go index ea6b07dc63..d3d7f89ba3 100644 --- a/core/services/ccip/mocks/orm.go +++ b/core/services/ccip/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go index c7e224f4f2..50a4478d7c 100644 --- a/core/services/chainlink/mocks/general_config.go +++ b/core/services/chainlink/mocks/general_config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/feeds/mocks/connections_manager.go b/core/services/feeds/mocks/connections_manager.go index 06cb0eeb5a..daeb06f692 100644 --- a/core/services/feeds/mocks/connections_manager.go +++ b/core/services/feeds/mocks/connections_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/feeds/mocks/feeds_manager_client.go b/core/services/feeds/mocks/feeds_manager_client.go index 71c8786da3..e2b92c28a8 100644 --- a/core/services/feeds/mocks/feeds_manager_client.go +++ b/core/services/feeds/mocks/feeds_manager_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/feeds/mocks/orm.go b/core/services/feeds/mocks/orm.go index 625a0b41d9..3fce89eb60 100644 --- a/core/services/feeds/mocks/orm.go +++ b/core/services/feeds/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/feeds/mocks/service.go b/core/services/feeds/mocks/service.go index 1e2e639327..de5779374a 100644 --- a/core/services/feeds/mocks/service.go +++ b/core/services/feeds/mocks/service.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/fluxmonitorv2/mocks/contract_submitter.go b/core/services/fluxmonitorv2/mocks/contract_submitter.go index ac67c353cf..0e969294b9 100644 --- a/core/services/fluxmonitorv2/mocks/contract_submitter.go +++ b/core/services/fluxmonitorv2/mocks/contract_submitter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/fluxmonitorv2/mocks/flags.go b/core/services/fluxmonitorv2/mocks/flags.go index 0585611ed0..7b5e0330c8 100644 --- a/core/services/fluxmonitorv2/mocks/flags.go +++ b/core/services/fluxmonitorv2/mocks/flags.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/fluxmonitorv2/mocks/key_store_interface.go b/core/services/fluxmonitorv2/mocks/key_store_interface.go index f831c854ce..4c99cea1af 100644 --- a/core/services/fluxmonitorv2/mocks/key_store_interface.go +++ b/core/services/fluxmonitorv2/mocks/key_store_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/fluxmonitorv2/mocks/orm.go b/core/services/fluxmonitorv2/mocks/orm.go index 7755543b40..d43a9ea16e 100644 --- a/core/services/fluxmonitorv2/mocks/orm.go +++ b/core/services/fluxmonitorv2/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/bridge_accessor.go b/core/services/functions/mocks/bridge_accessor.go index 797007d788..3641e7dfa1 100644 --- a/core/services/functions/mocks/bridge_accessor.go +++ b/core/services/functions/mocks/bridge_accessor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/external_adapter_client.go b/core/services/functions/mocks/external_adapter_client.go index cd402c1e6a..e7f7053a0b 100644 --- a/core/services/functions/mocks/external_adapter_client.go +++ b/core/services/functions/mocks/external_adapter_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/functions_listener.go b/core/services/functions/mocks/functions_listener.go index fed369fd65..ed0d269c6f 100644 --- a/core/services/functions/mocks/functions_listener.go +++ b/core/services/functions/mocks/functions_listener.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/offchain_transmitter.go b/core/services/functions/mocks/offchain_transmitter.go index 1e1422b8d4..b718222d09 100644 --- a/core/services/functions/mocks/offchain_transmitter.go +++ b/core/services/functions/mocks/offchain_transmitter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/functions/mocks/orm.go b/core/services/functions/mocks/orm.go index c921fda5c6..813abed7e2 100644 --- a/core/services/functions/mocks/orm.go +++ b/core/services/functions/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/connector/mocks/gateway_connector.go b/core/services/gateway/connector/mocks/gateway_connector.go index 0f37ee6040..41e3148d05 100644 --- a/core/services/gateway/connector/mocks/gateway_connector.go +++ b/core/services/gateway/connector/mocks/gateway_connector.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/connector/mocks/gateway_connector_handler.go b/core/services/gateway/connector/mocks/gateway_connector_handler.go index c21528134f..a79a2d32fe 100644 --- a/core/services/gateway/connector/mocks/gateway_connector_handler.go +++ b/core/services/gateway/connector/mocks/gateway_connector_handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/connector/mocks/signer.go b/core/services/gateway/connector/mocks/signer.go index bb4c364839..c60bd9d436 100644 --- a/core/services/gateway/connector/mocks/signer.go +++ b/core/services/gateway/connector/mocks/signer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go b/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go index 7581414d00..6d7c6a2535 100644 --- a/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go +++ b/core/services/gateway/handlers/functions/allowlist/mocks/onchain_allowlist.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/functions/allowlist/mocks/orm.go b/core/services/gateway/handlers/functions/allowlist/mocks/orm.go index c1d47169c5..9c293fb2f4 100644 --- a/core/services/gateway/handlers/functions/allowlist/mocks/orm.go +++ b/core/services/gateway/handlers/functions/allowlist/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go b/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go index 93b476820a..9bc8fc3ccb 100644 --- a/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go +++ b/core/services/gateway/handlers/functions/subscriptions/mocks/onchain_subscriptions.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go b/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go index 614ba83af1..759cf03c5d 100644 --- a/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go +++ b/core/services/gateway/handlers/functions/subscriptions/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/mocks/don.go b/core/services/gateway/handlers/mocks/don.go index 91c162b2f5..ceaa81eea1 100644 --- a/core/services/gateway/handlers/mocks/don.go +++ b/core/services/gateway/handlers/mocks/don.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/handlers/mocks/handler.go b/core/services/gateway/handlers/mocks/handler.go index e22c7f158f..e0bfe28f63 100644 --- a/core/services/gateway/handlers/mocks/handler.go +++ b/core/services/gateway/handlers/mocks/handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/connection_acceptor.go b/core/services/gateway/network/mocks/connection_acceptor.go index 37ebc7b8c9..1af874b433 100644 --- a/core/services/gateway/network/mocks/connection_acceptor.go +++ b/core/services/gateway/network/mocks/connection_acceptor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/connection_initiator.go b/core/services/gateway/network/mocks/connection_initiator.go index 7efac288ba..0b63edf182 100644 --- a/core/services/gateway/network/mocks/connection_initiator.go +++ b/core/services/gateway/network/mocks/connection_initiator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/http_request_handler.go b/core/services/gateway/network/mocks/http_request_handler.go index 0cbcf3eb6b..d2bba61f2f 100644 --- a/core/services/gateway/network/mocks/http_request_handler.go +++ b/core/services/gateway/network/mocks/http_request_handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/http_server.go b/core/services/gateway/network/mocks/http_server.go index 586677c604..8609803eaf 100644 --- a/core/services/gateway/network/mocks/http_server.go +++ b/core/services/gateway/network/mocks/http_server.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/gateway/network/mocks/web_socket_server.go b/core/services/gateway/network/mocks/web_socket_server.go index fb880193c7..32483fe402 100644 --- a/core/services/gateway/network/mocks/web_socket_server.go +++ b/core/services/gateway/network/mocks/web_socket_server.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/job/mocks/kv_store.go b/core/services/job/mocks/kv_store.go index 270a6c1d55..dba287da5e 100644 --- a/core/services/job/mocks/kv_store.go +++ b/core/services/job/mocks/kv_store.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index e8911b25af..1d2615b519 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/job/mocks/service_ctx.go b/core/services/job/mocks/service_ctx.go index d01ef619be..2871f7fcf0 100644 --- a/core/services/job/mocks/service_ctx.go +++ b/core/services/job/mocks/service_ctx.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/job/mocks/spawner.go b/core/services/job/mocks/spawner.go index 7127636cdb..24bfa36bec 100644 --- a/core/services/job/mocks/spawner.go +++ b/core/services/job/mocks/spawner.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/cosmos.go b/core/services/keystore/mocks/cosmos.go index 5e16a1a3c3..db143e6e34 100644 --- a/core/services/keystore/mocks/cosmos.go +++ b/core/services/keystore/mocks/cosmos.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/csa.go b/core/services/keystore/mocks/csa.go index c99fef9de8..c3e76f9f69 100644 --- a/core/services/keystore/mocks/csa.go +++ b/core/services/keystore/mocks/csa.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/dkg_encrypt.go b/core/services/keystore/mocks/dkg_encrypt.go index 48f50b3cec..1a3fddf577 100644 --- a/core/services/keystore/mocks/dkg_encrypt.go +++ b/core/services/keystore/mocks/dkg_encrypt.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/dkg_sign.go b/core/services/keystore/mocks/dkg_sign.go index fd16f573a8..01e69f8f3f 100644 --- a/core/services/keystore/mocks/dkg_sign.go +++ b/core/services/keystore/mocks/dkg_sign.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/eth.go b/core/services/keystore/mocks/eth.go index f4a2bea1b0..352605efcd 100644 --- a/core/services/keystore/mocks/eth.go +++ b/core/services/keystore/mocks/eth.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/master.go b/core/services/keystore/mocks/master.go index 2739c4bbe3..7c9b51c723 100644 --- a/core/services/keystore/mocks/master.go +++ b/core/services/keystore/mocks/master.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/ocr.go b/core/services/keystore/mocks/ocr.go index 76659d0d4d..7582295ee1 100644 --- a/core/services/keystore/mocks/ocr.go +++ b/core/services/keystore/mocks/ocr.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/ocr2.go b/core/services/keystore/mocks/ocr2.go index 74c8eed70c..0771f460db 100644 --- a/core/services/keystore/mocks/ocr2.go +++ b/core/services/keystore/mocks/ocr2.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/p2p.go b/core/services/keystore/mocks/p2p.go index cb5a9329e5..973fc81c95 100644 --- a/core/services/keystore/mocks/p2p.go +++ b/core/services/keystore/mocks/p2p.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/solana.go b/core/services/keystore/mocks/solana.go index 2f9514cc1d..4fde08fc26 100644 --- a/core/services/keystore/mocks/solana.go +++ b/core/services/keystore/mocks/solana.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/starknet.go b/core/services/keystore/mocks/starknet.go index a6cc0d5e5f..d12a8e9b8f 100644 --- a/core/services/keystore/mocks/starknet.go +++ b/core/services/keystore/mocks/starknet.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/keystore/mocks/vrf.go b/core/services/keystore/mocks/vrf.go index 87c6a724bd..bc88f04523 100644 --- a/core/services/keystore/mocks/vrf.go +++ b/core/services/keystore/mocks/vrf.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/mocks/checker.go b/core/services/mocks/checker.go index 09be8c2345..71b5f301a5 100644 --- a/core/services/mocks/checker.go +++ b/core/services/mocks/checker.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr/mocks/ocr_contract_tracker_db.go b/core/services/ocr/mocks/ocr_contract_tracker_db.go index d3dcce2641..8abfbba7f6 100644 --- a/core/services/ocr/mocks/ocr_contract_tracker_db.go +++ b/core/services/ocr/mocks/ocr_contract_tracker_db.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go index 0e2f87d082..ccc0feffae 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go index 0e9badc2ac..89c1ec6fd1 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core/mocks/upkeep_state_reader.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go index ab8e9f0494..f05cc8f75f 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/http_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go index c68e7094cc..240e4a7daa 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go index 1aeb0ea85c..79d1033377 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon_coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon_coordinator.go index d62a08f6a8..d12f69fde4 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon_coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon_coordinator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go index 268dff0523..205427f1a7 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go b/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go index 4e4b912c75..7a480dfc8e 100644 --- a/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go +++ b/core/services/ocr2/plugins/promwrapper/mocks/prometheus_backend.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/ocr2/plugins/threshold/mocks/decryptor.go b/core/services/ocr2/plugins/threshold/mocks/decryptor.go index daabd6d7de..b1afed995f 100644 --- a/core/services/ocr2/plugins/threshold/mocks/decryptor.go +++ b/core/services/ocr2/plugins/threshold/mocks/decryptor.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/p2p/types/mocks/peer.go b/core/services/p2p/types/mocks/peer.go index 3a2e218c17..31fb4c10d0 100644 --- a/core/services/p2p/types/mocks/peer.go +++ b/core/services/p2p/types/mocks/peer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/p2p/types/mocks/peer_wrapper.go b/core/services/p2p/types/mocks/peer_wrapper.go index cd20dc7ad9..170ab317f4 100644 --- a/core/services/p2p/types/mocks/peer_wrapper.go +++ b/core/services/p2p/types/mocks/peer_wrapper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/p2p/types/mocks/signer.go b/core/services/p2p/types/mocks/signer.go index baacbef07b..2e3f74a239 100644 --- a/core/services/p2p/types/mocks/signer.go +++ b/core/services/p2p/types/mocks/signer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/pipeline/mocks/config.go b/core/services/pipeline/mocks/config.go index 1c9213443f..91653b8d14 100644 --- a/core/services/pipeline/mocks/config.go +++ b/core/services/pipeline/mocks/config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/pipeline/mocks/orm.go b/core/services/pipeline/mocks/orm.go index 9bd5ddfbde..387df0d41c 100644 --- a/core/services/pipeline/mocks/orm.go +++ b/core/services/pipeline/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/pipeline/mocks/pipeline_param_unmarshaler.go b/core/services/pipeline/mocks/pipeline_param_unmarshaler.go index dcc15bf6fc..cbba896dda 100644 --- a/core/services/pipeline/mocks/pipeline_param_unmarshaler.go +++ b/core/services/pipeline/mocks/pipeline_param_unmarshaler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/pipeline/mocks/runner.go b/core/services/pipeline/mocks/runner.go index 88d71c76c3..cd93fbeab7 100644 --- a/core/services/pipeline/mocks/runner.go +++ b/core/services/pipeline/mocks/runner.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/mercury/mocks/async_deleter.go b/core/services/relay/evm/mercury/mocks/async_deleter.go index 6a43c1a056..181b9080fd 100644 --- a/core/services/relay/evm/mercury/mocks/async_deleter.go +++ b/core/services/relay/evm/mercury/mocks/async_deleter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/mocks/loop_relay_adapter.go b/core/services/relay/evm/mocks/loop_relay_adapter.go index 273589709c..b4eb32729d 100644 --- a/core/services/relay/evm/mocks/loop_relay_adapter.go +++ b/core/services/relay/evm/mocks/loop_relay_adapter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/mocks/request_round_db.go b/core/services/relay/evm/mocks/request_round_db.go index d1aa15a3b5..07d02af533 100644 --- a/core/services/relay/evm/mocks/request_round_db.go +++ b/core/services/relay/evm/mocks/request_round_db.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/relay/evm/types/mocks/log_poller_wrapper.go b/core/services/relay/evm/types/mocks/log_poller_wrapper.go index 46a0b08d0c..4febb45369 100644 --- a/core/services/relay/evm/types/mocks/log_poller_wrapper.go +++ b/core/services/relay/evm/types/mocks/log_poller_wrapper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/s4/mocks/orm.go b/core/services/s4/mocks/orm.go index f616623eb8..9b627d033e 100644 --- a/core/services/s4/mocks/orm.go +++ b/core/services/s4/mocks/orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/s4/mocks/storage.go b/core/services/s4/mocks/storage.go index 5971b9f1ec..29344d9ebf 100644 --- a/core/services/s4/mocks/storage.go +++ b/core/services/s4/mocks/storage.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/synchronization/mocks/telem_client.go b/core/services/synchronization/mocks/telem_client.go index 3ed4247dde..3c19dd07bc 100644 --- a/core/services/synchronization/mocks/telem_client.go +++ b/core/services/synchronization/mocks/telem_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/synchronization/mocks/telemetry_service.go b/core/services/synchronization/mocks/telemetry_service.go index b705d49aec..8c6677e4be 100644 --- a/core/services/synchronization/mocks/telemetry_service.go +++ b/core/services/synchronization/mocks/telemetry_service.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/vrf/mocks/aggregator_v3_interface.go b/core/services/vrf/mocks/aggregator_v3_interface.go index 65351354d7..65bf4f1126 100644 --- a/core/services/vrf/mocks/aggregator_v3_interface.go +++ b/core/services/vrf/mocks/aggregator_v3_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/vrf/mocks/config.go b/core/services/vrf/mocks/config.go index 3685e17b0f..75cbd82d78 100644 --- a/core/services/vrf/mocks/config.go +++ b/core/services/vrf/mocks/config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/vrf/mocks/fee_config.go b/core/services/vrf/mocks/fee_config.go index 0d62898862..df9d5ce1ae 100644 --- a/core/services/vrf/mocks/fee_config.go +++ b/core/services/vrf/mocks/fee_config.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/vrf/mocks/vrf_coordinator_v2.go b/core/services/vrf/mocks/vrf_coordinator_v2.go index e8c1467e44..79b389af23 100644 --- a/core/services/vrf/mocks/vrf_coordinator_v2.go +++ b/core/services/vrf/mocks/vrf_coordinator_v2.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/webhook/mocks/external_initiator_manager.go b/core/services/webhook/mocks/external_initiator_manager.go index 7a3ee29f62..7e0b334f09 100644 --- a/core/services/webhook/mocks/external_initiator_manager.go +++ b/core/services/webhook/mocks/external_initiator_manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/services/webhook/mocks/http_client.go b/core/services/webhook/mocks/http_client.go index 27167f235c..4bc69d5e7e 100644 --- a/core/services/webhook/mocks/http_client.go +++ b/core/services/webhook/mocks/http_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/sessions/ldapauth/mocks/ldap_client.go b/core/sessions/ldapauth/mocks/ldap_client.go index d8fe4dbadf..f902730d02 100644 --- a/core/sessions/ldapauth/mocks/ldap_client.go +++ b/core/sessions/ldapauth/mocks/ldap_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/sessions/ldapauth/mocks/ldap_conn.go b/core/sessions/ldapauth/mocks/ldap_conn.go index 3116320cd9..48783feaf5 100644 --- a/core/sessions/ldapauth/mocks/ldap_conn.go +++ b/core/sessions/ldapauth/mocks/ldap_conn.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/sessions/mocks/authentication_provider.go b/core/sessions/mocks/authentication_provider.go index 3031a7c980..69777f3e96 100644 --- a/core/sessions/mocks/authentication_provider.go +++ b/core/sessions/mocks/authentication_provider.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/core/sessions/mocks/basic_admin_users_orm.go b/core/sessions/mocks/basic_admin_users_orm.go index b8376267c2..800f7b595a 100644 --- a/core/sessions/mocks/basic_admin_users_orm.go +++ b/core/sessions/mocks/basic_admin_users_orm.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks From 33be0f265be3fd68bc969bc4f5d2e7fe6ffcebce Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 26 Jun 2024 12:29:34 -0500 Subject: [PATCH 12/61] core/services/cron: add evmChainID field (#13619) --- core/services/cron/cron.go | 20 ++++++++++++------ core/services/job/models.go | 1 + core/services/job/orm.go | 4 ++-- .../0246_cron_spec_evm_chain_id.sql | 5 +++++ core/testdata/testspecs/v2_specs.go | 19 ++++++++++++++--- core/web/jobs_controller_test.go | 21 +++++++++++++++++++ core/web/presenters/job.go | 4 +++- core/web/presenters/job_test.go | 4 +++- core/web/resolver/spec.go | 11 ++++++++++ core/web/resolver/spec_test.go | 3 +++ core/web/schema/type/spec.graphql | 1 + 11 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 core/store/migrate/migrations/0246_cron_spec_evm_chain_id.sql diff --git a/core/services/cron/cron.go b/core/services/cron/cron.go index 500192554f..aa4d1d782f 100644 --- a/core/services/cron/cron.go +++ b/core/services/cron/cron.go @@ -32,6 +32,9 @@ func NewCronFromJobSpec( "jobID", jobSpec.ID, "schedule", jobSpec.CronSpec.CronSchedule, ) + if id := jobSpec.CronSpec.EVMChainID; id != nil { + cronLogger = logger.With("evmChainID", id) + } return &Cron{ cronRunner: cronRunner(), @@ -48,7 +51,7 @@ func (cr *Cron) Start(context.Context) error { _, err := cr.cronRunner.AddFunc(cr.jobSpec.CronSpec.CronSchedule, cr.runPipeline) if err != nil { - cr.logger.Errorw(fmt.Sprintf("Error running cron job %d", cr.jobSpec.ID), "err", err, "schedule", cr.jobSpec.CronSpec.CronSchedule, "jobID", cr.jobSpec.ID) + cr.logger.Errorw(fmt.Sprintf("Error running cron job %d", cr.jobSpec.ID), "err", err) return err } cr.cronRunner.Start() @@ -67,12 +70,17 @@ func (cr *Cron) runPipeline() { ctx, cancel := cr.chStop.NewCtx() defer cancel() + jobSpec := map[string]interface{}{ + "databaseID": cr.jobSpec.ID, + "externalJobID": cr.jobSpec.ExternalJobID, + "name": cr.jobSpec.Name.ValueOrZero(), + } + if id := cr.jobSpec.CronSpec.EVMChainID; id != nil { + jobSpec["evmChainID"] = id.String() + } + vars := pipeline.NewVarsFrom(map[string]interface{}{ - "jobSpec": map[string]interface{}{ - "databaseID": cr.jobSpec.ID, - "externalJobID": cr.jobSpec.ExternalJobID, - "name": cr.jobSpec.Name.ValueOrZero(), - }, + "jobSpec": jobSpec, "jobRun": map[string]interface{}{ "meta": map[string]interface{}{}, }, diff --git a/core/services/job/models.go b/core/services/job/models.go index 5457768141..a8c12cbece 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -490,6 +490,7 @@ type DirectRequestSpec struct { type CronSpec struct { ID int32 `toml:"-"` CronSchedule string `toml:"schedule"` + EVMChainID *big.Big `toml:"evmChainID"` CreatedAt time.Time `toml:"-"` UpdatedAt time.Time `toml:"-"` } diff --git a/core/services/job/orm.go b/core/services/job/orm.go index efcb088284..de53198546 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -502,8 +502,8 @@ func (o *orm) insertKeeperSpec(ctx context.Context, spec *KeeperSpec) (specID in } func (o *orm) insertCronSpec(ctx context.Context, spec *CronSpec) (specID int32, err error) { - return o.prepareQuerySpecID(ctx, `INSERT INTO cron_specs (cron_schedule, created_at, updated_at) - VALUES (:cron_schedule, NOW(), NOW()) + return o.prepareQuerySpecID(ctx, `INSERT INTO cron_specs (cron_schedule, evm_chain_id, created_at, updated_at) + VALUES (:cron_schedule, :evm_chain_id, NOW(), NOW()) RETURNING id;`, spec) } diff --git a/core/store/migrate/migrations/0246_cron_spec_evm_chain_id.sql b/core/store/migrate/migrations/0246_cron_spec_evm_chain_id.sql new file mode 100644 index 0000000000..d2c0b1582e --- /dev/null +++ b/core/store/migrate/migrations/0246_cron_spec_evm_chain_id.sql @@ -0,0 +1,5 @@ +-- +goose Up +ALTER TABLE cron_specs ADD COLUMN evm_chain_id numeric(78,0); + +-- +goose Down +ALTER TABLE cron_specs DROP COLUMN evm_chain_id; diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go index 949515b335..3a1798ab5a 100644 --- a/core/testdata/testspecs/v2_specs.go +++ b/core/testdata/testspecs/v2_specs.go @@ -24,7 +24,7 @@ var ( type = "cron" schemaVersion = 1 schedule = "CRON_TZ=UTC * 0 0 1 1 *" -externalJobID = "%s" +externalJobID = "%s" observationSource = """ ds [type=http method=GET url="https://chain.link/ETH-USD"]; ds_parse [type=jsonparse path="data,price"]; @@ -36,7 +36,20 @@ ds -> ds_parse -> ds_multiply; type = "cron" schemaVersion = 1 schedule = "CRON_TZ=UTC * 0 0 1 1 *" -externalJobID = "%s" +externalJobID = "%s" +observationSource = """ +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; +""" +` + CronSpecEVMChainIDTemplate = ` +type = "cron" +schemaVersion = 1 +schedule = "CRON_TZ=UTC * 0 0 1 1 *" +externalJobID = "%s" +evmChainID = "42" observationSource = """ ds [type=http method=GET url="https://chain.link/ETH-USD"]; ds_parse [type=jsonparse path="data.price" separator="."]; @@ -62,7 +75,7 @@ type = "directrequest" schemaVersion = 1 name = "%s" contractAddress = "0x613a38AC1659769640aaE063C651F48E0250454C" -externalJobID = "%s" +externalJobID = "%s" evmChainID = "0" observationSource = """ ds1 [type=http method=GET url="http://example.com" allowunrestrictednetworkaccess="true"]; diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 0401dbdb8c..60abe61537 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -28,6 +28,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "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/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -270,6 +271,25 @@ func TestJobController_Create_HappyPath(t *testing.T) { require.Equal(t, "CRON_TZ=UTC * 0 0 1 1 *", jb.CronSpec.CronSchedule) }, }, + { + name: "cron-evm-chain-id", + tomlTemplate: func(nameAndExternalJobID string) string { + return fmt.Sprintf(testspecs.CronSpecEVMChainIDTemplate, nameAndExternalJobID) + }, + assertion: func(t *testing.T, nameAndExternalJobID string, r *http.Response) { + require.Equal(t, http.StatusOK, r.StatusCode) + resource := presenters.JobResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, r), &resource) + assert.NoError(t, err) + + jb, err := jorm.FindJob(testutils.Context(t), mustInt32FromString(t, resource.ID)) + require.NoError(t, err) + require.NotNil(t, jb.CronSpec) + + assert.NotNil(t, resource.PipelineSpec.DotDAGSource) + require.Equal(t, ubig.NewI(42), jb.CronSpec.EVMChainID) + }, + }, { name: "directrequest", tomlTemplate: func(nameAndExternalJobID string) string { @@ -464,6 +484,7 @@ targets: t.Run(c.name, func(t *testing.T) { nameAndExternalJobID := uuid.New().String() toml := c.tomlTemplate(nameAndExternalJobID) + t.Log("Job toml:", toml) body, err := json.Marshal(web.CreateJobRequest{ TOML: toml, }) diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go index 8d7dab626c..ad6bf617a8 100644 --- a/core/web/presenters/job.go +++ b/core/web/presenters/job.go @@ -252,9 +252,10 @@ func NewWebhookSpec(spec *job.WebhookSpec) *WebhookSpec { // CronSpec defines the spec details of a Cron Job type CronSpec struct { - CronSchedule string `json:"schedule" tom:"schedule"` + CronSchedule string `json:"schedule"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` + EVMChainID *big.Big `json:"evmChainID"` } // NewCronSpec generates a new CronSpec from a job.CronSpec @@ -263,6 +264,7 @@ func NewCronSpec(spec *job.CronSpec) *CronSpec { CronSchedule: spec.CronSchedule, CreatedAt: spec.CreatedAt, UpdatedAt: spec.UpdatedAt, + EVMChainID: spec.EVMChainID, } } diff --git a/core/web/presenters/job_test.go b/core/web/presenters/job_test.go index 80856daa8e..5de71f918e 100644 --- a/core/web/presenters/job_test.go +++ b/core/web/presenters/job_test.go @@ -374,6 +374,7 @@ func TestJob(t *testing.T) { CronSchedule: cronSchedule, CreatedAt: timestamp, UpdatedAt: timestamp, + EVMChainID: evmChainID, }, ExternalJobID: uuid.MustParse("0EEC7E1D-D0D2-476C-A1A8-72DFB6633F46"), PipelineSpec: &pipeline.Spec{ @@ -404,7 +405,8 @@ func TestJob(t *testing.T) { "cronSpec": { "schedule": "%s", "createdAt":"2000-01-01T00:00:00Z", - "updatedAt":"2000-01-01T00:00:00Z" + "updatedAt":"2000-01-01T00:00:00Z", + "evmChainID":"42" }, "fluxMonitorSpec": null, "gasLimit": null, diff --git a/core/web/resolver/spec.go b/core/web/resolver/spec.go index b3c22b3b34..00b2442aca 100644 --- a/core/web/resolver/spec.go +++ b/core/web/resolver/spec.go @@ -141,6 +141,17 @@ func (r *CronSpecResolver) Schedule() string { return r.spec.CronSchedule } +// EVMChainID resolves the spec's evm chain id. +func (r *CronSpecResolver) EVMChainID() *string { + if r.spec.EVMChainID == nil { + return nil + } + + chainID := r.spec.EVMChainID.String() + + return &chainID +} + // CreatedAt resolves the spec's created at timestamp. func (r *CronSpecResolver) CreatedAt() graphql.Time { return graphql.Time{Time: r.spec.CreatedAt} diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index 2d5dcc71d1..69d6a56509 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -42,6 +42,7 @@ func TestResolver_CronSpec(t *testing.T) { Type: job.Cron, CronSpec: &job.CronSpec{ CronSchedule: "CRON_TZ=UTC 0 0 1 1 *", + EVMChainID: ubig.NewI(42), CreatedAt: f.Timestamp(), }, }, nil) @@ -54,6 +55,7 @@ func TestResolver_CronSpec(t *testing.T) { __typename ... on CronSpec { schedule + evmChainID createdAt } } @@ -67,6 +69,7 @@ func TestResolver_CronSpec(t *testing.T) { "spec": { "__typename": "CronSpec", "schedule": "CRON_TZ=UTC 0 0 1 1 *", + "evmChainID": "42", "createdAt": "2021-01-01T00:00:00Z" } } diff --git a/core/web/schema/type/spec.graphql b/core/web/schema/type/spec.graphql index db33dd14ee..5a803e2f8e 100644 --- a/core/web/schema/type/spec.graphql +++ b/core/web/schema/type/spec.graphql @@ -16,6 +16,7 @@ union JobSpec = type CronSpec { schedule: String! + evmChainID: String createdAt: Time! } From 36b9645d9582bac5c11533138f6ee6b5760fc36a Mon Sep 17 00:00:00 2001 From: amit-momin <108959691+amit-momin@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:32:17 -0500 Subject: [PATCH 13/61] Updated TXM test for better cleanup (#13698) --- core/chains/evm/txmgr/txmgr_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index dac0ef29cd..4e187571e5 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -603,11 +603,11 @@ func TestTxm_GetTransactionStatus(t *testing.T) { ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() feeEstimator := gasmocks.NewEvmFeeEstimator(t) feeEstimator.On("Start", mock.Anything).Return(nil).Once() + feeEstimator.On("Close", mock.Anything).Return(nil).Once() feeEstimator.On("OnNewLongestChain", mock.Anything, mock.Anything).Once() txm, err := makeTestEvmTxm(t, db, ethClient, feeEstimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), gcfg.Database(), gcfg.Database().Listener(), ethKeyStore) require.NoError(t, err) - err = txm.Start(ctx) - require.NoError(t, err) + servicetest.Run(t, txm) head := &evmtypes.Head{ Hash: utils.NewHash(), From 6f9009f924437c7af7d2845db59f5b28a453c8cc Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 26 Jun 2024 14:38:26 -0400 Subject: [PATCH 14/61] adding new ccip custom provider methods (#13699) * adding new ccip custom provider methods * bumping cosmos --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- core/services/relay/evm/evm.go | 8 ++++++++ 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, 20 insertions(+), 12 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 4ba7eb9e65..c40e4cd41f 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -274,7 +274,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 07fafe50ef..36e6a3d784 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1214,8 +1214,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8um github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index e6732a81cf..bda99d3cb1 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -715,6 +715,14 @@ func (r *Relayer) NewAutomationProvider(rargs commontypes.RelayArgs, pargs commo return ocr2keeperRelayer.NewOCR2KeeperProvider(rargs, pargs) } +func (r *Relayer) NewCCIPCommitProvider(_ commontypes.RelayArgs, _ commontypes.PluginArgs) (commontypes.CCIPCommitProvider, error) { + return nil, errors.New("ccip.commit is not supported for evm") +} + +func (r *Relayer) NewCCIPExecProvider(_ commontypes.RelayArgs, _ commontypes.PluginArgs) (commontypes.CCIPExecProvider, error) { + return nil, errors.New("ccip.exec is not supported for evm") +} + var _ commontypes.MedianProvider = (*medianProvider)(nil) type medianProvider struct { diff --git a/go.mod b/go.mod index 09916e704e..accb1d390a 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 diff --git a/go.sum b/go.sum index d6a715faa5..e541c80b44 100644 --- a/go.sum +++ b/go.sum @@ -1173,8 +1173,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8um github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index bf82d1f8dd..051602164a 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -378,7 +378,7 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c20a0568d2..4a5a9d9843 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1515,8 +1515,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8um github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 2f983f57e4..0fe9777769 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -364,7 +364,7 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index cb05f66879..e7cdbdfcd1 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1505,8 +1505,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8um github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= From 286b02739a8638be0d8d5cd8673da18fb207a1ed Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Thu, 27 Jun 2024 10:24:39 +0200 Subject: [PATCH 15/61] [TT-1304] try CTF with newer eth genesis generator and prysm versions (#13669) * try CTF with newer eth genesis generator and prysm versions * add setup-gap id * use tagged CTF --- .github/workflows/integration-tests.yml | 3 +++ integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index a291b0581a..04d97e1838 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -323,6 +323,7 @@ jobs: fi - name: Setup GAP for Grafana uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 + id: setup-gap with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -438,6 +439,7 @@ jobs: fi - name: Setup GAP for Grafana uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 + id: setup-gap with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -667,6 +669,7 @@ jobs: docker logs otel-collector - name: Setup GAP for Grafana uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 + id: setup-gap with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 051602164a..d309944701 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -29,7 +29,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf - github.com/smartcontractkit/chainlink-testing-framework v1.31.4 + github.com/smartcontractkit/chainlink-testing-framework v1.31.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 4a5a9d9843..b301068a55 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1525,8 +1525,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.31.4 h1:5/zF5Z2w+/HTvUSSJNhWSiHvlQ2O2qxRw4e1fBbVraQ= -github.com/smartcontractkit/chainlink-testing-framework v1.31.4/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= +github.com/smartcontractkit/chainlink-testing-framework v1.31.5 h1:PemXseNS74zz1Oitm1MOCeJyQSIYCFck/QsnjM1y06c= +github.com/smartcontractkit/chainlink-testing-framework v1.31.5/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= 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-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 0fe9777769..5dba281f1e 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.1.7-0.20240625074419-c278d083facf - github.com/smartcontractkit/chainlink-testing-framework v1.31.4 + github.com/smartcontractkit/chainlink-testing-framework v1.31.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-20240419185742-fd3cab206b2c diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index e7cdbdfcd1..075883054c 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1515,8 +1515,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.31.4 h1:5/zF5Z2w+/HTvUSSJNhWSiHvlQ2O2qxRw4e1fBbVraQ= -github.com/smartcontractkit/chainlink-testing-framework v1.31.4/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= +github.com/smartcontractkit/chainlink-testing-framework v1.31.5 h1:PemXseNS74zz1Oitm1MOCeJyQSIYCFck/QsnjM1y06c= +github.com/smartcontractkit/chainlink-testing-framework v1.31.5/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= 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-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= From 884fca7512b77bdef987816166addffba5a1d403 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Thu, 27 Jun 2024 11:33:19 +0200 Subject: [PATCH 16/61] rm hardhat split tests (#13682) * rm hardhat split tests * cleanup --- .github/actions/split-tests/.npmrc | 2 - .github/actions/split-tests/action.yaml | 35 - .github/actions/split-tests/jest.config.js | 15 - .github/actions/split-tests/mjs-resolver.ts | 15 - .github/actions/split-tests/package.json | 30 - .github/actions/split-tests/pnpm-lock.yaml | 3071 ----------------- .github/actions/split-tests/src/index.mts | 74 - .github/actions/split-tests/src/sieve.mts | 27 - .github/actions/split-tests/src/splitter.mts | 43 - .github/actions/split-tests/src/types.mts | 75 - .../test/__snapshots__/sieve.test.ts.snap | 99 - .../test/__snapshots__/splitter.test.ts.snap | 119 - .github/actions/split-tests/test/fixtures.mts | 20 - .../actions/split-tests/test/sieve.test.ts | 15 - .../actions/split-tests/test/splitter.test.ts | 21 - .github/actions/split-tests/tsconfig.json | 104 - .github/workflows/solidity-foundry.yml | 4 - .github/workflows/solidity-hardhat.yml | 46 +- contracts/.prettierignore | 1 - contracts/ci.json | 15 - contracts/foundry.toml | 2 +- 21 files changed, 8 insertions(+), 3825 deletions(-) delete mode 100644 .github/actions/split-tests/.npmrc delete mode 100644 .github/actions/split-tests/action.yaml delete mode 100644 .github/actions/split-tests/jest.config.js delete mode 100644 .github/actions/split-tests/mjs-resolver.ts delete mode 100644 .github/actions/split-tests/package.json delete mode 100644 .github/actions/split-tests/pnpm-lock.yaml delete mode 100644 .github/actions/split-tests/src/index.mts delete mode 100644 .github/actions/split-tests/src/sieve.mts delete mode 100644 .github/actions/split-tests/src/splitter.mts delete mode 100644 .github/actions/split-tests/src/types.mts delete mode 100644 .github/actions/split-tests/test/__snapshots__/sieve.test.ts.snap delete mode 100644 .github/actions/split-tests/test/__snapshots__/splitter.test.ts.snap delete mode 100644 .github/actions/split-tests/test/fixtures.mts delete mode 100644 .github/actions/split-tests/test/sieve.test.ts delete mode 100644 .github/actions/split-tests/test/splitter.test.ts delete mode 100644 .github/actions/split-tests/tsconfig.json delete mode 100644 contracts/ci.json diff --git a/.github/actions/split-tests/.npmrc b/.github/actions/split-tests/.npmrc deleted file mode 100644 index 4c2f52b3be..0000000000 --- a/.github/actions/split-tests/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -auto-install-peers=true -strict-peer-dependencies=false diff --git a/.github/actions/split-tests/action.yaml b/.github/actions/split-tests/action.yaml deleted file mode 100644 index d11f0bcbc3..0000000000 --- a/.github/actions/split-tests/action.yaml +++ /dev/null @@ -1,35 +0,0 @@ -name: Test Spliting -description: Split tests -inputs: - config: - required: true - description: The path to the splitting config -outputs: - splits: - description: The generated test splits - value: ${{ steps.split.outputs.splits }} -runs: - using: composite - steps: - - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 - with: - version: ^8.0.0 - - - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 - with: - node-version: "16" - cache: "pnpm" - cache-dependency-path: "./.github/actions/split-tests/pnpm-lock.yaml" - - - name: Install dependencies - shell: bash - run: pnpm i --prod - working-directory: "./.github/actions/split-tests" - - - name: Run test spliter - id: split - shell: bash - run: pnpm start - env: - CONFIG: ${{ inputs.config }} - working-directory: "./.github/actions/split-tests" diff --git a/.github/actions/split-tests/jest.config.js b/.github/actions/split-tests/jest.config.js deleted file mode 100644 index 7b3dcf296f..0000000000 --- a/.github/actions/split-tests/jest.config.js +++ /dev/null @@ -1,15 +0,0 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ -const jestConfig = { - preset: "ts-jest/presets/default-esm", - resolver: "/mjs-resolver.ts", - transform: { - "^.+\\.mts?$": [ - "ts-jest", - { - useESM: true, - }, - ], - }, - testEnvironment: "node", -}; -export default jestConfig; diff --git a/.github/actions/split-tests/mjs-resolver.ts b/.github/actions/split-tests/mjs-resolver.ts deleted file mode 100644 index 92c66f7b6c..0000000000 --- a/.github/actions/split-tests/mjs-resolver.ts +++ /dev/null @@ -1,15 +0,0 @@ -const mjsResolver = (path, options) => { - const mjsExtRegex = /\.mjs$/i; - const resolver = options.defaultResolver; - if (mjsExtRegex.test(path)) { - try { - return resolver(path.replace(mjsExtRegex, ".mts"), options); - } catch { - // use default resolver - } - } - - return resolver(path, options); -}; - -module.exports = mjsResolver; diff --git a/.github/actions/split-tests/package.json b/.github/actions/split-tests/package.json deleted file mode 100644 index 10a71c0b35..0000000000 --- a/.github/actions/split-tests/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "shard-packages", - "version": "1.0.0", - "description": "", - "type": "module", - "main": "index.js", - "scripts": { - "start": "ts-node -T --esm ./src/index.mts", - "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js" - }, - "keywords": [], - "author": "", - "license": "MIT", - "engines": { - "node": "^16.0.0", - "pnpm": "^8.0.0" - }, - "dependencies": { - "@actions/core": "^1.10.1", - "ts-node": "^10.9.2", - "zx": "^7.2.3" - }, - "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "^18.19.32", - "jest": "^29.7.0", - "ts-jest": "^29.1.2", - "typescript": "^5.4.5" - } -} diff --git a/.github/actions/split-tests/pnpm-lock.yaml b/.github/actions/split-tests/pnpm-lock.yaml deleted file mode 100644 index 730971e0c6..0000000000 --- a/.github/actions/split-tests/pnpm-lock.yaml +++ /dev/null @@ -1,3071 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - '@actions/core': - specifier: ^1.10.1 - version: 1.10.1 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@18.19.32)(typescript@5.4.5) - zx: - specifier: ^7.2.3 - version: 7.2.3 - -devDependencies: - '@types/jest': - specifier: ^29.5.12 - version: 29.5.12 - '@types/node': - specifier: ^18.19.32 - version: 18.19.32 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@18.19.32)(ts-node@10.9.2) - ts-jest: - specifier: ^29.1.2 - version: 29.1.2(@babel/core@7.19.3)(jest@29.7.0)(typescript@5.4.5) - typescript: - specifier: ^5.4.5 - version: 5.4.5 - -packages: - - /@actions/core@1.10.1: - resolution: {integrity: sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==} - dependencies: - '@actions/http-client': 2.0.1 - uuid: 8.3.2 - dev: false - - /@actions/http-client@2.0.1: - resolution: {integrity: sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==} - dependencies: - tunnel: 0.0.6 - dev: false - - /@ampproject/remapping@2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@babel/code-frame@7.18.6: - resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - dev: true - - /@babel/code-frame@7.24.2: - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.2 - picocolors: 1.0.0 - dev: true - - /@babel/compat-data@7.19.3: - resolution: {integrity: sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/compat-data@7.24.4: - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.19.3: - resolution: {integrity: sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.19.3 - '@babel/helper-compilation-targets': 7.19.3(@babel/core@7.19.3) - '@babel/helper-module-transforms': 7.19.0 - '@babel/helpers': 7.19.0 - '@babel/parser': 7.19.3 - '@babel/template': 7.18.10 - '@babel/traverse': 7.24.1 - '@babel/types': 7.19.3 - convert-source-map: 1.8.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/core@7.24.4: - resolution: {integrity: sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helpers': 7.24.4 - '@babel/parser': 7.24.4 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.19.3: - resolution: {integrity: sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.19.3 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - dev: true - - /@babel/generator@7.24.4: - resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.19.3(@babel/core@7.19.3): - resolution: {integrity: sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.19.3 - '@babel/core': 7.19.3 - '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.4 - semver: 6.3.0 - dev: true - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.18.9: - resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-imports@7.18.6: - resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.19.3 - dev: true - - /@babel/helper-module-imports@7.24.3: - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-transforms@7.19.0: - resolution: {integrity: sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.18.10 - '@babel/traverse': 7.24.1 - '@babel/types': 7.19.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4): - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - - /@babel/helper-plugin-utils@7.19.0: - resolution: {integrity: sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-simple-access@7.18.6: - resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.19.3 - dev: true - - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-split-export-declaration@7.18.6: - resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.19.3 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-string-parser@7.18.10: - resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-string-parser@7.24.1: - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.18.6: - resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.19.0: - resolution: {integrity: sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.18.10 - '@babel/traverse': 7.24.1 - '@babel/types': 7.19.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helpers@7.24.4: - resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/highlight@7.24.2: - resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.0 - dev: true - - /@babel/parser@7.19.3: - resolution: {integrity: sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.19.3 - dev: true - - /@babel/parser@7.24.4: - resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.19.3 - dev: true - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.19.3): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.19.3): - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.19.3): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.19.3): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.19.3): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.19.3): - resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.19.3): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.19.3): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.19.3): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.19.3): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.19.3): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.19.3): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.19.3): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/plugin-syntax-typescript@7.18.6(@babel/core@7.19.3): - resolution: {integrity: sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.3 - '@babel/helper-plugin-utils': 7.19.0 - dev: true - - /@babel/template@7.18.10: - resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.19.3 - '@babel/types': 7.19.3 - dev: true - - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - dev: true - - /@babel/traverse@7.24.1: - resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.19.3: - resolution: {integrity: sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.18.10 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - dev: true - - /@babel/types@7.24.0: - resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - dev: true - - /@bcoe/v8-coverage@0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true - - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - - /@istanbuljs/load-nyc-config@1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - dev: true - - /@istanbuljs/schema@0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true - - /@jest/console@29.7.0: - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - dev: true - - /@jest/core@29.7.0(ts-node@10.9.2): - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.4.0 - exit: 0.1.2 - graceful-fs: 4.2.10 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.32)(ts-node@10.9.2) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.5 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /@jest/environment@29.7.0: - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - jest-mock: 29.7.0 - dev: true - - /@jest/expect-utils@29.1.2: - resolution: {integrity: sha512-4a48bhKfGj/KAH39u0ppzNTABXQ8QPccWAFUFobWBaEMSMp+sB31Z2fK/l47c4a/Mu1po2ffmfAIPxXbVTXdtg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.0.0 - dev: true - - /@jest/expect-utils@29.7.0: - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - dev: true - - /@jest/expect@29.7.0: - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/fake-timers@29.7.0: - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 18.19.32 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - - /@jest/globals@29.7.0: - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/reporters@29.7.0: - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 18.19.32 - chalk: 4.1.2 - collect-v8-coverage: 1.0.1 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-instrument: 6.0.2 - istanbul-lib-report: 3.0.0 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.5 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/schemas@29.0.0: - resolution: {integrity: sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.24.44 - dev: true - - /@jest/schemas@29.6.3: - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - dev: true - - /@jest/source-map@29.6.3: - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.10 - dev: true - - /@jest/test-result@29.7.0: - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.4 - collect-v8-coverage: 1.0.1 - dev: true - - /@jest/test-sequencer@29.7.0: - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.10 - jest-haste-map: 29.7.0 - slash: 3.0.0 - dev: true - - /@jest/transform@29.7.0: - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.19.3 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.10 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.5 - pirates: 4.0.5 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/types@29.1.2: - resolution: {integrity: sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.0.0 - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.1 - '@types/node': 18.19.32 - '@types/yargs': 17.0.13 - chalk: 4.1.2 - dev: true - - /@jest/types@29.6.3: - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.1 - '@types/node': 18.19.32 - '@types/yargs': 17.0.13 - chalk: 4.1.2 - dev: true - - /@jridgewell/gen-mapping@0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@jridgewell/gen-mapping@0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.15 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} - - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - - /@jridgewell/trace-mapping@0.3.15: - resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: false - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: false - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.13.0 - dev: false - - /@sinclair/typebox@0.24.44: - resolution: {integrity: sha512-ka0W0KN5i6LfrSocduwliMMpqVgohtPFidKdMEOUjoOFCHcOOYkKsPRxfs5f15oPNHTm6ERAm0GV/+/LTKeiWg==} - dev: true - - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true - - /@sinonjs/commons@3.0.1: - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - dependencies: - type-detect: 4.0.8 - dev: true - - /@sinonjs/fake-timers@10.3.0: - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - dependencies: - '@sinonjs/commons': 3.0.1 - dev: true - - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - /@tsconfig/node16@1.0.3: - resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} - - /@types/babel__core@7.1.19: - resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==} - dependencies: - '@babel/parser': 7.19.3 - '@babel/types': 7.19.3 - '@types/babel__generator': 7.6.4 - '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.18.2 - dev: true - - /@types/babel__generator@7.6.4: - resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} - dependencies: - '@babel/types': 7.19.3 - dev: true - - /@types/babel__template@7.4.1: - resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} - dependencies: - '@babel/parser': 7.19.3 - '@babel/types': 7.19.3 - dev: true - - /@types/babel__traverse@7.18.2: - resolution: {integrity: sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==} - dependencies: - '@babel/types': 7.19.3 - dev: true - - /@types/fs-extra@11.0.4: - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - dependencies: - '@types/jsonfile': 6.1.4 - '@types/node': 18.19.32 - dev: false - - /@types/graceful-fs@4.1.5: - resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} - dependencies: - '@types/node': 18.19.32 - dev: true - - /@types/istanbul-lib-coverage@2.0.4: - resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} - dev: true - - /@types/istanbul-lib-report@3.0.0: - resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} - dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - dev: true - - /@types/istanbul-reports@3.0.1: - resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} - dependencies: - '@types/istanbul-lib-report': 3.0.0 - dev: true - - /@types/jest@29.5.12: - resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} - dependencies: - expect: 29.1.2 - pretty-format: 29.1.2 - dev: true - - /@types/jsonfile@6.1.4: - resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} - dependencies: - '@types/node': 18.19.32 - dev: false - - /@types/minimist@1.2.2: - resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} - dev: false - - /@types/node@18.19.32: - resolution: {integrity: sha512-2bkg93YBSDKk8DLmmHnmj/Rwr18TLx7/n+I23BigFwgexUJoMHZOd8X1OFxuF/W3NN0S2W2E5sVabI5CPinNvA==} - dependencies: - undici-types: 5.26.5 - - /@types/ps-tree@1.1.2: - resolution: {integrity: sha512-ZREFYlpUmPQJ0esjxoG1fMvB2HNaD3z+mjqdSosZvd3RalncI9NEur73P8ZJz4YQdL64CmV1w0RuqoRUlhQRBw==} - dev: false - - /@types/stack-utils@2.0.1: - resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} - dev: true - - /@types/which@3.0.3: - resolution: {integrity: sha512-2C1+XoY0huExTbs8MQv1DuS5FS86+SEjdM9F/+GS61gg5Hqbtj8ZiDSx8MfWcyei907fIPbfPGCOrNUTnVHY1g==} - dev: false - - /@types/yargs-parser@21.0.0: - resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} - dev: true - - /@types/yargs@17.0.13: - resolution: {integrity: sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==} - dependencies: - '@types/yargs-parser': 21.0.0 - dev: true - - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - - /acorn@8.8.0: - resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} - engines: {node: '>=0.4.0'} - hasBin: true - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true - - /anymatch@3.1.2: - resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /babel-jest@29.7.0(@babel/core@7.19.3): - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - dependencies: - '@babel/core': 7.19.3 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.1.19 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.19.3) - chalk: 4.1.2 - graceful-fs: 4.2.10 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.19.0 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/template': 7.18.10 - '@babel/types': 7.19.3 - '@types/babel__core': 7.1.19 - '@types/babel__traverse': 7.18.2 - dev: true - - /babel-preset-current-node-syntax@1.0.1(@babel/core@7.19.3): - resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.19.3 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.19.3) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.19.3) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.19.3) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.19.3) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.19.3) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.19.3) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.19.3) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.19.3) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.19.3) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.19.3) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.19.3) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.19.3) - dev: true - - /babel-preset-jest@29.6.3(@babel/core@7.19.3): - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.19.3 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.19.3) - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - - /browserslist@4.21.4: - resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001418 - electron-to-chromium: 1.4.275 - node-releases: 2.0.6 - update-browserslist-db: 1.0.10(browserslist@4.21.4) - dev: true - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001607 - electron-to-chromium: 1.4.730 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) - dev: true - - /bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - dependencies: - fast-json-stable-stringify: 2.1.0 - dev: true - - /bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /caniuse-lite@1.0.30001418: - resolution: {integrity: sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==} - dev: true - - /caniuse-lite@1.0.30001607: - resolution: {integrity: sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==} - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: false - - /char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - dev: true - - /ci-info@3.4.0: - resolution: {integrity: sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==} - dev: true - - /cjs-module-lexer@1.2.2: - resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==} - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - - /collect-v8-coverage@1.0.1: - resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} - dev: true - - /convert-source-map@1.8.0: - resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /create-jest@29.7.0(@types/node@18.19.32)(ts-node@10.9.2): - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.10 - jest-config: 29.7.0(@types/node@18.19.32)(ts-node@10.9.2) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /data-uri-to-buffer@4.0.0: - resolution: {integrity: sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==} - engines: {node: '>= 12'} - dev: false - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /dedent@1.5.1: - resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - dev: true - - /deepmerge@4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} - engines: {node: '>=0.10.0'} - dev: true - - /detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - dev: true - - /diff-sequences@29.0.0: - resolution: {integrity: sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: false - - /duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - dev: false - - /electron-to-chromium@1.4.275: - resolution: {integrity: sha512-aJeQQ+Hl9Jyyzv4chBqYJwmVRY46N5i2BEX5Cuyk/5gFCUZ5F3i7Hnba6snZftWla7Gglwc5pIgcd+E7cW+rPg==} - dev: true - - /electron-to-chromium@1.4.730: - resolution: {integrity: sha512-oJRPo82XEqtQAobHpJIR3zW5YO3sSRRkPz2an4yxi1UvqhsGm54vR/wzTFV74a3soDOJ8CKW7ajOOX5ESzddwg==} - dev: true - - /emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /event-stream@3.3.4: - resolution: {integrity: sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=} - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - dev: false - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - dev: true - - /expect@29.1.2: - resolution: {integrity: sha512-AuAGn1uxva5YBbBlXb+2JPxJRuemZsmlGcapPXWNSBNsQtAULfjioREGBWuI0EOvYUKjDnrCy8PW5Zlr1md5mw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.1.2 - jest-get-type: 29.0.0 - jest-matcher-utils: 29.1.2 - jest-message-util: 29.1.2 - jest-util: 29.1.2 - dev: true - - /expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: false - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fastq@1.13.0: - resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} - dependencies: - reusify: 1.0.4 - dev: false - - /fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - dependencies: - bser: 2.1.1 - dev: true - - /fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.2.1 - dev: false - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - dependencies: - fetch-blob: 3.2.0 - dev: false - - /from@0.1.7: - resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - dev: false - - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.10 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: false - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true - - /fx@34.0.0: - resolution: {integrity: sha512-/fZih3/WLsrtlaj2mahjWxAmyuikmcl3D5kKPqLtFmEilLsy9wp0+/vEmfvYXXhwJc+ajtCFDCf+yttXmPMHSQ==} - hasBin: true - dev: false - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: false - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: false - - /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - dev: true - - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: false - - /import-local@3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} - engines: {node: '>=8'} - hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-core-module@2.10.0: - resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} - dependencies: - has: 1.0.3 - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: false - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: false - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - /istanbul-lib-coverage@3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} - engines: {node: '>=8'} - dev: true - - /istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.19.3 - '@babel/parser': 7.19.3 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-instrument@6.0.2: - resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} - engines: {node: '>=10'} - dependencies: - '@babel/core': 7.24.4 - '@babel/parser': 7.24.4 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-report@3.0.0: - resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} - engines: {node: '>=8'} - dependencies: - istanbul-lib-coverage: 3.2.0 - make-dir: 3.1.0 - supports-color: 7.2.0 - dev: true - - /istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.3.4 - istanbul-lib-coverage: 3.2.0 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-reports@3.1.5: - resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.0 - dev: true - - /jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - dev: true - - /jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.1 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.5 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - - /jest-cli@29.7.0(@types/node@18.19.32)(ts-node@10.9.2): - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.32)(ts-node@10.9.2) - exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@18.19.32)(ts-node@10.9.2) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.6.0 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /jest-config@29.7.0(@types/node@18.19.32)(ts-node@10.9.2): - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - dependencies: - '@babel/core': 7.19.3 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - babel-jest: 29.7.0(@babel/core@7.19.3) - chalk: 4.1.2 - ci-info: 3.4.0 - deepmerge: 4.2.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - ts-node: 10.9.2(@types/node@18.19.32)(typescript@5.4.5) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - - /jest-diff@29.1.2: - resolution: {integrity: sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.0.0 - jest-get-type: 29.0.0 - pretty-format: 29.1.2 - dev: true - - /jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - detect-newline: 3.1.0 - dev: true - - /jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - dev: true - - /jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - - /jest-get-type@29.0.0: - resolution: {integrity: sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.5 - '@types/node': 18.19.32 - anymatch: 3.1.2 - fb-watchman: 2.0.2 - graceful-fs: 4.2.10 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.5 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-matcher-utils@29.1.2: - resolution: {integrity: sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.1.2 - jest-get-type: 29.0.0 - pretty-format: 29.1.2 - dev: true - - /jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-message-util@29.1.2: - resolution: {integrity: sha512-9oJ2Os+Qh6IlxLpmvshVbGUiSkZVc2FK+uGOm6tghafnB2RyjKAxMZhtxThRMxfX1J1SOMhTn9oK3/MutRWQJQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.18.6 - '@jest/types': 29.1.2 - '@types/stack-utils': 2.0.1 - chalk: 4.1.2 - graceful-fs: 4.2.10 - micromatch: 4.0.5 - pretty-format: 29.1.2 - slash: 3.0.0 - stack-utils: 2.0.5 - dev: true - - /jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.18.6 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.1 - chalk: 4.1.2 - graceful-fs: 4.2.10 - micromatch: 4.0.5 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.5 - dev: true - - /jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - jest-util: 29.7.0 - dev: true - - /jest-pnp-resolver@1.2.2(jest-resolve@29.7.0): - resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: - jest-resolve: 29.7.0 - dev: true - - /jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.10 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.2(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.1 - resolve.exports: 2.0.2 - slash: 3.0.0 - dev: true - - /jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.10 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - chalk: 4.1.2 - cjs-module-lexer: 1.2.2 - collect-v8-coverage: 1.0.1 - glob: 7.2.3 - graceful-fs: 4.2.10 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.19.3 - '@babel/generator': 7.19.3 - '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.19.3) - '@babel/plugin-syntax-typescript': 7.18.6(@babel/core@7.19.3) - '@babel/types': 7.19.3 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.19.3) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.10 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-util@29.1.2: - resolution: {integrity: sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.1.2 - '@types/node': 18.19.32 - chalk: 4.1.2 - ci-info: 3.4.0 - graceful-fs: 4.2.10 - picomatch: 2.3.1 - dev: true - - /jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - chalk: 4.1.2 - ci-info: 3.4.0 - graceful-fs: 4.2.10 - picomatch: 2.3.1 - dev: true - - /jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - dev: true - - /jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.32 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - dev: true - - /jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@types/node': 18.19.32 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /jest@29.7.0(@types/node@18.19.32)(ts-node@10.9.2): - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) - '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@18.19.32)(ts-node@10.9.2) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.0 - optionalDependencies: - graceful-fs: 4.2.10 - dev: false - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.0 - dev: true - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - /makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - dependencies: - tmpl: 1.0.5 - dev: true - - /map-stream@0.1.0: - resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - dev: false - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: false - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: false - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - dev: false - - /node-fetch@3.3.1: - resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - data-uri-to-buffer: 4.0.0 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - dev: false - - /node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - dev: true - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true - - /node-releases@2.0.6: - resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.18.6 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: false - - /pause-stream@0.0.11: - resolution: {integrity: sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=} - dependencies: - through: 2.3.8 - dev: false - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - /pirates@4.0.5: - resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} - engines: {node: '>= 6'} - dev: true - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /pretty-format@29.1.2: - resolution: {integrity: sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.0.0 - ansi-styles: 5.2.0 - react-is: 18.2.0 - dev: true - - /pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.2.0 - dev: true - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /ps-tree@1.2.0: - resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} - engines: {node: '>= 0.10'} - hasBin: true - dependencies: - event-stream: 3.3.4 - dev: false - - /pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: false - - /react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve.exports@2.0.2: - resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} - engines: {node: '>=10'} - dev: true - - /resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true - dependencies: - is-core-module: 2.10.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: false - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: false - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: false - - /source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /split@0.3.3: - resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - dependencies: - through: 2.3.8 - dev: false - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /stack-utils@2.0.5: - resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - dev: true - - /stream-combiner@0.0.4: - resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} - dependencies: - duplexer: 0.1.2 - dev: false - - /string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true - - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: false - - /tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - - /ts-jest@29.1.2(@babel/core@7.19.3)(jest@29.7.0)(typescript@5.4.5): - resolution: {integrity: sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==} - engines: {node: ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - dependencies: - '@babel/core': 7.19.3 - bs-logger: 0.2.6 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.19.32)(ts-node@10.9.2) - jest-util: 29.1.2 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.0 - typescript: 5.4.5 - yargs-parser: 21.1.1 - dev: true - - /ts-node@10.9.2(@types/node@18.19.32)(typescript@5.4.5): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - 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': 18.19.32 - acorn: 8.8.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 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - /tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - dev: false - - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} - engines: {node: '>=14.17'} - hasBin: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - /universalify@2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} - engines: {node: '>= 10.0.0'} - dev: false - - /update-browserslist-db@1.0.10(browserslist@4.21.4): - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.21.4 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - - /update-browserslist-db@1.0.13(browserslist@4.23.0): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: false - - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - - /v8-to-istanbul@9.0.1: - resolution: {integrity: sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==} - engines: {node: '>=10.12.0'} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.4 - convert-source-map: 1.8.0 - dev: true - - /walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - dependencies: - makeerror: 1.0.12 - dev: true - - /web-streams-polyfill@3.2.1: - resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} - engines: {node: '>= 8'} - dev: false - - /webpod@0.0.2: - resolution: {integrity: sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg==} - hasBin: true - dev: false - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: false - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yaml@2.4.1: - resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} - engines: {node: '>= 14'} - hasBin: true - dev: false - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs@17.6.0: - resolution: {integrity: sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==} - engines: {node: '>=12'} - 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 - dev: true - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /zx@7.2.3: - resolution: {integrity: sha512-QODu38nLlYXg/B/Gw7ZKiZrvPkEsjPN3LQ5JFXM7h0JvwhEdPNNl+4Ao1y4+o3CLNiDUNcwzQYZ4/Ko7kKzCMA==} - engines: {node: '>= 16.0.0'} - hasBin: true - dependencies: - '@types/fs-extra': 11.0.4 - '@types/minimist': 1.2.2 - '@types/node': 18.19.32 - '@types/ps-tree': 1.1.2 - '@types/which': 3.0.3 - chalk: 5.3.0 - fs-extra: 11.2.0 - fx: 34.0.0 - globby: 13.2.2 - minimist: 1.2.8 - node-fetch: 3.3.1 - ps-tree: 1.2.0 - webpod: 0.0.2 - which: 3.0.1 - yaml: 2.4.1 - dev: false diff --git a/.github/actions/split-tests/src/index.mts b/.github/actions/split-tests/src/index.mts deleted file mode 100644 index 43f9eb1316..0000000000 --- a/.github/actions/split-tests/src/index.mts +++ /dev/null @@ -1,74 +0,0 @@ -import { $, cd, glob, fs } from "zx"; -import path from "node:path"; -import { setOutput } from "@actions/core"; -import { SolidityConfig, SoliditySplit } from "./types.mjs"; -import { sieveSlowTests } from "./sieve.mjs"; -import { simpleSplit } from "./splitter.mjs"; - -/** - * Get a JSON formatted config file - * - * @param path The path to the config relative to the git root - */ -function getConfigFrom(path?: string): SolidityConfig { - if (!path) { - throw Error("No config path given, specify a path via $CONFIG"); - } - try { - const config = fs.readJsonSync(path); - return config; - } catch (e: unknown) { - throw Error( - `Could not find config file at path: ${path}. ${(e as Error).message}` - ); - } -} - -async function main() { - $.verbose = false; - await runAtGitRoot(); - const configPath = process.env.CONFIG; - const config = getConfigFrom(configPath); - if (config.type === "solidity") { - await handleSolidity(config); - } else { - throw Error(`Invalid config given`); - } -} -main(); - -async function handleSolidity(config: SolidityConfig) { - const { basePath, splits: configBySplit } = config; - const splits = await Promise.all( - configBySplit.map( - async ({ dir, numOfSplits, slowTests: slowTestMatchers }) => { - const globPath = path.join(basePath, dir, "/**/*.test.ts"); - const rawTests = await glob(globPath); - const pathMappedTests = rawTests.map((r) => - r.replace("contracts/", "") - ); - const { filteredTests, slowTests } = sieveSlowTests( - pathMappedTests, - slowTestMatchers - ); - const testsBySplit = simpleSplit(filteredTests, slowTests, numOfSplits); - const splits: SoliditySplit[] = testsBySplit.map((tests, i) => ({ - idx: `${dir}_${i + 1}`, - id: `${dir} ${i + 1}/${numOfSplits}`, - tests: tests.join(" "), - coverageTests: - tests.length === 1 ? tests.join(",") : `{${tests.join(",")}}`, - })); - return splits; - } - ) - ); - - const serializedSplits = JSON.stringify(splits.flat()); - setOutput("splits", serializedSplits); -} - -async function runAtGitRoot() { - const gitRoot = await $`git rev-parse --show-toplevel`; - cd(gitRoot.stdout.trimEnd()); -} diff --git a/.github/actions/split-tests/src/sieve.mts b/.github/actions/split-tests/src/sieve.mts deleted file mode 100644 index 93573669a7..0000000000 --- a/.github/actions/split-tests/src/sieve.mts +++ /dev/null @@ -1,27 +0,0 @@ -import {Tests} from "./types.mjs"; - -export function sieveSlowTests(tests: Tests, slowTestMatchers?: string[]) { - const slowTests: Tests = []; - const filteredTests: Tests = []; - - if (!slowTestMatchers) { - return {slowTests, filteredTests: tests}; - } - - // If the user supplies slow test matchers - // then we go through each test to see if we get a case sensitive match - - tests.forEach((t) => { - const isSlow = slowTestMatchers.reduce( - (isSlow, matcher) => t.includes(matcher) || isSlow, - false - ); - if (isSlow) { - slowTests.push(t); - } else { - filteredTests.push(t); - } - }); - - return {slowTests, filteredTests}; -} diff --git a/.github/actions/split-tests/src/splitter.mts b/.github/actions/split-tests/src/splitter.mts deleted file mode 100644 index f924df5508..0000000000 --- a/.github/actions/split-tests/src/splitter.mts +++ /dev/null @@ -1,43 +0,0 @@ -import {Tests, TestsBySplit} from "./types.mjs"; - -/** - * Split tests by first prioritizing slow tests being spread over each split, then filling each split by test list order. - * - * @example - * Given the following arguments: - * tests: ['foo.test', 'bar.test', 'baz.test', 'yup.test', 'nope.test'] - * slowTests: ['bonk.test', 'bop.test', 'ouch.test.ts'] - * numOfSplits: 2 - * - * We get the following output: - * 1. Spread slow tests across splits: [['bonk.test', 'ouch.test.ts'], ['bop.test']] - * 2. Insert list of tests: [['bonk.test', 'ouch.test.ts', 'foo.test', 'bar.test'], ['bop.test', 'baz.test', 'yup.test', 'nope.test']] - * - * @param tests A list of tests to distribute across splits by the test list order - * @param slowTests A list of slow tests, where the list of tests is evenly distributed across all splits before inserting regular tests - * @param numOfSplits The number of splits to spread tests across - */ -export function simpleSplit( - tests: Tests, - slowTests: Tests, - numOfSplits: number -): TestsBySplit { - const maxTestsPerSplit = Math.max(tests.length / numOfSplits); - - const testsBySplit: TestsBySplit = new Array(numOfSplits) - .fill(null) - .map(() => []); - - // Evenly distribute slow tests over each split - slowTests.forEach((test, i) => { - const splitIndex = i % numOfSplits; - testsBySplit[splitIndex].push(test); - }); - - tests.forEach((test, i) => { - const splitIndex = Math.floor(i / maxTestsPerSplit); - testsBySplit[splitIndex].push(test); - }); - - return testsBySplit; -} diff --git a/.github/actions/split-tests/src/types.mts b/.github/actions/split-tests/src/types.mts deleted file mode 100644 index 3eae2f0eb9..0000000000 --- a/.github/actions/split-tests/src/types.mts +++ /dev/null @@ -1,75 +0,0 @@ -/** - * An array of all tests - */ -export type Tests = string[]; - -/** - * An array of tests, indexed by split - */ -export type TestsBySplit = string[][]; - -export interface Split { - /** - * The split index - * @example "4" - */ - idx: string; - - /** - * The split index in the context of all splits - * @example "4/10" - */ - id: string; -} - -export interface SoliditySplit extends Split { - /** - * A string that contains a whitespace delimited list of tests to run - * - * This format is to support the `hardhat test` command. - * @example test/foo.test.ts test/bar.test.ts - */ - tests: string; - - /** - * A string that contains a glob that expresses the list of tests to run. - * - * This format is used to conform to the --testfiles flag of solidity-coverage - * @example {test/foo.test.ts,test/bar.test.ts} - */ - coverageTests: string; -} - -/** - * Configuration file for solidity tests - */ -export interface SolidityConfig { - type: "solidity"; - /** - * The path to the contracts tests directory, relative to the git root - */ - basePath: string; - splits: { - /** - * The number of sub-splits to run across - */ - numOfSplits: number; - /** - * The directory of the tests to create sub-splits across, relative to the basePath - */ - dir: string; - /** - * An array of known slow tests, to better distribute across sub-splits - * - * Each string is a case-sensitive matcher that will match against any substring within the list of test file paths within the `dir` configuration. - * - * @example - * Given the dir `v0.8`, we get the following tests: ['v0.8/Foo1.test.ts','v0.8/bar.test.ts','v0.8/dev/eolpe/Foo.test.ts'] - * - * If we supply the following `slowTests` argument: ['Foo'] - * - * Then it'll match against both 'v0.8/Foo1.test.ts' and 'v0.8/dev/eolpe/Foo.test.ts'. - */ - slowTests?: string[]; - }[]; -} diff --git a/.github/actions/split-tests/test/__snapshots__/sieve.test.ts.snap b/.github/actions/split-tests/test/__snapshots__/sieve.test.ts.snap deleted file mode 100644 index d55bc175b8..0000000000 --- a/.github/actions/split-tests/test/__snapshots__/sieve.test.ts.snap +++ /dev/null @@ -1,99 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`sieveSlowTests works 1`] = ` -{ - "filteredTests": [], - "slowTests": [], -} -`; - -exports[`sieveSlowTests works 2`] = ` -{ - "filteredTests": [], - "slowTests": [], -} -`; - -exports[`sieveSlowTests works 3`] = ` -{ - "filteredTests": [ - "keepme", - ], - "slowTests": [], -} -`; - -exports[`sieveSlowTests works 4`] = ` -{ - "filteredTests": [ - "keepme", - ], - "slowTests": [], -} -`; - -exports[`sieveSlowTests works 5`] = ` -{ - "filteredTests": [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", - "bonk.test", - "bop.test", - "ouch.test.ts", - ], - "slowTests": [], -} -`; - -exports[`sieveSlowTests works 6`] = ` -{ - "filteredTests": [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", - "bonk.test", - "bop.test", - "ouch.test.ts", - ], - "slowTests": [], -} -`; - -exports[`sieveSlowTests works 7`] = ` -{ - "filteredTests": [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", - "bonk.test", - "bop.test", - ], - "slowTests": [ - "ouch.test.ts", - ], -} -`; - -exports[`sieveSlowTests works 8`] = ` -{ - "filteredTests": [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", - ], - "slowTests": [ - "bonk.test", - "bop.test", - "ouch.test.ts", - ], -} -`; diff --git a/.github/actions/split-tests/test/__snapshots__/splitter.test.ts.snap b/.github/actions/split-tests/test/__snapshots__/splitter.test.ts.snap deleted file mode 100644 index 70dfe70ec1..0000000000 --- a/.github/actions/split-tests/test/__snapshots__/splitter.test.ts.snap +++ /dev/null @@ -1,119 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`simpleSplit doesn't error on empty arrays 1`] = ` -[ - [], -] -`; - -exports[`simpleSplit doesn't error on empty arrays 2`] = ` -[ - [], - [], - [], - [], - [], -] -`; - -exports[`simpleSplit handles no slow test splitting 1`] = ` -[ - [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", - "bonk.test", - "bop.test", - "ouch.test.ts", - ], -] -`; - -exports[`simpleSplit handles no slow test splitting 2`] = ` -[ - [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - ], - [ - "nope.test", - "bonk.test", - "bop.test", - "ouch.test.ts", - ], -] -`; - -exports[`simpleSplit handles no slow test splitting 3`] = ` -[ - [ - "foo.test", - "bar.test", - "baz.test", - ], - [ - "yup.test", - "nope.test", - "bonk.test", - ], - [ - "bop.test", - "ouch.test.ts", - ], -] -`; - -exports[`simpleSplit handles slow test splitting 1`] = ` -[ - [ - "bonk.test", - "bop.test", - "ouch.test.ts", - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", - ], -] -`; - -exports[`simpleSplit handles slow test splitting 2`] = ` -[ - [ - "bonk.test", - "ouch.test.ts", - "foo.test", - "bar.test", - "baz.test", - ], - [ - "bop.test", - "yup.test", - "nope.test", - ], -] -`; - -exports[`simpleSplit handles slow test splitting 3`] = ` -[ - [ - "bonk.test", - "foo.test", - "bar.test", - ], - [ - "bop.test", - "baz.test", - "yup.test", - ], - [ - "ouch.test.ts", - "nope.test", - ], -] -`; diff --git a/.github/actions/split-tests/test/fixtures.mts b/.github/actions/split-tests/test/fixtures.mts deleted file mode 100644 index aa87ba4c35..0000000000 --- a/.github/actions/split-tests/test/fixtures.mts +++ /dev/null @@ -1,20 +0,0 @@ -export const testArr: string[] = [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", - "bonk.test", - "bop.test", - "ouch.test.ts", -]; - -export const testSievedArr: string[] = [ - "foo.test", - "bar.test", - "baz.test", - "yup.test", - "nope.test", -]; - -export const testSlowArr: string[] = ["bonk.test", "bop.test", "ouch.test.ts"]; diff --git a/.github/actions/split-tests/test/sieve.test.ts b/.github/actions/split-tests/test/sieve.test.ts deleted file mode 100644 index bc296a435f..0000000000 --- a/.github/actions/split-tests/test/sieve.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {sieveSlowTests} from "../src/sieve.mjs"; -import {testArr} from "./fixtures.mjs"; - -describe("sieveSlowTests", () => { - it("works", () => { - expect(sieveSlowTests([])).toMatchSnapshot(); - expect(sieveSlowTests([], [])).toMatchSnapshot(); - expect(sieveSlowTests(["keepme"], [])).toMatchSnapshot(); - expect(sieveSlowTests(["keepme"])).toMatchSnapshot(); - expect(sieveSlowTests(testArr, [])).toMatchSnapshot(); - expect(sieveSlowTests(testArr, ["noself"])).toMatchSnapshot(); - expect(sieveSlowTests(testArr, ["ouch.test.ts"])).toMatchSnapshot(); - expect(sieveSlowTests(testArr, ["bo", "ouch.test.ts"])).toMatchSnapshot(); - }); -}); diff --git a/.github/actions/split-tests/test/splitter.test.ts b/.github/actions/split-tests/test/splitter.test.ts deleted file mode 100644 index 85ae7726fe..0000000000 --- a/.github/actions/split-tests/test/splitter.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {simpleSplit} from "../src/splitter.mjs"; -import {testArr, testSievedArr, testSlowArr} from "./fixtures.mjs"; - -describe("simpleSplit", () => { - it("doesn't error on empty arrays", () => { - expect(simpleSplit([], [], 1)).toMatchSnapshot(); - expect(simpleSplit([], [], 5)).toMatchSnapshot(); - }); - - it("handles no slow test splitting", () => { - expect(simpleSplit(testArr, [], 1)).toMatchSnapshot(); - expect(simpleSplit(testArr, [], 2)).toMatchSnapshot(); - expect(simpleSplit(testArr, [], 3)).toMatchSnapshot(); - }); - - it("handles slow test splitting", () => { - expect(simpleSplit(testSievedArr, testSlowArr, 1)).toMatchSnapshot(); - expect(simpleSplit(testSievedArr, testSlowArr, 2)).toMatchSnapshot(); - expect(simpleSplit(testSievedArr, testSlowArr, 3)).toMatchSnapshot(); - }); -}); diff --git a/.github/actions/split-tests/tsconfig.json b/.github/actions/split-tests/tsconfig.json deleted file mode 100644 index 4b36d4a178..0000000000 --- a/.github/actions/split-tests/tsconfig.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "NodeNext" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "NodeNext" /* Specify how TypeScript looks up a file from a given module specifier. */, - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - "noEmit": true /* Disable emitting files from a compilation. */, - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - - /* Type Checking */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": false /* Skip type checking all .d.ts files. */ - }, - "include": ["src", "test"] -} diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index bfbca1c632..a7ced0f565 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -16,16 +16,12 @@ jobs: - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: - # Foundry is only used for Solidity v0.8 contracts, therefore we can ignore - # changes to older contracts. filters: | src: - 'contracts/src/v0.8/**/*' - '.github/workflows/solidity-foundry.yml' - 'contracts/foundry.toml' - 'contracts/gas-snapshots/*.gas-snapshot' - - 'contracts/foundry-lib/**/*' - - '.gitmodules' tests: strategy: diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 9b5058eda6..fb6ba6fef4 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -25,46 +25,17 @@ jobs: with: filters: | src: - - 'contracts/src/!(v0.8/(llo-feeds|keystone|ccip|functions|transmission)/**)/**/*' + - 'contracts/src/!(v0.8/(ccip|functions|keystone|l2ep|llo-feeds|transmission|vrf)/**)/**/*' - '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@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - 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] + hardhat-test: + needs: [changes] 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) }} + name: Solidity ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }} runs-on: ubuntu-latest steps: - name: Checkout the repo @@ -76,23 +47,20 @@ jobs: with: namespace: coverage - name: Run tests - env: - SPLIT: ${{ matrix.split.tests }} working-directory: contracts - run: pnpm test -- $SPLIT + run: pnpm test - name: Collect Metrics id: collect-gha-metrics uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 with: - id: solidity-splits + id: hardhat-test 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] + needs: [changes, hardhat-test] name: Solidity runs-on: ubuntu-latest if: always() diff --git a/contracts/.prettierignore b/contracts/.prettierignore index b2c6d61c22..7c3131db42 100644 --- a/contracts/.prettierignore +++ b/contracts/.prettierignore @@ -15,7 +15,6 @@ abi artifacts foundry-artifacts foundry-cache -foundry-lib cache node_modules solc diff --git a/contracts/ci.json b/contracts/ci.json deleted file mode 100644 index 668c85fd4d..0000000000 --- a/contracts/ci.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "solidity", - "basePath": "./contracts/test/", - "splits": [ - { - "dir": "v0.8", - "numOfSplits": 5, - "slowTests": [ - "CronUpkeepFactory", - "AutomationRegistry2_2", - "AutomationRegistry2_3" - ] - } - ] -} diff --git a/contracts/foundry.toml b/contracts/foundry.toml index f5922c4a57..08940b4e9f 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -7,7 +7,7 @@ src = 'src/v0.8' test = 'test/v0.8' out = 'foundry-artifacts' cache_path = 'foundry-cache' -libs = ['node_modules', 'foundry-lib'] +libs = ['node_modules'] bytecode_hash = "none" ffi = false From c3f6b704f1c510dbfb28b421ee3a8f63416b18c1 Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 27 Jun 2024 11:21:32 +0100 Subject: [PATCH 17/61] Allow flat interpolation (#13601) * Allow flat interpolation * Update common * Fix tests after rebase --- .changeset/tall-wombats-deliver.md | 5 + .../capabilities/remote/target/client_test.go | 8 +- .../remote/target/endtoend_test.go | 14 ++- .../target/request/client_request_test.go | 11 ++- .../target/request/server_request_test.go | 6 +- .../remote/trigger_subscriber_test.go | 15 +-- core/capabilities/remote/utils_test.go | 4 +- core/capabilities/streams/trigger_test.go | 5 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- core/services/workflows/engine.go | 17 +++- core/services/workflows/engine_test.go | 99 ++++++++++++++++++- core/services/workflows/models_test.go | 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 +- 19 files changed, 166 insertions(+), 46 deletions(-) create mode 100644 .changeset/tall-wombats-deliver.md diff --git a/.changeset/tall-wombats-deliver.md b/.changeset/tall-wombats-deliver.md new file mode 100644 index 0000000000..cb165b999a --- /dev/null +++ b/.changeset/tall-wombats-deliver.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Allow outputs to be passed directly to the inputs diff --git a/core/capabilities/remote/target/client_test.go b/core/capabilities/remote/target/client_test.go index 64b824d74d..aa4a645df9 100644 --- a/core/capabilities/remote/target/client_test.go +++ b/core/capabilities/remote/target/client_test.go @@ -33,9 +33,9 @@ func Test_Client_DonTopologies(t *testing.T) { responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) response := <-responseCh - responseValue, err := response.Value.Unwrap() + mp, err := response.Value.Unwrap() require.NoError(t, err) - assert.Equal(t, "aValue1", responseValue.(string)) + assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) } capability := &TestCapability{} @@ -64,9 +64,9 @@ func Test_Client_TransmissionSchedules(t *testing.T) { responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) response := <-responseCh - responseValue, err := response.Value.Unwrap() + mp, err := response.Value.Unwrap() require.NoError(t, err) - assert.Equal(t, "aValue1", responseValue.(string)) + assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) } capability := &TestCapability{} diff --git a/core/capabilities/remote/target/endtoend_test.go b/core/capabilities/remote/target/endtoend_test.go index d5305afeb3..f7cc9e04bf 100644 --- a/core/capabilities/remote/target/endtoend_test.go +++ b/core/capabilities/remote/target/endtoend_test.go @@ -74,9 +74,9 @@ func Test_RemoteTargetCapability_TransmissionSchedules(t *testing.T) { responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) response := <-responseCh - responseValue, err := response.Value.Unwrap() + mp, err := response.Value.Unwrap() require.NoError(t, err) - assert.Equal(t, "aValue1", responseValue.(string)) + assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) } transmissionSchedule, err := values.NewMap(map[string]any{ @@ -106,9 +106,9 @@ func Test_RemoteTargetCapability_DonTopologies(t *testing.T) { responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) response := <-responseCh - responseValue, err := response.Value.Unwrap() + mp, err := response.Value.Unwrap() require.NoError(t, err) - assert.Equal(t, "aValue1", responseValue.(string)) + assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) } transmissionSchedule, err := values.NewMap(map[string]any{ @@ -409,8 +409,12 @@ func (t TestCapability) Execute(ctx context.Context, request commoncap.Capabilit value := request.Inputs.Underlying["executeValue1"] + response, err := values.NewMap(map[string]any{"response": value}) + if err != nil { + return nil, err + } ch <- commoncap.CapabilityResponse{ - Value: value, + Value: response, } return ch, nil diff --git a/core/capabilities/remote/target/request/client_request_test.go b/core/capabilities/remote/target/request/client_request_test.go index a053623cd2..52e324a654 100644 --- a/core/capabilities/remote/target/request/client_request_test.go +++ b/core/capabilities/remote/target/request/client_request_test.go @@ -75,8 +75,10 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { Config: transmissionSchedule, } + m, err := values.NewMap(map[string]any{"response": "response1"}) + require.NoError(t, err) capabilityResponse := commoncap.CapabilityResponse{ - Value: values.NewString("response1"), + Value: m, Err: nil, } @@ -106,8 +108,10 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { require.NoError(t, err) + nm, err := values.NewMap(map[string]any{"response": "response2"}) + require.NoError(t, err) capabilityResponse2 := commoncap.CapabilityResponse{ - Value: values.NewString("response2"), + Value: nm, Err: nil, } @@ -297,8 +301,9 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { require.NoError(t, err) response := <-request.ResponseChan() + resp := response.Value.Underlying["response"] - assert.Equal(t, response.Value, values.NewString("response1")) + assert.Equal(t, resp, values.NewString("response1")) }) } diff --git a/core/capabilities/remote/target/request/server_request_test.go b/core/capabilities/remote/target/request/server_request_test.go index fe3fdd713b..d5ed471c95 100644 --- a/core/capabilities/remote/target/request/server_request_test.go +++ b/core/capabilities/remote/target/request/server_request_test.go @@ -225,8 +225,12 @@ func (t TestCapability) Execute(ctx context.Context, request commoncap.Capabilit value := request.Inputs.Underlying["executeValue1"] + response, err := values.NewMap(map[string]any{"response": value}) + if err != nil { + return nil, err + } ch <- commoncap.CapabilityResponse{ - Value: value, + Value: response, } return ch, nil diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index 3b819f9f3c..4750430951 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -18,11 +18,14 @@ import ( ) const ( - peerID1 = "12D3KooWF3dVeJ6YoT5HFnYhmwQWWMoEwVFzJQ5kKCMX3ZityxMC" - peerID2 = "12D3KooWQsmok6aD8PZqt3RnJhQRrNzKHLficq7zYFRp7kZ1hHP8" - workflowID1 = "workflowID1" - triggerEvent1 = "triggerEvent1" - triggerEvent2 = "triggerEvent2" + peerID1 = "12D3KooWF3dVeJ6YoT5HFnYhmwQWWMoEwVFzJQ5kKCMX3ZityxMC" + peerID2 = "12D3KooWQsmok6aD8PZqt3RnJhQRrNzKHLficq7zYFRp7kZ1hHP8" + workflowID1 = "workflowID1" +) + +var ( + triggerEvent1 = map[string]any{"event": "triggerEvent1"} + triggerEvent2 = map[string]any{"event": "triggerEvent2"} ) func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { @@ -77,7 +80,7 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { <-awaitRegistrationMessageCh // receive trigger event - triggerEventValue, err := values.Wrap(triggerEvent1) + triggerEventValue, err := values.NewMap(triggerEvent1) require.NoError(t, err) capResponse := commoncap.CapabilityResponse{ Value: triggerEventValue, diff --git a/core/capabilities/remote/utils_test.go b/core/capabilities/remote/utils_test.go index b5f97af99e..0dd91696fb 100644 --- a/core/capabilities/remote/utils_test.go +++ b/core/capabilities/remote/utils_test.go @@ -89,7 +89,7 @@ func TestToPeerID(t *testing.T) { } func TestDefaultModeAggregator_Aggregate(t *testing.T) { - val, err := values.Wrap(triggerEvent1) + val, err := values.NewMap(triggerEvent1) require.NoError(t, err) capResponse1 := commoncap.CapabilityResponse{ Value: val, @@ -98,7 +98,7 @@ func TestDefaultModeAggregator_Aggregate(t *testing.T) { marshaled1, err := pb.MarshalCapabilityResponse(capResponse1) require.NoError(t, err) - val2, err := values.Wrap(triggerEvent2) + val2, err := values.NewMap(triggerEvent2) require.NoError(t, err) capResponse2 := commoncap.CapabilityResponse{ Value: val2, diff --git a/core/capabilities/streams/trigger_test.go b/core/capabilities/streams/trigger_test.go index b8106e9212..8f9450d2c9 100644 --- a/core/capabilities/streams/trigger_test.go +++ b/core/capabilities/streams/trigger_test.go @@ -194,7 +194,10 @@ func newTriggerEvent(t *testing.T, reportList []datastreams.FeedReport, triggerE eventVal, err := values.Wrap(triggerEvent) require.NoError(t, err) - marshaled, err := pb.MarshalCapabilityResponse(capabilities.CapabilityResponse{Value: eventVal}) + marshaled, err := pb.MarshalCapabilityResponse( + capabilities.CapabilityResponse{ + Value: eventVal.(*values.Map), + }) require.NoError(t, err) msg := &remotetypes.MessageBody{ Sender: sender[:], diff --git a/core/scripts/go.mod b/core/scripts/go.mod index c40e4cd41f..f0edb3503c 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 36e6a3d784..e2002fcf8b 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1212,8 +1212,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.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index a2cb3f72e3..362fb7fb09 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -668,18 +668,25 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, return nil, nil, err } - i, err := findAndInterpolateAllKeys(step.Inputs, msg.state) + var inputs any + if step.Inputs.OutputRef != "" { + inputs = step.Inputs.OutputRef + } else { + inputs = step.Inputs.Mapping + } + + i, err := findAndInterpolateAllKeys(inputs, msg.state) if err != nil { return nil, nil, err } - inputs, err := values.NewMap(i.(map[string]any)) + inputsMap, err := values.NewMap(i.(map[string]any)) if err != nil { return nil, nil, err } tr := capabilities.CapabilityRequest{ - Inputs: inputs, + Inputs: inputsMap, Config: step.config, Metadata: capabilities.RequestMetadata{ WorkflowID: msg.state.WorkflowID, @@ -692,10 +699,10 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, output, err := executeSyncAndUnwrapSingleValue(ctx, step.capability, tr) if err != nil { - return inputs, nil, err + return inputsMap, nil, err } - return inputs, output, err + return inputsMap, output, err } func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, triggerIdx int) error { diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 50ee0c36eb..6146d1e13d 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -506,8 +506,9 @@ targets: ` ) -func mockAction() (*mockCapability, values.Value) { - outputs := values.NewString("output") +func mockAction(t *testing.T) (*mockCapability, values.Value) { + outputs, err := values.NewMap(map[string]any{"output": "foo"}) + require.NoError(t, err) return newMockCapability( capabilities.MustNewCapabilityInfo( "read_chain_action@1.0.0", @@ -533,7 +534,7 @@ func TestEngine_MultiStepDependencies(t *testing.T) { require.NoError(t, reg.Add(ctx, mockConsensus())) require.NoError(t, reg.Add(ctx, mockTarget())) - action, out := mockAction() + action, out := mockAction(t) require.NoError(t, reg.Add(ctx, action)) eng, hooks := newTestEngine(t, reg, multiStepWorkflow) @@ -580,7 +581,7 @@ func TestEngine_ResumesPendingExecutions(t *testing.T) { require.NoError(t, reg.Add(ctx, mockConsensus())) require.NoError(t, reg.Add(ctx, mockTarget())) - action, _ := mockAction() + action, _ := mockAction(t) require.NoError(t, reg.Add(ctx, action)) dbstore := newTestDBStore(t, clockwork.NewFakeClock()) ec := &store.WorkflowExecution{ @@ -632,7 +633,7 @@ func TestEngine_TimesOutOldExecutions(t *testing.T) { require.NoError(t, reg.Add(ctx, mockConsensus())) require.NoError(t, reg.Add(ctx, mockTarget())) - action, _ := mockAction() + action, _ := mockAction(t) require.NoError(t, reg.Add(ctx, action)) clock := clockwork.NewFakeClock() @@ -814,6 +815,94 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { assert.Equal(t, node, eng.localNode) } +const passthroughInterpolationWorkflow = ` +triggers: + - id: "mercury-trigger@1.0.0" + config: + feedIds: + - "0x1111111111111111111100000000000000000000000000000000000000000000" + - "0x2222222222222222222200000000000000000000000000000000000000000000" + - "0x3333333333333333333300000000000000000000000000000000000000000000" + +consensus: + - id: "offchain_reporting@1.0.0" + ref: "evm_median" + inputs: + observations: + - "$(trigger.outputs)" + config: + aggregation_method: "data_feeds_2_0" + aggregation_config: + "0x1111111111111111111100000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x2222222222222222222200000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + "0x3333333333333333333300000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: 3600 + encoder: "EVM" + encoder_config: + abi: "mercury_reports bytes[]" + +targets: + - id: "write_ethereum-testnet-sepolia@1.0.0" + inputs: "$(evm_median.outputs)" + config: + address: "0x54e220867af6683aE6DcBF535B4f952cB5116510" + params: ["$(report)"] + abi: "receive(report bytes)" +` + +func TestEngine_PassthroughInterpolation(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_ethereum-testnet-sepolia@1.0.0" + target := newMockCapability( + capabilities.MustNewCapabilityInfo( + writeID, + capabilities.CapabilityTypeTarget, + "a write capability targeting ethereum sepolia testnet", + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + return capabilities.CapabilityResponse{ + Value: req.Inputs, + }, nil + }, + ) + require.NoError(t, reg.Add(ctx, target)) + + eng, testHooks := newTestEngine( + t, + reg, + passthroughInterpolationWorkflow, + ) + + 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) + + // There is passthrough interpolation between the consensus and target steps, + // so the input of one should be the output of the other, exactly. + gotInputs, err := values.Unwrap(state.Steps[writeID].Inputs) + require.NoError(t, err) + + gotOutputs, err := values.Unwrap(state.Steps["evm_median"].Outputs.Value) + require.NoError(t, err) + assert.Equal(t, gotInputs, gotOutputs) +} + func TestEngine_Error(t *testing.T) { err := errors.New("some error") tests := []struct { diff --git a/core/services/workflows/models_test.go b/core/services/workflows/models_test.go index 4b4747c486..a28aeb9df0 100644 --- a/core/services/workflows/models_test.go +++ b/core/services/workflows/models_test.go @@ -214,7 +214,7 @@ targets: }, }, { - name: "non-trigger step with no dependent refs", + name: "invalid refs", yaml: ` triggers: - id: "a-trigger@1.0.0" @@ -241,7 +241,7 @@ targets: inputs: consensus_output: $(a-consensus.outputs) `, - errMsg: "all non-trigger steps must have a dependent ref", + errMsg: "invalid refs", }, { name: "duplicate edge declarations", diff --git a/go.mod b/go.mod index accb1d390a..0086ef3ec0 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 diff --git a/go.sum b/go.sum index e541c80b44..7ab9fe024e 100644 --- a/go.sum +++ b/go.sum @@ -1171,8 +1171,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.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index d309944701..f33080c3f8 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -28,7 +28,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 github.com/smartcontractkit/chainlink-testing-framework v1.31.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b301068a55..780bab37c7 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1513,8 +1513,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.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 5dba281f1e..fca1936781 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.1.7-0.20240625074419-c278d083facf + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 github.com/smartcontractkit/chainlink-testing-framework v1.31.5 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 075883054c..4eabc24cdd 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1503,8 +1503,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.1.7-0.20240625074419-c278d083facf h1:d9AS/K8RSVG64USb20N/U7RaPOsYPcmuLGJq7iE+caM= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625074419-c278d083facf/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From 2a1b0c4eecb9cc23a364d62a080cc9ae0d08c518 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Thu, 27 Jun 2024 15:08:19 +0200 Subject: [PATCH 18/61] update OCR test names in on-demand workflow (#13708) --- .github/workflows/on-demand-ocr-soak-test.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index ae24786b43..c4415ac85d 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -8,7 +8,10 @@ on: default: TestOCRSoak type: choice options: - - TestOCRSoak + - TestOCRv1Soak + - TestOCRv2Soak + - TestForwarderOCRv1Soak + - TestForwarderOCRv2Soak - TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled - TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled - TestOCRSoak_GasSpike @@ -18,7 +21,7 @@ on: base64Config: description: base64-ed config required: true - type: string + type: string slackMemberID: description: Slack Member ID (Not your @) required: true @@ -78,7 +81,7 @@ jobs: echo "### chainlink-tests image tag for this test run :ship:" >>$GITHUB_STEP_SUMMARY echo "\`${GITHUB_SHA}\`" >>$GITHUB_STEP_SUMMARY echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY - echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY + echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Build Image uses: ./.github/actions/build-test-image with: From 7e5dc96e04032db9c8fa6d89ceb51b8bdd889293 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Thu, 27 Jun 2024 10:01:09 -0500 Subject: [PATCH 19/61] bump operator-ui for CronSpec.EVMChainID (#13701) --- core/web/assets/index.html | 2 +- core/web/assets/index.html.gz | Bin 419 -> 419 bytes ...27a75d.js => main.6f07a88cfc748f57e21d.js} | 2 +- ....js.gz => main.6f07a88cfc748f57e21d.js.gz} | Bin 1196036 -> 1196025 bytes operator_ui/TAG | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename core/web/assets/{main.026013f04da39527a75d.js => main.6f07a88cfc748f57e21d.js} (90%) rename core/web/assets/{main.026013f04da39527a75d.js.gz => main.6f07a88cfc748f57e21d.js.gz} (94%) diff --git a/core/web/assets/index.html b/core/web/assets/index.html index eb81b6d994..e50dfc0709 100644 --- a/core/web/assets/index.html +++ b/core/web/assets/index.html @@ -1 +1 @@ -Operator UIChainlink
\ No newline at end of file +Operator UIChainlink
\ No newline at end of file diff --git a/core/web/assets/index.html.gz b/core/web/assets/index.html.gz index 009ac43692aa81d401d9ba0180357ae5364707f9..f32bc10dbc313c6e49188a920a5f9bb14ffd54ff 100644 GIT binary patch delta 404 zcmV;F0c-xF1ET|w8Gn-|wF%PZ5GbTj3T<=faV*VxreKZqjFS*xL7 z@AM!t);nWrf+DkN0WS@uJ-sv;#rOdz&y0pV-@`%Jc}`=&THjtj^js3i+`wY*hN&I yV1jQaTVYiWS;;_E!8kV7TncTVNl|dRFw5){XzHvv;SJ5Qs=onc?@b`U0ssJR_Qfjz delta 404 zcmV;F0c-xF1ET|w8GmEPO&g@mAy7!66q@GH<5-&YPAh2^X}pR5eOcQv6bhvm2|bwa z%{+~L6WGgPL^Vi?ojsojp|c4Elpml}6sMoQe_DRf<}7DO==4PRJaQ4OJZHfyPCrwS z!3CVi&!d1f@^`40BN&T|?I*7|mJ-*ZVIa|1`4Kao9W zsm+dg7ZFCPjpt;1t#>^niU;?Nw=8_SZrjCm+b%Y3tIv(fAz~d6|BF0N^@{!if`uTy zd+?m=zp$o=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n */ var r=n(48764),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function o(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=o),o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if("number"==typeof e)throw TypeError("Argument must not be a number");return i(e,t,n)},o.alloc=function(e,t,n){if("number"!=typeof e)throw TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},o.allocUnsafe=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return i(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return r.SlowBuffer(e)}},93379(e,t,n){"use strict";var r,i,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=(i={},function(e){if(void 0===i[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(n){t=null}i[e]=t}return i[e]}),s=[];function u(e){for(var t=-1,n=0;nOW});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(39814),h=n(5977),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(37703),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e6(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e5(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n9.kG)(!!n,32),n}var rp=n(10542),rb=n(53712),rm=n(21436),rg=Object.prototype.hasOwnProperty;function rv(e,t){return void 0===t&&(t=Object.create(null)),ry(rh(t.client),e).useQuery(t)}function ry(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new rw(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var rw=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rp.J)({loading:!0,data:void 0,error:void 0,networkStatus:ru.I.loading}),this.skipStandbyResult=(0,rp.J)({loading:!1,data:void 0,error:void 0,networkStatus:ru.I.ready}),this.toQueryResultCache=new(n7.mr?WeakMap:Map),rd(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n9.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,ro.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rt((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ri.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rg.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ri.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:ru.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ri.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rb.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ra.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,t0._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n9.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rm.O)(e.errors)?new rs.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,t0._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,t0.pi)((0,t0.pi)((0,t0.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rm.O)(e.errors)&&(t.error=new rs.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:ru.I.refetch}),this.observable.refetch())},e}();function r_(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return rv(iH,e)},iz=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=i$({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(iR,null):o?l.createElement(iD,{error:o}):i?l.createElement(iI,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iG=n(67932),iW=n(8126),iK="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iV(e){if(iq())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iq(){return("undefined"==typeof Intl?"undefined":iK(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iZ="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iX=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iZ(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iZ(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i1=iQ;var i0=new i1;function i2(e,t){if(!iq())return function(e){return e.toString()};var n=i4(e),r=JSON.stringify(t),i=i0.get(String(n),r)||i0.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i3={};function i4(e){var t=e.toString();return i3[t]?i3[t]:i3[t]=iV(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i5(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i9(e)}function i9(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var i7=n(54087),ae=n.n(i7);function at(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)aa(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=ae()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){ae().cancel(this.scheduledTick)}};function ai(e){var t=an(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function aa(e,t){ai(e),as(t,e),ao(t,e)}function ao(e,t){var n=au(e,t);e.splice(n,0,t)}function as(e,t){var n=e.indexOf(t);e.splice(n,1)}function au(e,t){var n=t.nextUpdateTime;return at(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var ac=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),al=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(ac).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),af=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ap(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ah(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iW.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iW.Z(y)},[y]);t=(0,l.useMemo)(function(){return i5(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ad(u,2),l=c[0],f=c[1];return f=o?ag:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ad(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ad(M,2),A=O[0],L=O[1],C=ad((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ar.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ad(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i2(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,af({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,af({},f,{verboseDate:I?R:void 0}),j):j}ap.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:al,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ap.defaultProps={locales:[],component:av,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ap=l.memo(ap);let ab=ap;var am,ag=31536e9;function av(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ah(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",af({},a,{dateTime:o,title:r?n:void 0}),i)}av.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var ay=n(30381),aw=n.n(ay),a_=n(31657);function aE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function aS(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new rs.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ri.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ri.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,t0.pi)({reset:c},a)]}var os=n(59067),ou=n(28428),oc=n(11186),ol=n(78513);function of(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var od=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:of({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},oh=(0,b.withStyles)(od)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ii.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),op=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},ob=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},om=(0,b.withStyles)(od)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function og(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sq=sV;function sZ(e,t){var n=this.__data__,r=sH(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sX=sZ;function sJ(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cC}let cD=cI;var cN="[object Arguments]",cP="[object Array]",cR="[object Boolean]",cj="[object Date]",cF="[object Error]",cY="[object Function]",cB="[object Map]",cU="[object Number]",cH="[object Object]",c$="[object RegExp]",cz="[object Set]",cG="[object String]",cW="[object WeakMap]",cK="[object ArrayBuffer]",cV="[object DataView]",cq="[object Float64Array]",cZ="[object Int8Array]",cX="[object Int16Array]",cJ="[object Int32Array]",cQ="[object Uint8Array]",c1="[object Uint8ClampedArray]",c0="[object Uint16Array]",c2="[object Uint32Array]",c3={};function c4(e){return eD(e)&&cD(e.length)&&!!c3[eC(e)]}c3["[object Float32Array]"]=c3[cq]=c3[cZ]=c3[cX]=c3[cJ]=c3[cQ]=c3[c1]=c3[c0]=c3[c2]=!0,c3[cN]=c3[cP]=c3[cK]=c3[cR]=c3[cV]=c3[cj]=c3[cF]=c3[cY]=c3[cB]=c3[cU]=c3[cH]=c3[c$]=c3[cz]=c3[cG]=c3[cW]=!1;let c6=c4;function c5(e){return function(t){return e(t)}}let c8=c5;var c9=n(79730),c7=c9.Z&&c9.Z.isTypedArray,le=c7?c8(c7):c6;let lt=le;var ln=Object.prototype.hasOwnProperty;function lr(e,t){var n=cx(e),r=!n&&cS(e),i=!n&&!r&&(0,cT.Z)(e),a=!n&&!r&&!i&<(e),o=n||r||i||a,s=o?cb(e.length,String):[],u=s.length;for(var c in e)(t||ln.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cL(c,u)))&&s.push(c);return s}let li=lr;var la=Object.prototype;function lo(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||la)}let ls=lo;var lu=sT(Object.keys,Object);let lc=lu;var ll=Object.prototype.hasOwnProperty;function lf(e){if(!ls(e))return lc(e);var t=[];for(var n in Object(e))ll.call(e,n)&&"constructor"!=n&&t.push(n);return t}let ld=lf;function lh(e){return null!=e&&cD(e.length)&&!ur(e)}let lp=lh;function lb(e){return lp(e)?li(e):ld(e)}let lm=lb;function lg(e,t){return e&&ch(t,lm(t),e)}let lv=lg;function ly(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let lw=ly;var l_=Object.prototype.hasOwnProperty;function lE(e){if(!ed(e))return lw(e);var t=ls(e),n=[];for(var r in e)"constructor"==r&&(t||!l_.call(e,r))||n.push(r);return n}let lS=lE;function lk(e){return lp(e)?li(e,!0):lS(e)}let lx=lk;function lT(e,t){return e&&ch(t,lx(t),e)}let lM=lT;var lO=n(42896);function lA(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function hu(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var hc=function(e){return Array.isArray(e)&&0===e.length},hl=function(e){return"function"==typeof e},hf=function(e){return null!==e&&"object"==typeof e},hd=function(e){return String(Math.floor(Number(e)))===e},hh=function(e){return"[object String]"===Object.prototype.toString.call(e)},hp=function(e){return 0===l.Children.count(e)},hb=function(e){return hf(e)&&hl(e.then)};function hm(e,t,n,r){void 0===r&&(r=0);for(var i=d8(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hv(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,hm(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=hg(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sk.all([t,n,r],{arrayMerge:hL})})},[h.validate,h.validationSchema,T,S,k]),O=hN(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),sd()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&sd()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hb(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!sd()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hS,E({type:"SET_ERRORS",payload:h.initialErrors||hS}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hk,E({type:"SET_TOUCHED",payload:h.initialTouched||hk}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hN(function(e){if(y.current[e]&&hl(y.current[e].validate)){var t=hm(_.values,e),n=y.current[e].validate(t);return hb(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hN(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hN(function(e,t){var r=hl(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hN(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(hg(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hh(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?hI(hm(_.values,r),l,c):d?hC(f):c}r&&j(r,i)},[j,_.values]),Y=hN(function(e){if(hh(e))return function(t){return F(t,e)};F(e)}),B=hN(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hN(function(e){if(hh(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){hl(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hN(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hN(function(){return f(_.values,V)}),Z=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:hm(_.values,e),error:hm(_.errors,e),touched:!!hm(_.touched,e),initialValue:hm(p.current,e),initialTouched:!!hm(m.current,e),initialError:hm(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=hf(e),n=t?e.name:e,r=hm(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!sd()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&hl(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return ha({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hT(e){var t=hx(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(hw,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?hl(r)?r(t):hp(r)?null:l.Children.only(r):null)}function hM(e){var t={};if(e.inner){if(0===e.inner.length)return hg(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;hm(t,o.path)||(t=hg(t,o.path,o.message))}}return t}function hO(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hA(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hA(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sR(e)?hA(e):""!==e?e:void 0}):sR(e[r])?t[r]=hA(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hL(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sk(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sk(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hC(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function hI(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hD="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hN(e){var t=(0,l.useRef)(e);return hD(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(ha({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=hg(n.values,a,e(hm(n.values,a))),u=r?i(hm(n.errors,a)):void 0,c=t?o(hm(n.touched,a)):void 0;return hc(u)&&(u=void 0),hc(c)&&(c=void 0),ha({},n,{values:s,errors:r?hg(n.errors,a,u):n.errors,touched:t?hg(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hU(t),[hi(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hF(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hj(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hY(n,e,t)},function(t){return hY(t,e,null)},function(t){return hY(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hB(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(hu(n)),n.pop=n.pop.bind(hu(n)),n}ho(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!sd()(hm(e.formik.values,e.name),hm(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hU(n):[];return t||(t=r[e]),hl(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=hs(t.formik,["validate","validationSchema"]),s=ha({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hp(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var hH=n(24802),h$=n(71209),hz=n(91750),hG=n(11970),hW=n(4689),hK=n(67598),hV=function(){return(hV=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hZ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hq(e,["disabled","field","form","onBlur","helperText"]),d=hm(u,i.name),h=hm(s,i.name)&&!!d;return hV(hV({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hX(e){var t=e.children,n=hq(e,["children"]);return(0,l.createElement)(iw.Z,hV({},hZ(n)),t)}function hJ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hQ(e){return(0,l.createElement)(hH.Z,hV({},hJ(e)))}function h1(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hq(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function h0(e){return(0,l.createElement)(h$.Z,hV({},h1(e)))}function h2(e){var t=e.Label,n=hq(e,["Label"]);return(0,l.createElement)(hz.Z,hV({control:(0,l.createElement)(h$.Z,hV({},h1(n)))},t))}function h3(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h4(e){return(0,l.createElement)(hG.default,hV({},h3(e)))}function h6(e){var t=e.field,n=t.onBlur,r=hq(t,["onBlur"]),i=(e.form,e.onBlur),a=hq(e,["field","form","onBlur"]);return hV(hV({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function h5(e){return(0,l.createElement)(hW.Z,hV({},h6(e)))}function h8(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h9(e){return(0,l.createElement)(hK.default,hV({},h8(e)))}hX.displayName="FormikMaterialUITextField",hQ.displayName="FormikMaterialUISwitch",h0.displayName="FormikMaterialUICheckbox",h2.displayName="FormikMaterialUICheckboxWithLabel",h4.displayName="FormikMaterialUISelect",h5.displayName="FormikMaterialUIRadioGroup",h9.displayName="FormikMaterialUIInputBase";try{a=Map}catch(h7){}try{o=Set}catch(pe){}function pt(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(pn);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:pt(e[i],t,n)}return r}return e}function pn(e){return pt(e,[],[])}let pr=Object.prototype.toString,pi=Error.prototype.toString,pa=RegExp.prototype.toString,po="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",ps=/^Symbol\((.*)\)(.*)$/;function pu(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function pc(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return pu(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return po.call(e).replace(ps,"Symbol($1)");let r=pr.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+pi.call(e)+"]":"RegExp"===r?pa.call(e):null}function pl(e,t){let n=pc(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=pc(this[e],t);return null!==r?r:n},2)}let pf={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${pl(n,!0)}\``+(i?` (cast from the value \`${pl(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},pd={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},ph={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pp={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pb={isValue:"${path} field must be ${value}"},pm={noUnknown:"${path} field has unspecified keys: ${unknown}"},pg={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pf,string:pd,number:ph,date:pp,object:pm,array:pg,boolean:pb});var pv=n(18721),py=n.n(pv);let pw=e=>e&&e.__isYupSchema__;class p_{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!py()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!pw(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pE=p_;function pS(e){return null==e?[]:[].concat(e)}function pk(){return(pk=Object.assign||function(e){for(var t=1;tpl(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pS(e).forEach(e=>{pT.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pT)}}let pM=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pO(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pM(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pT(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function pR(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pP(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pD.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=pL()(pN({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pT(pT.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pN({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pT.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pT.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pD.prototype.__isYupRef=!0;let pj=e=>e.substr(0,e.length-1).substr(1);function pF(e,t,n,r=n){let i,a,o;return t?((0,pC.forEach)(t,(s,u,c)=>{let l=u?pj(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pY{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pD.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pD.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pY;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pB(){return(pB=Object.assign||function(e){for(var t=1;t{this.typeError(pf.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pB({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pB({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=pn(pB({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pB({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pB({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=pl(e),a=pl(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". attempted value: ${i} -`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pB({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pO({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pO({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pB({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pB({},t,{value:e}))._validate(e,pB({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pT.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pT.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pn(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pf.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pf.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pf.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pR(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pS(e).map(e=>new pD(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pE(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pR({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pf.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pR({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pf.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pR({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pH of(pU.prototype.__isYupSchema__=!0,["validate","validateSync"]))pU.prototype[`${pH}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pF(this,e,t,n.context);return a[pH](r&&r[i],pB({},n,{parent:r,path:e}))};for(let p$ of["equals","is"])pU.prototype[p$]=pU.prototype.oneOf;for(let pz of["not","nope"])pU.prototype[pz]=pU.prototype.notOneOf;pU.prototype.optional=pU.prototype.notRequired;let pG=pU;function pW(){return new pG}pW.prototype=pG.prototype;let pK=e=>null==e;function pV(){return new pq}class pq extends pU{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pK(e)||!0===e})}isFalse(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pK(e)||!1===e})}}pV.prototype=pq.prototype;let pZ=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pX=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pJ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pQ=e=>pK(e)||e===e.trim(),p1=({}).toString();function p0(){return new p2}class p2 extends pU{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p1?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pd.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t=pd.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t=pd.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pd.matches,params:{regex:e},test:t=>pK(t)||""===t&&n||-1!==t.search(e)})}email(e=pd.email){return this.matches(pZ,{name:"email",message:e,excludeEmptyString:!0})}url(e=pd.url){return this.matches(pX,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pd.uuid){return this.matches(pJ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pd.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pQ})}lowercase(e=pd.lowercase){return this.transform(e=>pK(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toLowerCase()})}uppercase(e=pd.uppercase){return this.transform(e=>pK(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toUpperCase()})}}p0.prototype=p2.prototype;let p3=e=>e!=+e;function p4(){return new p6}class p6 extends pU{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p3(e)}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t>=this.resolve(e)}})}max(e,t=ph.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t<=this.resolve(e)}})}lessThan(e,t=ph.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pK(t)||tthis.resolve(e)}})}positive(e=ph.positive){return this.moreThan(0,e)}negative(e=ph.negative){return this.lessThan(0,e)}integer(e=ph.integer){return this.test({name:"integer",message:e,test:e=>pK(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pK(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pK(t)?t:Math[e](t))}}p4.prototype=p6.prototype;var p5=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p5.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p9=new Date(""),p7=e=>"[object Date]"===Object.prototype.toString.call(e);function be(){return new bt}class bt extends pU{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p9:new Date(e))})})}_typeCheck(e){return p7(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pD.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pp.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pK(e)||e>=this.resolve(n)}})}max(e,t=pp.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pK(e)||e<=this.resolve(n)}})}}bt.INVALID_DATE=p9,be.prototype=bt.prototype,be.INVALID_DATE=p9;var bn=n(11865),br=n.n(bn),bi=n(68929),ba=n.n(bi),bo=n(67523),bs=n.n(bo),bu=n(94633),bc=n.n(bu);function bl(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pC.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(py()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pD.isRef(o)&&o.isSibling?i(o.path,a):pw(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bc().array(r,n).reverse()}function bf(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bd(e){return(t,n)=>bf(e,t)-bf(e,n)}function bh(){return(bh=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bb(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bm=bd([]);class bg extends pU{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bm,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bp(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bh({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=py()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pT.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bp(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bh({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pO({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bh({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pU&&i instanceof pU&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bd(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bl(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pC.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return py()(i,e)&&(a=bh({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pm.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bb(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pm.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bs()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(ba())}snakeCase(){return this.transformKeys(br())}constantCase(){return this.transformKeys(e=>br()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pL()(this.fields,e=>e.describe()),e}}function bv(e){return new bg(e)}function by(){return(by=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,by({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pT.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pO({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pw(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pl(e));return t.innerType=e,t}length(e,t=pg.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pg.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pg.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bw.prototype=b_.prototype;var bE=bv().shape({name:p0().required("Required"),url:p0().required("Required")}),bS=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hT,{initialValues:t,validationSchema:bE,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hR,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bk=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Bridge",action:l.createElement(aA.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aW.Z,null,l.createElement(bS,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},mc=n(76023);function ml(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mB(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mZ={};function mX(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mZ[t]||(mZ[t]=mq(e)),mZ[t]}function mJ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mX(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mK({},e,n[t])},t)}function mQ(e){return e.join(" ")}function m1(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m0({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m0(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m1(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mK({},s,{className:mQ(m)||void 0,style:mJ(s.className,Object.assign({},s.style,i),n)})}else d=mK({},s,{className:mQ(s.className)});var g=h(t.children);return l.createElement(c,(0,mV.Z)({key:o},d),g)}}let m2=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m3=/\n/g;function m4(e){return e.match(m3)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m5(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m9(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function m7(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mK({},i,"function"==typeof e?e(t):e)}function ge(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=m7(r,n,i);t.unshift(m9(n,h))}return f&l&&(d.style=mK({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gt(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return ge({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=m7(s,t,o);e.unshift(m9(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m4(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(ge({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=ge({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gu=n(98695),gc=n.n(gu);let gl=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gf=go(gc(),gs);gf.supportedLanguages=gl;let gd=gf;var gh=n(64566);function gp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gb(){var e=gp(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gb=function(){return e},e}var gm=n0(gb()),gg=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gv=function(){return l.createElement(gg,null,"...")},gy=function(e){var t=e.children;return l.createElement(gg,null,t)},gw=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gy,null,i);if(t)return l.createElement(gv,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mP.Z,{defaultExpanded:o},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},a),l.createElement(mj.Z,{style:s},l.createElement(gd,{language:"toml",style:gs},n))))},g_=function(){var e=rv(gm,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gw,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gE=n(34823),gS=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gk=(0,b.withStyles)(gS)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gE.N,A.wU);return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gx=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(g_,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mN,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mE,null))))))},gT=function(){return l.createElement(gx,null)},gM=function(){return l.createElement(gT,null)},gO=n(44431),gA=1e18,gL=function(e){return new gO.BigNumber(e).dividedBy(gA).toFixed(8)},gC=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sl.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aW.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(op,{title:"Address"}),l.createElement(ob,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"Native Token Balance"}),l.createElement(ob,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"LINK Balance"}),l.createElement(ob,{value:e.linkBalance?gL(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gB.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(aA.Z,{href:"/runs",component:tz},"View More"))))))});function vt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vn(){var e=vt(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vn=function(){return e},e}var vr=5,vi=n0(vn(),g9),va=function(){var e=rv(vi,{variables:{offset:0,limit:vr},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(ve,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vr})},vo=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vs=(0,b.withStyles)(vo)(function(e){var t=e.classes,n=(0,A.v9)(gE.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vu=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vc=(0,b.withStyles)(vu)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function vl(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vf(){var e=vl(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vf=function(){return e},e}var vd=n0(vf()),vh=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vp=(0,b.withStyles)(vh)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gU,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vc,{job:e,key:t})}))))});function vb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vm(){var e=vb(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vm=function(){return e},e}var vg=5,vv=n0(vm(),vd),vy=function(){var e=rv(vv,{variables:{offset:0,limit:vg},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vp,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vw=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(va,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gY,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vy,null))))),l.createElement(vs,null))},v_=function(){return l.createElement(vw,null)},vE=function(){return l.createElement(v_,null)},vS=n(87239),vk=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vx=n(5022),vT=n(78718),vM=n.n(vT);function vO(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yh(t,e.status))},e.status.toLowerCase())))})))}),yb=n(16839),ym=n.n(yb);function yg(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=ym().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yv=n(94164),yy=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yw=n(73343),y_=n(3379),yE=n.n(y_);function yS(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yv.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yw.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yy,{data:e}))}))};function yL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyY&&l.createElement("div",{className:t.runDetails},l.createElement(aA.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yF,{observationSource:n.observationSource})))});function yH(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vx.parse(e),!0}catch(t){return!1}})}),wW=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hT,{initialValues:t,validationSchema:wG,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hR,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wK=n(50109),wV="persistSpec";function wq(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wK.t8(wV,n),{toml:n}):{toml:wK.U2(wV)||""}}var wZ=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wq({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wK.t8("".concat(wV),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"New Job"}),l.createElement(aW.Z,null,l.createElement(wW,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _M(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_W,e)},_V=function(){var e=_K({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_U,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_q=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_x,{data:t.publicKey}))))};function _Z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _X(){var e=_Z(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _X=function(){return e},e}var _J=n0(_X()),_Q=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(sl.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ok.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gU,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_q,{csaKey:e,key:t})}))))};function _1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EM,e)};function EA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EJ,e)},E3=function(){return oo(EQ)},E4=function(){return oo(E1)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(E0,e)};function E5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(SK,e)};function Sq(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kV(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kq=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kK(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kW(kz({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aW.Z,null,l.createElement(kH,{object:n})))};function kZ(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kX(e){for(var t=1;t0&&l.createElement(kr,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kq,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kN,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k5(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k5(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k9=n0(k8(),k4),k7=function(){var e=rv(k9,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oa,null);default:return null}};function xe(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xt(){var e=xe(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xt=function(){return e},e}var xn=n0(xt()),xr=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yp,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xa(){var e=xi(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xa=function(){return e},e}var xo=n0(xa(),xn),xs=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xo,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(xr,{loading:a,data:i,page:t,pageSize:n})},xu=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xs,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(k7,null)))},xc=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xl=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xc,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hR,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ok.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xf=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:r,onSubmit:n})))))};function xd(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xh(){var e=xd(["\n query FetchFeedsManagers {\n feedsManagers {\n results {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n }\n }\n }\n"]);return xh=function(){return e},e}var xp=n0(xh()),xb=function(){return rv(xp)};function xm(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function xF(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function xY(e,t){return xD(e)||xP(e,t)||xB(e,t)||xR()}function xB(e,t){if(e){if("string"==typeof e)return xI(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return xI(e,t)}}var xU=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},xH=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0().required("Required"),ocr1Multiaddr:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr1P2PPeerID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr1KeyBundleID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2Multiaddr:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr2P2PPeerID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2KeyBundleID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2CommitPluginEnabled:pV().required("Required"),ocr2ExecutePluginEnabled:pV().required("Required"),ocr2MedianPluginEnabled:pV().required("Required"),ocr2MercuryPluginEnabled:pV().required("Required"),ocr2ForwarderAddress:p0().nullable()}),x$=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},xz=function(e){var t=e.chainAccounts,n=xj(e,["chainAccounts"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=xY(l.useState(!1),2),c=u[0],f=u[1],d=l.useRef();l.useEffect(function(){d.current=a},[a]),l.useEffect(function(){a!==d.current&&(s(n.name,""),f(!1))},[a,s,n.name]);var h=function(e){var t=e.target.value;"custom"===t?(f(!0),s(n.name,"")):(f(!1),s(n.name,t))};return l.createElement(l.Fragment,null,!xU(a)&&l.createElement(hP,xN({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e.address,value:e.address},e.address)})),xU(a)&&l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Enter your account address",inputProps:{"data-testid":"customAccountAddr-input"},helperText:"The account address used for this chain",required:!0,fullWidth:!0}),xU(a)&&l.createElement("div",null,l.createElement(hP,{component:hX,id:"accountAddrPubKey",name:"accountAddrPubKey",label:"Account Address Public Key",required:!0,fullWidth:!0,helperText:"The public key for your account address",FormHelperTextProps:{"data-testid":"accountAddrPubKey-helper-text"}})))},xG=(0,b.withStyles)(x$)(function(e){var t=e.classes,n=e.editing,r=void 0!==n&&n,i=e.innerRef,a=e.initialValues,o=e.onSubmit,s=e.chainIDs,u=void 0===s?[]:s,c=e.accounts,f=void 0===c?[]:c,h=e.p2pKeys,p=void 0===h?[]:h,b=e.ocrKeys,m=void 0===b?[]:b,g=e.ocr2Keys,v=void 0===g?[]:g,y=e.showSubmit,w=void 0!==y&&y;return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:xH,onSubmit:o},function(e){var n=e.values,i=f.filter(function(e){return e.chain.id==n.chainID&&!e.isDisabled});return l.createElement(hR,{"data-testid":"feeds-manager-form",id:"chain-configuration-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainType",name:"chainType",label:"Chain Type",select:!0,required:!0,fullWidth:!0,disabled:!0},l.createElement(tE.default,{key:"EVM",value:"EVM"},"EVM"))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,select:!0,disabled:r,inputProps:{"data-testid":"chainID-input"},FormHelperTextProps:{"data-testid":"chainID-helper-text"}},u.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(xz,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-input"},required:!0,fullWidth:!0,select:!0,helperText:"The account address used for this chain",chainAccounts:i,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",required:!0,fullWidth:!0,helperText:"The address used for LINK payments",FormHelperTextProps:{"data-testid":"adminAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Job Types")),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"fluxMonitorEnabled",type:"checkbox",Label:{label:"Flux Monitor"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1Enabled",type:"checkbox",Label:{label:"OCR"}}),n.ocr1Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),n.ocr1IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr1Multiaddr",name:"ocr1Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr1Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1P2PPeerID",name:"ocr1P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1P2PPeerID-helper-text"}},p.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1KeyBundleID",name:"ocr1KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1KeyBundleID-helper-text"}},m.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})))))))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2Enabled",type:"checkbox",Label:{label:"OCR2"}}),n.ocr2Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),n.ocr2IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr2Multiaddr",name:"ocr2Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR2 Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr2Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},p.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2KeyBundleID",name:"ocr2KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR2 Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2KeyBundleID-helper-text"}},v.filter(function(e){return n.chainType===e.chainType}).map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)}))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Plugins")),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2CommitPluginEnabled",type:"checkbox",Label:{label:"Commit"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2ExecutePluginEnabled",type:"checkbox",Label:{label:"Execute"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2RebalancerPluginEnabled",type:"checkbox",Label:{label:"Rebalancer"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MedianPluginEnabled",type:"checkbox",Label:{label:"Median"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MercuryPluginEnabled",type:"checkbox",Label:{label:"Mercury"}})),l.createElement(d.Z,{item:!0,xs:12,md:12},l.createElement(hP,{component:hX,id:"ocr2ForwarderAddress",name:"ocr2ForwarderAddress",label:"Forwarder Address (optional)",fullWidth:!0,helperText:"The forwarder address from the Operator Forwarder Contract",FormHelperTextProps:{"data-testid":"ocr2ForwarderAddress-helper-text"}}))))))),w&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})}),xW=function(e){var t=e.onClose,n=e.open,r=e.onSubmit,i=l.useRef(),a=i$({fetchPolicy:"network-only"}).data,o=_K({fetchPolicy:"cache-and-network"}).data,s=SV({fetchPolicy:"cache-and-network"}).data,u=EO({fetchPolicy:"cache-and-network"}).data,c=E2({fetchPolicy:"cache-and-network"}).data,f={chainID:"",chainType:"EVM",accountAddr:"",adminAddr:"",accountAddrPubKey:"",fluxMonitorEnabled:!1,ocr1Enabled:!1,ocr1IsBootstrap:!1,ocr1Multiaddr:"",ocr1P2PPeerID:"",ocr1KeyBundleID:"",ocr2Enabled:!1,ocr2IsBootstrap:!1,ocr2Multiaddr:"",ocr2P2PPeerID:"",ocr2KeyBundleID:"",ocr2CommitPluginEnabled:!1,ocr2ExecutePluginEnabled:!1,ocr2MedianPluginEnabled:!1,ocr2MercuryPluginEnabled:!1,ocr2RebalancerPluginEnabled:!1,ocr2ForwarderAddress:""},d=a?a.chains.results.map(function(e){return e.id}):[],h=o?o.ethKeys.results:[],p=s?s.p2pKeys.results:[],b=u?u.ocrKeyBundles.results:[],m=c?c.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:t,open:n,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"New Supported Chain")),l.createElement(oT.Z,null,l.createElement(xG,{innerRef:i,initialValues:f,onSubmit:r,chainIDs:d,accounts:h,p2pKeys:p,ocrKeys:b,ocr2Keys:m})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:t},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))},xK=function(e){var t=e.cfg,n=e.onClose,r=e.open,i=e.onSubmit,a=l.useRef(),o=i$({fetchPolicy:"network-only"}).data,s=_K({fetchPolicy:"cache-and-network"}).data,u=SV({fetchPolicy:"cache-and-network"}).data,c=EO({fetchPolicy:"cache-and-network"}).data,f=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var d={chainID:t.chainID,chainType:"EVM",accountAddr:t.accountAddr,adminAddr:t.adminAddr,accountAddrPubKey:t.accountAddrPubKey,fluxMonitorEnabled:t.fluxMonitorJobConfig.enabled,ocr1Enabled:t.ocr1JobConfig.enabled,ocr1IsBootstrap:t.ocr1JobConfig.isBootstrap,ocr1Multiaddr:t.ocr1JobConfig.multiaddr,ocr1P2PPeerID:t.ocr1JobConfig.p2pPeerID,ocr1KeyBundleID:t.ocr1JobConfig.keyBundleID,ocr2Enabled:t.ocr2JobConfig.enabled,ocr2IsBootstrap:t.ocr2JobConfig.isBootstrap,ocr2Multiaddr:t.ocr2JobConfig.multiaddr,ocr2P2PPeerID:t.ocr2JobConfig.p2pPeerID,ocr2KeyBundleID:t.ocr2JobConfig.keyBundleID,ocr2CommitPluginEnabled:t.ocr2JobConfig.plugins.commit,ocr2ExecutePluginEnabled:t.ocr2JobConfig.plugins.execute,ocr2MedianPluginEnabled:t.ocr2JobConfig.plugins.median,ocr2MercuryPluginEnabled:t.ocr2JobConfig.plugins.mercury,ocr2RebalancerPluginEnabled:t.ocr2JobConfig.plugins.rebalancer,ocr2ForwarderAddress:t.ocr2JobConfig.forwarderAddress},h=o?o.chains.results.map(function(e){return e.id}):[],p=s?s.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:n,open:r,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"Edit Supported Chain")),l.createElement(oT.Z,null,l.createElement(xG,{innerRef:a,initialValues:d,onSubmit:i,chainIDs:h,accounts:p,p2pKeys:b,ocrKeys:m,ocr2Keys:g,editing:!0})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:n},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))};function xV(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xq(){var e=xV(["\n fragment FeedsManager_ChainConfigFields on FeedsManagerChainConfig {\n id\n chainID\n chainType\n accountAddr\n adminAddr\n accountAddrPubKey\n fluxMonitorJobConfig {\n enabled\n }\n ocr1JobConfig {\n enabled\n isBootstrap\n multiaddr\n p2pPeerID\n keyBundleID\n }\n ocr2JobConfig {\n enabled\n isBootstrap\n multiaddr\n forwarderAddress\n p2pPeerID\n keyBundleID\n plugins {\n commit\n execute\n median\n mercury\n rebalancer\n }\n }\n }\n"]);return xq=function(){return e},e}function xZ(){var e=xV(["\n ","\n fragment FeedsManagerFields on FeedsManager {\n id\n name\n uri\n publicKey\n isConnectionActive\n chainConfigs {\n ...FeedsManager_ChainConfigFields\n }\n }\n"]);return xZ=function(){return e},e}function xX(){var e=xV(["\n fragment FeedsManager_JobProposalsFields on JobProposal {\n id\n name\n externalJobID\n remoteUUID\n status\n pendingUpdate\n latestSpec {\n createdAt\n version\n }\n }\n"]);return xX=function(){return e},e}function xJ(){var e=xV(["\n ","\n ","\n fragment FeedsManagerPayload_ResultsFields on FeedsManager {\n ...FeedsManagerFields\n jobProposals {\n ...FeedsManager_JobProposalsFields\n }\n }\n"]);return xJ=function(){return e},e}function xQ(){var e=xV(["\n ","\n query FetchFeedManagersWithProposals {\n feedsManagers {\n results {\n ...FeedsManagerPayload_ResultsFields\n }\n }\n }\n"]);return xQ=function(){return e},e}var x1=n0(xq()),x0=n0(xZ(),x1),x2=n0(xX()),x3=n0(xJ(),x0,x2),x4=n0(xQ(),x3),x6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(x4,e)};function x5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0?n.feedsManagers.results[0]:void 0;return n&&a?l.createElement(TZ,{manager:a}):l.createElement(h.l_,{to:{pathname:"/feeds_manager/new",state:{from:e}}})},TJ={name:"Chainlink Feeds Manager",uri:"",publicKey:""},TQ=function(e){var t=e.onSubmit;return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Register Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:TJ,onSubmit:t})))))};function T1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return ME(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mP.Z,{defaultExpanded:0===n,key:n},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Es.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mj.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ok.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gd,{language:"toml",style:gs,"data-testid":"codeblock"},e.definition)))}),l.createElement(oC,{open:null!=c,title:c?MM[c.action].title:"",body:c?MM[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Md,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function MA(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function ML(){var e=MA(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return ML=function(){return e},e}var MC=n0(ML(),Mx),MI=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(Mo,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(Tq,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(MO,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function MD(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.nextNonce&&t.append("nextNonce",e.nextNonce),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file +`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pB({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pO({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pO({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pB({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pB({},t,{value:e}))._validate(e,pB({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pT.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pT.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pn(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pf.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pf.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pf.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pR(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pS(e).map(e=>new pD(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pE(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pR({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pf.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pR({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pf.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pR({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pH of(pU.prototype.__isYupSchema__=!0,["validate","validateSync"]))pU.prototype[`${pH}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pF(this,e,t,n.context);return a[pH](r&&r[i],pB({},n,{parent:r,path:e}))};for(let p$ of["equals","is"])pU.prototype[p$]=pU.prototype.oneOf;for(let pz of["not","nope"])pU.prototype[pz]=pU.prototype.notOneOf;pU.prototype.optional=pU.prototype.notRequired;let pG=pU;function pW(){return new pG}pW.prototype=pG.prototype;let pK=e=>null==e;function pV(){return new pq}class pq extends pU{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pK(e)||!0===e})}isFalse(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pK(e)||!1===e})}}pV.prototype=pq.prototype;let pZ=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pX=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pJ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pQ=e=>pK(e)||e===e.trim(),p1=({}).toString();function p0(){return new p2}class p2 extends pU{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p1?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pd.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t=pd.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t=pd.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pd.matches,params:{regex:e},test:t=>pK(t)||""===t&&n||-1!==t.search(e)})}email(e=pd.email){return this.matches(pZ,{name:"email",message:e,excludeEmptyString:!0})}url(e=pd.url){return this.matches(pX,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pd.uuid){return this.matches(pJ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pd.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pQ})}lowercase(e=pd.lowercase){return this.transform(e=>pK(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toLowerCase()})}uppercase(e=pd.uppercase){return this.transform(e=>pK(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toUpperCase()})}}p0.prototype=p2.prototype;let p3=e=>e!=+e;function p4(){return new p6}class p6 extends pU{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p3(e)}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t>=this.resolve(e)}})}max(e,t=ph.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t<=this.resolve(e)}})}lessThan(e,t=ph.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pK(t)||tthis.resolve(e)}})}positive(e=ph.positive){return this.moreThan(0,e)}negative(e=ph.negative){return this.lessThan(0,e)}integer(e=ph.integer){return this.test({name:"integer",message:e,test:e=>pK(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pK(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pK(t)?t:Math[e](t))}}p4.prototype=p6.prototype;var p5=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p5.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p9=new Date(""),p7=e=>"[object Date]"===Object.prototype.toString.call(e);function be(){return new bt}class bt extends pU{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p9:new Date(e))})})}_typeCheck(e){return p7(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pD.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pp.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pK(e)||e>=this.resolve(n)}})}max(e,t=pp.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pK(e)||e<=this.resolve(n)}})}}bt.INVALID_DATE=p9,be.prototype=bt.prototype,be.INVALID_DATE=p9;var bn=n(11865),br=n.n(bn),bi=n(68929),ba=n.n(bi),bo=n(67523),bs=n.n(bo),bu=n(94633),bc=n.n(bu);function bl(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pC.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(py()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pD.isRef(o)&&o.isSibling?i(o.path,a):pw(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bc().array(r,n).reverse()}function bf(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bd(e){return(t,n)=>bf(e,t)-bf(e,n)}function bh(){return(bh=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bb(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bm=bd([]);class bg extends pU{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bm,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bp(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bh({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=py()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pT.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bp(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bh({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pO({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bh({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pU&&i instanceof pU&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bd(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bl(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pC.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return py()(i,e)&&(a=bh({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pm.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bb(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pm.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bs()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(ba())}snakeCase(){return this.transformKeys(br())}constantCase(){return this.transformKeys(e=>br()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pL()(this.fields,e=>e.describe()),e}}function bv(e){return new bg(e)}function by(){return(by=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,by({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pT.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pO({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pw(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pl(e));return t.innerType=e,t}length(e,t=pg.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pg.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pg.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bw.prototype=b_.prototype;var bE=bv().shape({name:p0().required("Required"),url:p0().required("Required")}),bS=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hT,{initialValues:t,validationSchema:bE,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hR,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bk=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Bridge",action:l.createElement(aA.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aW.Z,null,l.createElement(bS,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},mc=n(76023);function ml(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mB(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mZ={};function mX(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mZ[t]||(mZ[t]=mq(e)),mZ[t]}function mJ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mX(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mK({},e,n[t])},t)}function mQ(e){return e.join(" ")}function m1(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m0({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m0(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m1(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mK({},s,{className:mQ(m)||void 0,style:mJ(s.className,Object.assign({},s.style,i),n)})}else d=mK({},s,{className:mQ(s.className)});var g=h(t.children);return l.createElement(c,(0,mV.Z)({key:o},d),g)}}let m2=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m3=/\n/g;function m4(e){return e.match(m3)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m5(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m9(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function m7(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mK({},i,"function"==typeof e?e(t):e)}function ge(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=m7(r,n,i);t.unshift(m9(n,h))}return f&l&&(d.style=mK({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gt(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return ge({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=m7(s,t,o);e.unshift(m9(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m4(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(ge({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=ge({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gu=n(98695),gc=n.n(gu);let gl=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gf=go(gc(),gs);gf.supportedLanguages=gl;let gd=gf;var gh=n(64566);function gp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gb(){var e=gp(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gb=function(){return e},e}var gm=n0(gb()),gg=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gv=function(){return l.createElement(gg,null,"...")},gy=function(e){var t=e.children;return l.createElement(gg,null,t)},gw=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gy,null,i);if(t)return l.createElement(gv,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mP.Z,{defaultExpanded:o},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},a),l.createElement(mj.Z,{style:s},l.createElement(gd,{language:"toml",style:gs},n))))},g_=function(){var e=rv(gm,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gw,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gE=n(34823),gS=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gk=(0,b.withStyles)(gS)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gE.N,A.wU);return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gx=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(g_,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mN,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mE,null))))))},gT=function(){return l.createElement(gx,null)},gM=function(){return l.createElement(gT,null)},gO=n(44431),gA=1e18,gL=function(e){return new gO.BigNumber(e).dividedBy(gA).toFixed(8)},gC=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sl.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aW.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(op,{title:"Address"}),l.createElement(ob,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"Native Token Balance"}),l.createElement(ob,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"LINK Balance"}),l.createElement(ob,{value:e.linkBalance?gL(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gB.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(aA.Z,{href:"/runs",component:tz},"View More"))))))});function vt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vn(){var e=vt(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vn=function(){return e},e}var vr=5,vi=n0(vn(),g9),va=function(){var e=rv(vi,{variables:{offset:0,limit:vr},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(ve,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vr})},vo=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vs=(0,b.withStyles)(vo)(function(e){var t=e.classes,n=(0,A.v9)(gE.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vu=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vc=(0,b.withStyles)(vu)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function vl(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vf(){var e=vl(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vf=function(){return e},e}var vd=n0(vf()),vh=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vp=(0,b.withStyles)(vh)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gU,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vc,{job:e,key:t})}))))});function vb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vm(){var e=vb(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vm=function(){return e},e}var vg=5,vv=n0(vm(),vd),vy=function(){var e=rv(vv,{variables:{offset:0,limit:vg},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vp,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vw=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(va,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gY,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vy,null))))),l.createElement(vs,null))},v_=function(){return l.createElement(vw,null)},vE=function(){return l.createElement(v_,null)},vS=n(87239),vk=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vx=n(5022),vT=n(78718),vM=n.n(vT);function vO(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yh(t,e.status))},e.status.toLowerCase())))})))}),yb=n(16839),ym=n.n(yb);function yg(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=ym().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yv=n(94164),yy=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yw=n(73343),y_=n(3379),yE=n.n(y_);function yS(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yv.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yw.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yy,{data:e}))}))};function yL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyY&&l.createElement("div",{className:t.runDetails},l.createElement(aA.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yF,{observationSource:n.observationSource})))});function yH(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vx.parse(e),!0}catch(t){return!1}})}),wW=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hT,{initialValues:t,validationSchema:wG,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hR,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wK=n(50109),wV="persistSpec";function wq(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wK.t8(wV,n),{toml:n}):{toml:wK.U2(wV)||""}}var wZ=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wq({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wK.t8("".concat(wV),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"New Job"}),l.createElement(aW.Z,null,l.createElement(wW,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _M(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_W,e)},_V=function(){var e=_K({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_U,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_q=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_x,{data:t.publicKey}))))};function _Z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _X(){var e=_Z(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _X=function(){return e},e}var _J=n0(_X()),_Q=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(sl.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ok.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gU,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_q,{csaKey:e,key:t})}))))};function _1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EM,e)};function EA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EJ,e)},E3=function(){return oo(EQ)},E4=function(){return oo(E1)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(E0,e)};function E5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(SK,e)};function Sq(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kV(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kq=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kK(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kW(kz({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aW.Z,null,l.createElement(kH,{object:n})))};function kZ(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kX(e){for(var t=1;t0&&l.createElement(kr,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kq,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kN,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k5(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k5(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k9=n0(k8(),k4),k7=function(){var e=rv(k9,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oa,null);default:return null}};function xe(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xt(){var e=xe(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xt=function(){return e},e}var xn=n0(xt()),xr=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yp,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xa(){var e=xi(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xa=function(){return e},e}var xo=n0(xa(),xn),xs=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xo,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(xr,{loading:a,data:i,page:t,pageSize:n})},xu=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xs,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(k7,null)))},xc=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xl=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xc,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hR,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ok.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xf=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:r,onSubmit:n})))))};function xd(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xh(){var e=xd(["\n query FetchFeedsManagers {\n feedsManagers {\n results {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n }\n }\n }\n"]);return xh=function(){return e},e}var xp=n0(xh()),xb=function(){return rv(xp)};function xm(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function xF(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function xY(e,t){return xD(e)||xP(e,t)||xB(e,t)||xR()}function xB(e,t){if(e){if("string"==typeof e)return xI(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return xI(e,t)}}var xU=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},xH=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0().required("Required"),ocr1Multiaddr:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr1P2PPeerID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr1KeyBundleID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2Multiaddr:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr2P2PPeerID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2KeyBundleID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2CommitPluginEnabled:pV().required("Required"),ocr2ExecutePluginEnabled:pV().required("Required"),ocr2MedianPluginEnabled:pV().required("Required"),ocr2MercuryPluginEnabled:pV().required("Required"),ocr2ForwarderAddress:p0().nullable()}),x$=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},xz=function(e){var t=e.chainAccounts,n=xj(e,["chainAccounts"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=xY(l.useState(!1),2),c=u[0],f=u[1],d=l.useRef();l.useEffect(function(){d.current=a},[a]),l.useEffect(function(){a!==d.current&&(s(n.name,""),f(!1))},[a,s,n.name]);var h=function(e){var t=e.target.value;"custom"===t?(f(!0),s(n.name,"")):(f(!1),s(n.name,t))};return l.createElement(l.Fragment,null,!xU(a)&&l.createElement(hP,xN({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e.address,value:e.address},e.address)})),xU(a)&&l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Enter your account address",inputProps:{"data-testid":"customAccountAddr-input"},helperText:"The account address used for this chain",required:!0,fullWidth:!0}),xU(a)&&l.createElement("div",null,l.createElement(hP,{component:hX,id:"accountAddrPubKey",name:"accountAddrPubKey",label:"Account Address Public Key",required:!0,fullWidth:!0,helperText:"The public key for your account address",FormHelperTextProps:{"data-testid":"accountAddrPubKey-helper-text"}})))},xG=(0,b.withStyles)(x$)(function(e){var t=e.classes,n=e.editing,r=void 0!==n&&n,i=e.innerRef,a=e.initialValues,o=e.onSubmit,s=e.chainIDs,u=void 0===s?[]:s,c=e.accounts,f=void 0===c?[]:c,h=e.p2pKeys,p=void 0===h?[]:h,b=e.ocrKeys,m=void 0===b?[]:b,g=e.ocr2Keys,v=void 0===g?[]:g,y=e.showSubmit,w=void 0!==y&&y;return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:xH,onSubmit:o},function(e){var n=e.values,i=f.filter(function(e){return e.chain.id==n.chainID&&!e.isDisabled});return l.createElement(hR,{"data-testid":"feeds-manager-form",id:"chain-configuration-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainType",name:"chainType",label:"Chain Type",select:!0,required:!0,fullWidth:!0,disabled:!0},l.createElement(tE.default,{key:"EVM",value:"EVM"},"EVM"))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,select:!0,disabled:r,inputProps:{"data-testid":"chainID-input"},FormHelperTextProps:{"data-testid":"chainID-helper-text"}},u.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(xz,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-input"},required:!0,fullWidth:!0,select:!0,helperText:"The account address used for this chain",chainAccounts:i,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",required:!0,fullWidth:!0,helperText:"The address used for LINK payments",FormHelperTextProps:{"data-testid":"adminAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Job Types")),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"fluxMonitorEnabled",type:"checkbox",Label:{label:"Flux Monitor"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1Enabled",type:"checkbox",Label:{label:"OCR"}}),n.ocr1Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),n.ocr1IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr1Multiaddr",name:"ocr1Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr1Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1P2PPeerID",name:"ocr1P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1P2PPeerID-helper-text"}},p.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1KeyBundleID",name:"ocr1KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1KeyBundleID-helper-text"}},m.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})))))))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2Enabled",type:"checkbox",Label:{label:"OCR2"}}),n.ocr2Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),n.ocr2IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr2Multiaddr",name:"ocr2Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR2 Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr2Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},p.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2KeyBundleID",name:"ocr2KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR2 Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2KeyBundleID-helper-text"}},v.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)}))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Plugins")),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2CommitPluginEnabled",type:"checkbox",Label:{label:"Commit"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2ExecutePluginEnabled",type:"checkbox",Label:{label:"Execute"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2RebalancerPluginEnabled",type:"checkbox",Label:{label:"Rebalancer"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MedianPluginEnabled",type:"checkbox",Label:{label:"Median"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MercuryPluginEnabled",type:"checkbox",Label:{label:"Mercury"}})),l.createElement(d.Z,{item:!0,xs:12,md:12},l.createElement(hP,{component:hX,id:"ocr2ForwarderAddress",name:"ocr2ForwarderAddress",label:"Forwarder Address (optional)",fullWidth:!0,helperText:"The forwarder address from the Operator Forwarder Contract",FormHelperTextProps:{"data-testid":"ocr2ForwarderAddress-helper-text"}}))))))),w&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})}),xW=function(e){var t=e.onClose,n=e.open,r=e.onSubmit,i=l.useRef(),a=i$({fetchPolicy:"network-only"}).data,o=_K({fetchPolicy:"cache-and-network"}).data,s=SV({fetchPolicy:"cache-and-network"}).data,u=EO({fetchPolicy:"cache-and-network"}).data,c=E2({fetchPolicy:"cache-and-network"}).data,f={chainID:"",chainType:"EVM",accountAddr:"",adminAddr:"",accountAddrPubKey:"",fluxMonitorEnabled:!1,ocr1Enabled:!1,ocr1IsBootstrap:!1,ocr1Multiaddr:"",ocr1P2PPeerID:"",ocr1KeyBundleID:"",ocr2Enabled:!1,ocr2IsBootstrap:!1,ocr2Multiaddr:"",ocr2P2PPeerID:"",ocr2KeyBundleID:"",ocr2CommitPluginEnabled:!1,ocr2ExecutePluginEnabled:!1,ocr2MedianPluginEnabled:!1,ocr2MercuryPluginEnabled:!1,ocr2RebalancerPluginEnabled:!1,ocr2ForwarderAddress:""},d=a?a.chains.results.map(function(e){return e.id}):[],h=o?o.ethKeys.results:[],p=s?s.p2pKeys.results:[],b=u?u.ocrKeyBundles.results:[],m=c?c.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:t,open:n,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"New Supported Chain")),l.createElement(oT.Z,null,l.createElement(xG,{innerRef:i,initialValues:f,onSubmit:r,chainIDs:d,accounts:h,p2pKeys:p,ocrKeys:b,ocr2Keys:m})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:t},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))},xK=function(e){var t=e.cfg,n=e.onClose,r=e.open,i=e.onSubmit,a=l.useRef(),o=i$({fetchPolicy:"network-only"}).data,s=_K({fetchPolicy:"cache-and-network"}).data,u=SV({fetchPolicy:"cache-and-network"}).data,c=EO({fetchPolicy:"cache-and-network"}).data,f=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var d={chainID:t.chainID,chainType:"EVM",accountAddr:t.accountAddr,adminAddr:t.adminAddr,accountAddrPubKey:t.accountAddrPubKey,fluxMonitorEnabled:t.fluxMonitorJobConfig.enabled,ocr1Enabled:t.ocr1JobConfig.enabled,ocr1IsBootstrap:t.ocr1JobConfig.isBootstrap,ocr1Multiaddr:t.ocr1JobConfig.multiaddr,ocr1P2PPeerID:t.ocr1JobConfig.p2pPeerID,ocr1KeyBundleID:t.ocr1JobConfig.keyBundleID,ocr2Enabled:t.ocr2JobConfig.enabled,ocr2IsBootstrap:t.ocr2JobConfig.isBootstrap,ocr2Multiaddr:t.ocr2JobConfig.multiaddr,ocr2P2PPeerID:t.ocr2JobConfig.p2pPeerID,ocr2KeyBundleID:t.ocr2JobConfig.keyBundleID,ocr2CommitPluginEnabled:t.ocr2JobConfig.plugins.commit,ocr2ExecutePluginEnabled:t.ocr2JobConfig.plugins.execute,ocr2MedianPluginEnabled:t.ocr2JobConfig.plugins.median,ocr2MercuryPluginEnabled:t.ocr2JobConfig.plugins.mercury,ocr2RebalancerPluginEnabled:t.ocr2JobConfig.plugins.rebalancer,ocr2ForwarderAddress:t.ocr2JobConfig.forwarderAddress},h=o?o.chains.results.map(function(e){return e.id}):[],p=s?s.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:n,open:r,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"Edit Supported Chain")),l.createElement(oT.Z,null,l.createElement(xG,{innerRef:a,initialValues:d,onSubmit:i,chainIDs:h,accounts:p,p2pKeys:b,ocrKeys:m,ocr2Keys:g,editing:!0})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:n},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))};function xV(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xq(){var e=xV(["\n fragment FeedsManager_ChainConfigFields on FeedsManagerChainConfig {\n id\n chainID\n chainType\n accountAddr\n adminAddr\n accountAddrPubKey\n fluxMonitorJobConfig {\n enabled\n }\n ocr1JobConfig {\n enabled\n isBootstrap\n multiaddr\n p2pPeerID\n keyBundleID\n }\n ocr2JobConfig {\n enabled\n isBootstrap\n multiaddr\n forwarderAddress\n p2pPeerID\n keyBundleID\n plugins {\n commit\n execute\n median\n mercury\n rebalancer\n }\n }\n }\n"]);return xq=function(){return e},e}function xZ(){var e=xV(["\n ","\n fragment FeedsManagerFields on FeedsManager {\n id\n name\n uri\n publicKey\n isConnectionActive\n chainConfigs {\n ...FeedsManager_ChainConfigFields\n }\n }\n"]);return xZ=function(){return e},e}function xX(){var e=xV(["\n fragment FeedsManager_JobProposalsFields on JobProposal {\n id\n name\n externalJobID\n remoteUUID\n status\n pendingUpdate\n latestSpec {\n createdAt\n version\n }\n }\n"]);return xX=function(){return e},e}function xJ(){var e=xV(["\n ","\n ","\n fragment FeedsManagerPayload_ResultsFields on FeedsManager {\n ...FeedsManagerFields\n jobProposals {\n ...FeedsManager_JobProposalsFields\n }\n }\n"]);return xJ=function(){return e},e}function xQ(){var e=xV(["\n ","\n query FetchFeedManagersWithProposals {\n feedsManagers {\n results {\n ...FeedsManagerPayload_ResultsFields\n }\n }\n }\n"]);return xQ=function(){return e},e}var x1=n0(xq()),x0=n0(xZ(),x1),x2=n0(xX()),x3=n0(xJ(),x0,x2),x4=n0(xQ(),x3),x6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(x4,e)};function x5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0?n.feedsManagers.results[0]:void 0;return n&&a?l.createElement(TZ,{manager:a}):l.createElement(h.l_,{to:{pathname:"/feeds_manager/new",state:{from:e}}})},TJ={name:"Chainlink Feeds Manager",uri:"",publicKey:""},TQ=function(e){var t=e.onSubmit;return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Register Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:TJ,onSubmit:t})))))};function T1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return ME(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mP.Z,{defaultExpanded:0===n,key:n},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Es.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mj.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ok.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gd,{language:"toml",style:gs,"data-testid":"codeblock"},e.definition)))}),l.createElement(oC,{open:null!=c,title:c?MM[c.action].title:"",body:c?MM[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Md,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function MA(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function ML(){var e=MA(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return ML=function(){return e},e}var MC=n0(ML(),Mx),MI=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(Mo,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(Tq,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(MO,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function MD(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.nextNonce&&t.append("nextNonce",e.nextNonce),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file diff --git a/core/web/assets/main.026013f04da39527a75d.js.gz b/core/web/assets/main.6f07a88cfc748f57e21d.js.gz similarity index 94% rename from core/web/assets/main.026013f04da39527a75d.js.gz rename to core/web/assets/main.6f07a88cfc748f57e21d.js.gz index 8524ee8d01a3a4be87692f99e938d155562e3d92..1a833982299df121160a1d6a5f4661e5553cf095 100644 GIT binary patch delta 66266 zcmV)GK)%0(fJyoPNPvU^gaU*Egam{Iga(8Mgb0KQgbIWUgbaiYgbsucv=A=be_GC1!y+kSgYR%9BZuBdeGZUo-BZ`{hK_qf@XGulsUx6|j@irS z<_zZewd3|*MtDGzF_HE_4k%fpbF$0^P3GP?mpvZ`JwOMSb;I@nzs3xkEwIY&lc}+ln6Q)Y!C>r?O>38CB7rP62{G!4bUr$ zM_4j8n@k=MR{lu#jkDv6jR&8o_=q+d`r}2Rbny8digA}+Iq9dD1b^2*_XdMguzZXu zytu4PE9wBl?O>r`da{D2o)-q8Z;s9}!7=XR+0zJ6w8?XU{w2*HHAdq`3;f=QrY$3Z zqeBPKmo?oGCVykCj|S0=<6cs3Mt{W5x)|G(I3;})#;<^Gy}x+2c6oci072kfzrt~_ znq0vaO!i~c893G}JQFCD4Q~V|aqr39WP%75|FNt^D5${=P2m=;U^z;P&|-3X(??(+SC!2?V?6^`S5EjZUgf$y*^{XJh;6CXb)O zFtcGyO|u^fJ8Z?mDI7GabA5)fU4j<>&~YP6t!UJ4H7Jn7AdG9ofjG(}PlEKBbSOE6 zDap=AV}ImiNJ_?5(bMugCQUHXJ$P=0cw)}hwEu>dVvSAL@WJ!@VCz~_#e@|jL%@Fs zmt?PJs&0iQ7^duFb7Xd$fdd-lwIe+onl2NZQjJZkkLEx^ZI4XPlhN?N@s{d49G)im z>Kb_l*lLZf`XQWeprelA@ZPJ>8mgLBwLKTZ=$I6c%cU76HMA8j7A707 zEyD=4L#S9gWJjY&n+NbA--wo7$2A9o897gRR2yX&PL&P^;D#}an--UJx@w?N<&z(0 z&wn_xcfXE`<(;Tv zc_mdveDXTPhT^#=BySn=jq!7p`1Z6yGsI+1XsDqf$MCOe*T^*dt2%6qbg`{EDHIqU z6p9QF3R$U7nkueZkq=lem&64}TcVWJ*?&}-ioR!zpQ@o&O$gL&(MY`>nzK|=x;$h+ z`r0gUIq=-$fn)V`IN17*xic_3c%bMcLCek%yOG45+#AH;jk#xG8!ROzar|ixbO(~L zx%yL@k4|+o1RwMQtamw{DI`~a=2=m2O3f?z?}cx{sX=h#JxWH-i1j4cg@iEgE`Lss zx!Z=?(gRq9=D47)#NWJC(&r&SZ0W2am8UXKeT!4O{8wswB;sE^P*BsBWqlt zkiOrqdYyC#7%Qv@v@t8^c_J3V#|QT~k?Kp)lhsl&|O*&B=BS5c?`!a4-Nz;BjZq zbmfETLnxnKx$HSXg%YQVWxB2x0zZvh5F)k|YWDJnPopsO+)F$SNnT&Lr2vhfmwF18 zUPBQO;w7?xSr1aLk~`#0awXq%b?VE2#_z%8SlfLJCdbc)tJWJ2AMa^s{C^Sd??2ps zEZQFhOo#DLj_EKih3PQL#T#8W{7Xrd^HeRqz{y;CQ2UZ7BSQg2r`tc#^Qh`n91X zKY0Nf3S~5|4TWCv2jDwy>|PrXwiYNvavV1#9%{Aqey5I|c&P-(03S-6*1+XBb_#;8 z5Dzwpub^c-_*$=e`9f2*Dg>GXu||U_I?t78-^TT_r`e(USxZ5FJPZL&63GcGA`-%4PGL?{59Sv`de%e zyYsb;G4rvm+2%m-hW;4-p>d-^v*4H5DDrzr{pWWn)7qTVo|Xeqkl1uRBdY*9MdnsEn2QKP`?cCNaeSYJd9h-K z`VGDr@8muWYDr=K+#2iz`>`^jaO*~%~pn%LQad>75qVX|HZKG^#0-I(5^Hf&^ zv3@IpMn}F3H*i&|-zzlYl-FhuR$3T?`|leX z1EgGUJ^{s`C=Ona&yfv&D^x*>vB)Gj4~czd>!$$Sz$QuG%bef#gA5vUP2jJnb-a zl7C~J2 z5g@IM>nDXIMJQOHP^LJCFooSKetwxd!2RCHbRqXR1?AC@>(DP`r$siNT_@aO2zm;N z0TT$i1m2;z3FM4=2_BqX&mTgF+EfIsC)aP)LyYaoqwX?twq)2rDjmRBH z>9e8fxMWg^scJ=411AX2DQa_z41F~zo2xrtn3Pze7>IM-r;d5Sav#eUXPEFz*%a~S|GT!m zU7Eut%!in5m|SB;en1q~;M)k922rsWgHKOyS!_j2urQX((mAXt#ZD*0`bzxE+e1&{ z0wj;3#>brH8&5r{cO$5e6i45v1AmMKuAYHay@{(kQ#F-WiDo@DL>%@QI6S{jQwo|d zmS|WyVAVKy1fk2bA&CT@bwp*$jYu8hz~X-)*fMK)5k-joDDust}s0h7cy^R*x?IyBCd|XzMGEhr17Ps8KBk?cC;E+%`o(xP88z6NQxjh#gHTG*l^Xy zd-a1o4b5h&j;~i-;8$~5U6W5}=~SAjNAj$$;Ja|>Qfg4JahVMN^;;y_uu!ptP;{8j z8%Bz*XapvU!*%#ZsxtyQM}LBkaD}fmDXf>^P8a6+M7fTf$G|~_%?=6uK`wCU2`C(Q zclUNRG;15Ky1V-jc1Dx#jJCKlT6d#{>~ElkoZhP;Z>NU5{E5_%Z_;YWK2<|bx%Tml zUtFftkZ0x9kgZ=w4cQXakWUN=8kB)4pE?0@?i;f=q7HJtl;|J@6o12<4~>LVkX5}^ zM~*@1VZ4vX7DJxlN*2c9mKqwWX?W?4bqLkbiUY%>dkcmP8-@`8mE)G2WwNh)Xn~X2 zS0Ue5Uc9e7>Av#WzH*k!B_R+o`zE8NUtJ>rjDrh6cDTAm4zR?$$Q;sPreuNee&WB1 z;Pk~rfb=^qyhG|{?|%d|yxm0%jgeNc1W<-lrR-GvI0oV0tF8JDY?`D31*e5>M86v7 zSMc+ieLK*v!fW{Ul5Qgb8Z;r#2385@;lbn?*q{XP$}ixc0=^X!_|nJ7m5D5bq&uM* z^mqKoB{`CIg2=LP5L8lk6$E`}kCL)Uz&rtW7c*Y0%y&`vaetyJkbRmwSn=V^$yb&T zqwu3FMU?EbJbP5(hnLGk7f;k#Q`NwcZa|Rd=t?2gfy!WqSfh9BT?KI`PTfaD9M+vB zXr|$%vk{Fcm@9bDubP7!&v(M!5aI&-n<|DxqyetNvjJr7Aqr;rWfL#}P*>~9>*ljd zcAFI>q7i-rj<+`py!p$@*3uME8L? zqPT-wbwpP;w!v$G`F8;3#4`^_{Z(C%h9(=Du!YT6Tqvs9vINg-@8>C)w zZhAyfd4g|zjCJ7-&p22oOpD_rEC0*hg?|;)^?zKJ(nTRy$@C5Zfvz{m^#_*M#r6Cl zM4ZM|$FD_LxciL1{wRHqSJNR_7elZE9%s}<$cr26L&hEdHF1&Ls;9Eo?t*%_kNp?4 zLjIFIT#|mi;9q`5?*9)_~hZLmzHdI+kb`}O4ar(BCG?B7URZGXQ#HRFg@Ciy}M)e zOg~ImE5wo$(UMf-0Glw4dhIYYqThU|=P79C0q}v0zy%1}8qM$ZoAYnha>sSqGCzuT z*1WZ2>d|kYtg%+qPf1AT19V#*Sv%|A+c9F@NN^<(z~>F(&Om4Q#QpHtf{3MDJFhsA76>AQaEc zp);82N?^LdPJn%NoB};%bKFOCR`s1aqGm%vp8#?6BbR2c z??!ueyn*)Y^ar6!&Q9*tcDGa8z5R*QcIWp%nQMVE`4%h$%A8%Km7f$NlYecX#bWk} zU%X8zKR=aMe!l*7l%KCf<>xc05i3zV(YSytm?UUKFGP*#DxXZLS`?_$_O_yIL9c-} zP(A7F1~@6<-<7#24nb;h7>H1dV|b0)q5lVG7X*ot362n|dl+6hpqXQlyP{ohb`IgT zj@U_7SksoKIwxNT-o>by2Y+}H^BCq^K$#>*UZOv$ke8IDw#0(~S5oEQdKEy3s}QNb z@(kE56hv1bDVx_4`*As+Oj0R`=Tv7!g`S}~-66uQveNC6Bn0D4Txnx7)47Ty$r@oS zc~vac7->ts+SwB{kG1MLE4HLAX@490X!cZ|&3A3KzCxd|Q0^-h%71*sLcwF_oy2wK zX{lr|$d|{`#^!HdNcJYTfs?A@jEW>0$FXTB4tG1?Ft3gcVVL}`?ogktKzC7+b5Y0D zC(yH~VT#Q{0RS!Z?|rLirR=N>yl4&n97zDM}HqnGuaJ!CcE2@*X$XR0QDmP2U^_s#6WfPl)TBeMlL-M-W93Yk&Do5d2jIZYtVh0hXD1 zO+)aTC<(F!1A-X|1#6__GL7;TRN+lzu?wgIbqV%YkzqYlBV2om?i$==FzKq4K?=Beht-YwQI7>^k}CZ2ddCUS zU|jf17s6Ll=tAtxx@0-0V`1q^UJ^~(spYve@)r)nV9`wl3y*v}-XYs%iGahbDGo(g zal*|7X8!qZnEA&InE7A#%=~uD{N+!?%>PU?^N*C7|9{1Kc#U7YOfmENo##zsEh!~G zeExOhhtEuYNXDrV`=`z7*$j~{y$(ENo>D%|BsFOn>AJfj8woj^|u zDdFPxb6G8tiZba2it4LWiqPPN=S3MTl3aH@jfJd{nJgAb6LTpl*0ep7tRj0`NKcV{ z)LJvDkbkB#lddB7fI@={qrygm-^pdK$UR8c5T<*b9F~lUZt#R2i8^JYNRC zoyn3Ro1%P@43R$Nb34eMH8RhVR1W-3I-f&oQ)Tlu6wg|c!J!nT#PYTZStpXUUz~hn zWq+AC|3l%(W;1F0hYW6U+Klfo`~~?mVgacrsYbc!%M7}hb0g1bla{9FVKG6KP|CHe zU_%xu=MZ8_@oXoBv>ZtnQ&~7lRU_u+Na{&aab)ihQj)zXtGFmLhd3W35r;4!YZ{%- znLKM0Xgq3osY-h5+FqZFh{KA!+vB`eq;Go6S;lr~k|7rhsM-S0kz-PrXH8B;!MKvN`Hmx z7R8r|no*XTyuxs0lEUflhzqZHcOI%Z6!l#r zT7kEbQ$^>03s^V1D?tYATVm86upY@!C25^_YFZ(6rq5N*QGcN%6?ea? zVrt5lRQsOKKx}Q(&9a}6I2Fv^CC!x7G7DKI2x|q(T$d(mAiG|7(k{1?@J`GH6Sus% zVB%AMKd=-a6L~b}FAWyLSLQVU#ezwYD0`VA-h#9g7N@w&fGG5jLN(I#bKe^}0g$)A z8;r3Uu`n$kIf7Pr;t0NrnSTJ?&>$%sglrKpTm_y~SpA7X4=QGc2+UJJAXo6W@ZeJu zUo}Y&Jrp2f&ry(=>OII8B9;JB%3}$WN!V7>hkL-$+u2zrKM~;QBn>!9Hr8S>;eewP zi(jMwM<>yp+gVsk%Gg;L5&9MEEUc^4Ph&F3K!3$M7wDeB@*C7p0Dorkw0mrQ+qtS; z^Ei7!>VoSf3jG-gvj@}h)pZA zL|dSi5LSAaCT3aU8VVVKt}p`c?qu~us!82|wcNgp<5(+@*JuD}LbD2IhbXV}CTZ0ge2~XEZ`*zsM&R3srRt{zwByRkGfE4b?Q=CnQYU-rhpF*vh##Qb55X5H3jW8|tP=5z-2yYZrN8U))kXMCu zLVqMhdDOhqRiU%0W6*LU7Ls%2uwOg%Yar+chCz_t7mEhF(zH2*5%X%7PFLM!kG8kf zEoZTScK+KTzv1!^=W3U{MY}?}K}Q7MJ&50B&;Njxo|J}PC>}$2!x4)%Qbilrh>Zhq zAyeZoT{TGkYkx*)X&ND;MabiR;DI(bjjIC`TqED8#k|Kg9HR!U*(Ym&t!6XXu<@kU zu8-ihPB}Z9;M!75mOAOidWA`p)+>CDus^Fj1DW%s*HIrhwq7|s*+Tp*tyfOn5V4aq z`4JzdKY1M$ia&5{ZOsWjqm{^?hYQZ!?A5nkNF3Z#x_=pZCMP(!vJ-gvC_U+}RlZE@ z{2&dZkmxfi^iU*@ke29(_@n$_aAPzt(qeEJLKi-zhb2+jqz2+UjEKETxiIM&`)D!( z?Ex$vG<&F_Nr(KjL9s9y7Q&R3J;p0+FuKuTFyqQ5?vAYx+^<}6#xJp-bQ-dd;%6}I zttFb=7=Jme9HNnUcLo{>$3`TN#gpo34SW_|(VNj1Q&~~hKI9nQX9&JE!F>3JtqC&p z$XxBeC-H^!!G-P`JR#S4JqGy_ki2=ZnDk=VM%75s$neMNWW>}0odFJX3VFwNvFh#A zwSNVOZsTA{PnqZ5z_B2r9fzQX-tpYQ4E*3NBY&cZb6q2HI4b?SZ9Zpy6YDJip7c@Nu6tW8oogf$gWNIpnB zC_quXt_L)6UR=(Kkx?y5$72S{-mn<029kbNLk)y>uQhbFhdQdNdXT)W8jmUk5?mrr z(|@iH83Rrs?x=y0pw+3SVO2p0BS#oBH06+W)tH26{9Yg?y`(@qSt6q7F30bLpaDfg z0p^xY$x;kewT8l3^>e7H>8(eOUz=<^Q#Qfr4->FO)%9dH3bD$aFe@jLhgor@Hw(8qT#2=t1oXI7-&7hAZe&jiUqDkaEA~{s>VK|e{`bEUi+RjDewB%vYB(g8m~T` z>Q)R&n#}G-F*(^lG1OX&VKbuu`4bJfS4w7r6r>0v2UgNVK-lb>W2aPlg7g%pD2dkrWC_m#T0^y$z|#zca2UMOq@g~Y#M&76ZQV#uM@llb=SND#J6}{e4)1BP&$uZG41-e5-79IvqH*A~f_bg?jM*39C~SnjWHnLAk-{onh*8Wu8|hTT0vB zrZ)fs>&Vsdp?||GFg#?&*8w@zMTS39{hk^EL^Q>K)lfh!08v1PfoMZ()sdqKS98#T zqj}H=g-qN;a9Haa7Ke`M5NuCEX{!#6wt1GUvBe^SReM7DmheE;kj+nz;5AnK;7ZnmJCJRuH*Vs~6yFjg?D)qKl zy{y7`S%1}+ngkkMIxZOXKnobdW>EE%$ZR#_QoEadE%2vjKM19B^7lP}<5~bmK0Ac~ zj+3Y28D8u@CilveAQI`Pp%`d4JI!ao2r-c(sDEg2_WK45|Kyxs?0Z zjx4N7{N0R@#1hSibhq6EFpBPrM^6S z^M6`FIT0_r*}*v~=G)2Eu8I4+cC9N4(dVuQ8o`ykxfO)FL_gAk_jf zhWsAr83W{WTTy4|@W2mfIX%D>X=-|xXr8J@4-x4#jU^%hL;B=7;uRAiQ`VG#J_kQM z(h@>sV{4qhz3r=R6$Vz~4}XE?nWWpFynoIPB%W1}>%FJV!Nuw#X@p4qV0kN5O7C1e zjQ0LwxZJQJsFjUgQwL2@K~;zjSB0_G6vUSmNk$P31~fSUBv61@XMoCvA8?M<>-6s% zbE-G?697#w3J1iLgdjZz&o8ShUbm~DXP!TNfd?b(Uy@{Y^Z=P2JZRufj}+R0fPWQo zkSqf(IJEVL`2q3zlEiv^$nAVWPheC826X7q^uiVBf}9gHAE?c z3t|(wn!KvMYp9d=a28XT&+bR*E`N;ooSWHm$TudRxk#0BNg@X_S$#1vy!t0<)M`(6 z$e)vcqG!!#&#q}c%|qJsBrs+2UIVeq-QEViw%k0admye}#pcd>AF`yxPsj#@ zB_$(6LQztRjlb^3@bnJF??9op|#~!EY*a4+u`<#3|22slG9}%V8zUwIEc9|&U_C`_4 zZ8Jrsm^N&Cdle4~IR)&Q!6~Ds*GF4h()%jb^n~ns-AX8Y+`H$4w}0Y;?cnF(gY9&% zbDM@pv#DP!+5>(OhOC_!^Kg5@WflaX8 z$vI_ZLxu|@f_7Jasbxk?lAjvMrB~^$fEbV79a%E`Qchh2U4C&BGws>qa9J z^Vt^TYa3_}p#vIU>#M3d$i>%^eKUu{p-xqPkP9}BzTD;Ew%s_+HZoKzZbd%MHsTIa zQ8nJ3$Ofk%T0xgT@8+W+v%542c@6h9wLLtscLIlDqdFDlj&&LSOO*` zzzy9~Coj~l7=Ju_aGhaSy=1IYv#`$#jFSShcz8xekQTgR1pJJ4%fn7)}Ej z5$Hr=#qy$oU2(mzLcI4XpmcRCtXGuZdWqp*chw$=K!4`Ld{7vHEIJ6`qFCM{;?>52 z+QTGqyu$)?f&?$I(BQrqOdduGamJS5&9yt!EmJFBlkV8EnkF}^Yf3}aVMzt&tO6LD z8^cu}?baXe3L1s>_-?c~vkkO3lY4!@?eqcdpGY6jOzQ(?R39+mYJe8MXs7f6t@4NS z@vn0@AAgI7^S;F8OO}DPLn0mYImtb%Hy)xM2H;e<8anQa5~gm zF#TwW91H61dTvPE$m@?tdb9R44_-PWvPYIf+49*~| z(&>>fmzy+PLRf{NrpkGdu3si&ne&IMOa0;MqCZ@n_`QN3AYt^#H)1KnJvz``OH+RF3&Ng63Pkw}1;q_gc z6@Q+TF)KXT$gFUD&&hAc$xnYGPJWW+oc#P= z&3>C=j7- zLp(VB#GF-0&KZq@@6n@1?x}D>*(rEP-^@P+e|~n>bCYu>{J&LtZ3(BR?n|!jLaa+lc~w_g~r5)5P>$$Gw3_0(yx0Kz~2E zU#p3|-IaIt(i;^$Vl$Tgo&{%?r|du|j@SlYSR%*mdP$SXxi2^1LTC2&Q=K`;)i?BP za{yUDfx)qJs^Yjk>^mV$6oJ7@w;CF@m#fH++?QS_U6PH&Zb9KUsc+{daG7#0ZGTE< z3{P^7k#HZA!p#r>7~m6cJ=em>G=JtvIo(C9lbLXJi;S ztf?a!drYH!qVkwqa<13-!QLYj9R-wQMY4i!)d_gw(|pn!)RVkJBa0gv8h;r*DB3Z4 zP;^+_jvHeL1;@q^3eHkp##I23z%GxpRyEXDN9cy+xu1w*-c`4(G|(j0=ABG(aso0b z9`@9&8*PbN;=O>hYfS#%VcqFwhC*1I{Y(_@Wr31Ce&I4+AnK*jew~UAjICj@#p^s{ z@d}cIz^54EHCg9|OV=eBbbma)F$_1}B3`mV3=AdcqBlb1@#Sv730xApoW@Cpur>{~ z031NHDm^1MNG%(~416>HhV@ia&9?}XfJ!i308C23@ZB=Ml6eB!9HKk&5ZgDv3xWBB zRe=>PW6e?v39uvsY4y$B`_LQDcDggiy#ab$QBbmt6vzlyAv=xS=X-9A zC$L1sNDlxk!!XB$huzqK@`(cM zTF^QhdhBO{c$Y|_;3y`nlmSc0{sAC*VYe~ zn$%yYJw%yXA$Zw*S^p`(6GJ1hyh> zwuDn3aTI(L+>rd93BXr;Ci=>#a5$0?0lV_VBJg~29Dm90ix$a2RmMCq1y(aJAnfrN2X*ZZ@whY zRqhZLGUJ+%`+^?6V{kXoRV?JCI3lKI7)DL@t#@cX3~m4z0P#<`8-2=+UDq-Qm4ekM z$0wemIe)EE#|XeG!#K%-N6{)%`j;1XA13l3@o9dMMX+vOzJS3f1hH~ljQ3;Re zFDpHwpA(Ph2gD=#1G)YJPPET8)P7}rE4-k2tbcg($7=fnn88u|eZKnkD>Vi9rdX!c z!#k#H?=UZ9pw?VEophABuG{(nZF5~*5g3F9-G(<-@yA(1QUcjJpz+rSsC z@gscEcJJC3tx?7ot+A0W+TOh{+Ut0YVt-q& ztZ3r3nwDmmZ+s?1K7A^*B=<4_@bsZ12A+2M7GdzT#^%%s!r=DVv76zl(`wU&(<)3R zYQNM_(z zXZ42}j~OqH5%&sW#EWt$M`|{2E`Lvy?8LFe7|v2&VE{MgCnsDLSCp0h`0D81W4|v>8<+Qntw0w^wZ)O zn6_Yvnt|b}_1eL1LqpBTaMj1P-Q7nTYFdV??(WqN_B7NSlyoj0I6(-O@pGzG$#_|2 zeJpwD7WWCz=T^oM`NqeytAkqYdWp=j8Ja7-mYFW6Iy4=Z1R6HGd4pYZus+a`RYVl8 zvBN^qa+)M+CL6nf90$F`rDQAm>Mb((I+2G5mbz<;mSdh#BV94eJW zUr0YiQ>&bF&2oPA%fE|qo;4H&e~4`-f;a$$t_vlt5^VPFL?zf9l~)NiJ3l}r*c{%m zO0d}}p%P3NTBj0h-hbSy1aGAhY>s~(m0)w0QtpwBwOFvJUo4s&aRT}zyfrDUpJNo^ zSJ2O~u2TJ6vwg3hyVuX%>*wzEb1TDBo6WCqkK`wB=6paUG87rjnFs_EhjgW)zYcF1 zl2g)$;Tt&}c+BbG?D!(>bdbo#7kK3PKpmh!Q0RqF@IvJ&Ie+W?2#?U@>&hmQ`;YOJ z^eq1sp0UBY3y;aQAH0p5aJ7d5)k@T-m}5J388yLjz|B}2X@T@QNVT5aA&nsjRD7My)_^=8p92woG>*F&gyO+fb(Y zPUQ_isowF1r}pAHW6=8XDPaSduC#$%5~D|-7(L#Q>wl@Lq2{HAnrGj~f3^7r&dI`} zd~!E>j@KLLIgWpXp5yec^&H1#^c=?<={ZjB^&Gd;bG-eD^c?4DJ;!UR=Q!c&jZggI zZA#B^areCEQ+d_OlV3-*@Rfn)2H(~~5Bh@CG3MIJbIK7~lWzVFoU zrz_6^?}+UGH#rBqAlFaH^#h3`6mmsZD8JYh$}yT}>S{kI({QME&NCb#0LWo}P!W-< zs2`MNG|!12)I076)#Z0y@H;m6AvI4`Nuvozi+@MsSsqP@QO!W^8x<7!Mp-%Es7lHy zDl~%fPEq1I0Nk!6Qgh)cQa>rl0s?O-S8bZAYH}wYBT@FrRCfw8V~--kVZICCC18Ti zCMxo*@>MVCmi47SKOf5Ij zo_~?(`BcXk6i&3D(#sPE6bKV7c!gyqx{y+^iS|@AC_T}^ni;i{&Xk+cM7#<&b(U*3 z6K6S(I?I_^XSsk6OOSV#vlGo@kGN!gxp&1$zz<+KFdrQF4L?gb%zQI9o-?<|@y5;i z-TYU2@jSo#WABGVe0eTWxi-q_TpPtoSAV{aR_S0}sR~x6na#*4AJ)rfuksy~s$UyY z{cB?*1#IK%HL$PN_vn4TM|p{}QAXr!Y$9_uzPHf%etp+JujqO#6p3Arm!D3S=`sJA z&EJ=PO?WG*K`TCnY&C?4euqtjrvIUOxvPQ*-ctlAZJ%hkxYL z&&;7ShyyvOV4@QEw2G3N1VtE9>_$T(OQyyS-YRJI{}EdKapiI4FLFfrK#nK`bO2}q zYW}66=AY!}d-AAGu0NCO8oB;Rt{dOUwDFQab2N7)ZHHsZpYU+6;9(se9(<>U)iO4h z{kyTbJleqK^7!6#a68k%!=J}=(0{^d)4?NZI^e<5t&p1z9*U*|cDs}wfB)CfLtk`-a*P%hy`PxH5B#4@1GJ`~v;n1O zU^EX@Y7*rt9Lorp3a865S3>ur#e(}t3>qJYDO1L zfLJ!QB^nt8=|QUrbISO<2&xH~;N;k9E*73T0u^ep`${NtUZKNDgq8K)D-?DWGTnlx zxNJUEe5ku(Hw@krtr*}IK8J8wW z6S-o`zZ0(5a>{eXmiYrb5nA3Idm^;V5}pX@LhC#cTEV?IaVv4675zlwgq0E}$i`YM z*wil;tpUG?QsTs*v^c>i!ml7su&y$3qI>TaaPJmy?-p?H7O*nnqJL$tkGS9m0#l5u z$V6PUENPHMWCRrL0+Pg{Zl)N^nPVGWDAY5$KTRY?o-p+|7B~ygXsnOWXlx#%(fHM( zG@P%C(rDZ=Ok;H@M&mogVtm;o7Q-qZixI7k#b|66j1iR%#%OtxV2oCGqhO3k9*kkC zkt7(y`kuiURve6x8-MGTOH7Q^j_o0dzDBoEk+ue`-Kq2I-5>_EHb4w$by5qLo|(e! z?N#Tmkc)CXGdN{uiR+`SE$Mv~YkG3z@Vb>y`1tVt40yXU;LT5T1{|l)fHdl!P5olg zn(>R9)ERJA{tWo*MBTT`DNXYJp$p0!m*&)V8Z&pN&5vA5%~mp>7YeUs*~P0C}ZoVA|ui^~*`JuA;+ z+rJKvZHqki$-SQSUe9{3XT8_6uGX`@E)j*(n#55!iQokxIE_^yIEcmS=>Do;oCJ!v z^+s*(s(%R(G5p?BlYkr*8?Am}%!Y*qoD#L3WVAWmSew(8$82+(w%Zq8)1n+92-Vz#iT}sQ+oR_97{H(i3_iEW;rDF zZGv(n9>ZGUoEG~C(>YBrlJRc})syyPcbZaI)qlPk-C_Jq%a+97Bno69&<3JwTE``U znl00}S+;dZG;iB9wXw3T56mFkv3kzHR)i>JcCQ0tJZyQPDZxl%* z9DiY3CwHSZc)Nkx;QU9Z4KD6lZE#*jZE(Jk+Thc@+TeC-gJ(aH+TicB+Tbl!8*qG> z)>D4*ETuMhT3&5%^6RJ#PDHiAyL+|4z1rYjZE&wPSgkgA@f`qhTYvwz0pgxF&eQHz z>_)M36)SKLcw5euik`Oa1nPFhr*7j|)qgrgb6Vwp2gq&fLgrWX?!OA;w)No75f@rt z5)X+7S;U3&#`($|?DTmq2Rk{#ug%Ba`m#2-yY)QZxI9_{Yb9?6+ehp05mxnWePnv; z`KlQ2)&~gKhN0C^>lL|vu4<_DK|`(g-zQAE^(q}E-THht8i$V?XdM3f5gLb=cYm#M z_^XV@;jfJ}4u9Tj9B!v^sQ*M7hgw?W@R4d9{^W{=U4BtdX&f4N&oOq(D>**@I!cbu zqLO3pUdeH<OUWbmQCX(0JO4cOheC}H_rdF0A^b+zAeCPA4}1eoPcJl51wHYPJclRuBOnl zuP#q=?n7fh#)$r5lS{3uroRo6ptU%Fz*8VrgWvCbUA z)W$UGNoIslq5*Rw3d`%fm4AVwFu11QG@Vm$W?i?1W81cE+qOHlosRRycE`4zbZpz{ z*tV^c|5SZdbM2b@a^HJ0>!EcdYnfDn zugvX4NJDGjs3I?jgR){+?+tn+orjSp^g%rwAju}Whno_e0pJEthfg9r7dPbwueI2& zv5vR}Zk;uUEHThNlJV(m&lc5{(DL#|ri9vGv0hXMUkg9NNdZCKQjng{WnN;Y*d(>ZK$by9k~V-yqZ(`Qnt$ z`B6VHYNzcR5_{EGq6+D`$vM zjZJf-)FjNSvgs)|rPaVHiWb2wDC!k~MM{hTge4Kqp-nTYY%kUZb4m57#Ls1ho4p|; z>-s;)&(;UA{*VL?1VcIDyV(-;NoqmDKiD_~ewwiMR%krlS{mwTeRh4m!*kKVx-XJ` z0x-V8qVO+s|6OxR!L(s}T}zPauO`Oy!=J@D?7Q0Y_E{QEyB72IsuqvlXQ7V59qKRu z5)R=di5}N0`Q|~rP%035hm57;&?~oz#63I(or&>JEACJi!bm>g_YiwezHBz&@98Cl zEkl)s;7-SgxEQzwFI*vVmNb>ZOLvPM+J%?z!`hA0Nh#SNr!gn-&4US?8Sl95{4h(I?S-58{dQ+!mllLW==9>D2D$6jP()x z0&l0~#YU>zY#TK&)UHN*9_k+hk?nl-eji793=781coo&|2|6-Ga3lN~-cF&pqy9s4 z%F(tCv;H2g!+>2Pxf6NZT-S7%5$FU@0(Z{O`;vd`e0@52xO5RU!aSfz*9n?tYU?}R z3fBbwLrEcifR2G*CCHLu`ufNOxDc@Kfl8+si9G)YYyMKwXE7+=gs>?Ib3*jH_w8^c zvc{38abNN(*2J@>VG%+5vj{UJxktxKTA-{=;=}VbgkV7ru%B3u+qIq}?RB8v_wg;miK42Aac)1+|3(~dsUHOZMlZ~|bu+oo zPXkDZe8zsFhwY@KE1#K(C^zvDt?v?(3U)Q4Z}oHdOC{lt*$lxl^P&OQzct6kA>qMt z&A|@mZeUIUn*p42=&UeZt#2T0a9I%%b&!cGuri;Cg}vP$7n5D_V^Jw|1kQwe#1Ud6 zha&%M%SC`(!B<1mjZSz0+2Q^Zr}s6-p@f#_DuH^=-|WcZ5vJ}G2^U*ZWW4=~yS&2A z#(luZN4AW7{P|G%%3P5md;SWS);qokQMn7pvp2C^s%ri~)S*TMJuv51 z5s|FO2Lz9lV&TB`G-63HmrGoP>y=|oA&D~$;%X{uca^qJtOY3m(il+nza;TejNDSQ~f}Tu2%Z=OkP0v_zmb0xmW<(%1fka&H{xmKJQ`0sE7no}|jd zJ18aS=-JiKP+d~89Ab$y4=^gSKfq4M6j^TKyuu-uN4TkkbqS~D!?GI)vIo{u0cl!c z)-B)`LtlS7)R8FwgnszH@E5;qrfDXD4Er!(out};&~P3HZsMv^FN|K+9ptQ$vrGrh zwe0WmMQc*_#ee<*GFv-sl1SS|A%Q^+UYA3?4-IT4w3Oyy?obUCqo2Y+AVSVC}e3S2N!Pu+#rab%(R({9CCJg@3NJl zaA<=6S~uWH#fKVPdigDYF~RkbMl-h1IzpmKaAFUs3d6~}5u!qLSD-#rd(0l-53L!E z4wJ9%*13k|N1P)3alFqP!GNwJ-Qw0f*^t(e9Qh~Yf!1$Z`)cW^cG28+r9R7X_NmI@ zbwex2Tf@N!SbMl?M`S9_9JT{;C@!6!g?sxU2+S1gQ}%wPd6YMGj}u%!1^hIW zKil-{D*>OX{4Z9o_dlU;fPu@f4oGz@`TpU|zJhVO zEBK)l`TfB__0Zpm{JR&?QgrqCarKqvOeTWz$2UGFzO_}f1j$ZTWc(Rj>Qvt^h72f9KEQ{ z7)Hf|7#wdapwwSsimf+L2S42p=t!X?;J(+>i@;{)jd1Y`bH_P0^r*?)-==^aaL%yD z4qC8|qL*yksInjQ0rUYfMO_HeA+o0Sax3YS*mK1_=B04wgiq=Dx;-iV^^u=-aJcE5 z_?A7=_-Mndcd^`vJj>WMEq-u^3o!9G`YE^s_%b-qD$oCt zY&AUI)x>zRhCAXzHRD3{lmb{)ouQnQ~bSM4ZS6fR|p|kXq$BPX5~) zh91SchzSe_($W7#m)MPp`0?w#n$+B6_8hXs#mLV}Kck^U@({)}O zVVmR0j9`?Mgx=ZAJH2i+;5lV`!lp-177lI$nfS?P4*XarX%aJ}6HbxUOgXnzmkB2U6U48jte zdw;zdA`7KPolP@eRI#T7XNjQoI1icW)r+g5t0%w^Y!WD||F$I0BvX!NqATku&HoaW z#+%T(6f`HuMj|Z%O((Uz+r+Mu9tkZnA%^^L29IXU&D2sIU&jOQHpE`dt~tZR;4%6I zZwbu(*X0>Apko#qu=k}}Ndi&cLy!$!JQ`C55OPl#_()G$v_DRVE$|FEBe!FTooJ|7NQ|P13zx@JYxgZUF2Urq*9AtrBWH}0=Dj$(zT$+qaR;98 zhUqnBF=C|~>r*=vmj^M>17AkfbYh{(*}Il(LHl${(c)zSnurP534Sa+JLxmmX9&i& z!|2-1_VFs1`>{qL2%%IBTYnYD5b3vBgktBEX~4B0pE2=JH~#x+(VqlzMR{FH4>a?PO}FN z6~FVkh2LKQ0<=TW6bXssavWgS+`$~MA~wE$;Zv`ZUf@PtcY{I#>u-n5!Wd|1WKLYnGC#nB7roW-c<3#oo!MMCh?; z?=RZrd=^@EXSf50|3*5n37U*)>W~LRE4w}SuP+%;T~NTyFq4|31*xrf{`$74D~--C zf-bKvs;VivKs2+Qtw>X6R{$m8MvQb05mq5Wq4kR{sXg$F-7$VFxmSRCcBPcu2MM`E zUq;L@s4SG%?b3juK=gz`nMOL?OozYIr2Pp&78AtD-5*FayvgbXM5}BD44NRuPmPYq zLzW(J-LOwNw@MK+{rlty4%q_8aZta&Dv7WnS|u;Ms0MZCcCkq$Phae57-hLCkBUm$ z3#3=-RnOh_6xbh9QZ$aPkX7Ta_5T}PgFXu5tjVH}Tn=7VG?HO|7h6)@Wuq&ar1kEx z$imA*-mSPT2V@0-xdgOfwN{t0y28NEcL8LX1fd*Gcc3{OZM~Z6ygV$=RAFzuMp6Dq zOf4J}V}gR*-KQTT!V3BZ9AUrz#x&tw!A6PK06-e+Bpq@tE1`+KJWY#3EWN{WH`ny4 z(S*xUb(kZ&I*cI-@G7};;=o~HSi%eU80`EEV3A<^B7EB$mA3z9Jq1SO6M0x}1^_A* z)@yzDb0oS4cx4#01-JFGYEH}-A12X^apxbNX~OsCH@$fFZ;-c7DF* zfHyO4()=^#8Tyn|8&7D|{KKm=sK`hXXt4fc;N`2e!+SH z>xx2Jj)FFrcYU85&uF5y0a-b>(M-3uQEe)eHwWqy7LiFaXtKWD>HOwtE&c!tz(^xdfwZ{ zn+#KCIJDh%UDTrnsx@kf@>0h9< zoMs9q25k)j{j}x*5n>GFhLc;NH90~2hx-O6nJNYyv|CD zwt(Tp1;#28{k}e{s*h&P8T$PQ$Ij#xa?=CSyzb>klT!zfn&t z;REOffB)2ribQl7%Ng%-&2FM4d#ssZXM*EGkJa(>bLhH#8=1H(Drw3oUQ39(HUvbT z*r5aq_`Vw;1q<-^Eaz<~1UcWLS}6%6M{s2dykAE)ntZ+rJN=esou|%+{;N&5(*29B zgpVA+Mn|<B@mLgOoa=z94YwEsnxm0m9n>?di zs*O;Kf5AynQR4+G9;I$bGl`jgFZ*$@`O~?0x=`WbFHjV!28UGF)2!3-;-0qOr#u@J zJ}Uz!aASWmh$5CTFPOfL-zS^LnWqub+mRHY4Z_1+FP65h3!ecQi!!o@mdz#In$_pH z)5%Yvfzz+?$<|jdNPic5iu{dmp-5ski(LiYdSfn&9p?Dr-{tE#unx0@V1@L^mg7nA zanQ-IlP5#)+&emN;~d$WSmzk6L)~TCmAS)<#=#7S=VAJ>qFg+afBO#6Xd;2*A1@^U zN+LtJ1Sw*_i@q2Bk)D@*Y+Y_|;c-BS@bEXuBY^1P5t=;4@SLoFJUOu)o_N1|&Zcsa z*g;OOd53EJgi{$6>H!@*6mdjt??fsKO2{mJe7{S5#^P3j3S5KXnEOp8rvp@@+ zKTPj0$@Yl7Wtyz3nSPK>P*Yx;8I}`Z_tK7CN$+efpDLchqY~lDQIi4&sS6x8`bPyQa@=!ic( zn7!XOU8N zxkyCAt)6hHp>BrO@#7ynB)T+NP(NW^zEM{tlZeXd$}McW;$vO1Ku&_f1Y~>kv1Uy+ zHzHFW-^{&#%mU&5NQ2nJuX5+aF+rLi@eOwQAe6{6dYXo_ME!kf0Q{C?c`aT_X~G{=P2&soEvJLLjOxSXgHw zy}i%yMk~$rDJIuCfkX`WQpkA7JNcIt=fVfoYv8w3rqHvI18q+ADKl*$al$0H*mv#xytgBm@6eR=eUjA+)GoqJm( zdD@HQ_2;HMZtCRzv)@_x2EE4#ztHs)#Rz!7v8iCD^)hcrpeckkKE8)dND2NeN6%OZ zJ-3~&w)W45t4-z^Yw&bNjzgJzhbxfaOXPnQI?TGZhpEbNh@Zqb{$bZ?RrMmw#Wzsf zd#3r5WAaFo8xJeP?lh~~ zvRWs~V&iq+9E3Q*qdu`LA2d69AqM9lh#ZTr7-%v8#?_1g*bneA*;}TX!NP&Iu>8Qu z%D>I#7Tx!D3Jr~BW$VVau-t&RvHYN{|9NL;`?}W>-S7DcSshg6-){c&xObt$Fk4Jt zPo2BCxzT02C5vq*hNO`+^_ta%RS(I|r3F(sq^u#;Ht^oZ-fYJp?vubT>o2%}sXQ;e z*<_60e*u<>-o~G;yV(!2({C_Rf^PJEj~JD2nQu#mPl0+xM!1=Tq|&U z#@*<5#za6CXSAfe$jb@tRNhL^Q%ZlWavV>gi@{|l0pkV!M1>#c&Rqkk!9oH-{0WpH z4DHmMnJ;iM{NgE{9pfPN{jKocp*q0iX_^DL0s-piRn3Tto-m#v5zM?fylK?3F}!{) z24>@9NII6gy_Q{!dR#0S7R9i?BpQ|59hbxLBhkcf@CsmD=47Rm!7K>H6J8*wVa9FR zf#yVJ@o#ejizXb%uP7oDZ|96S#Q?Bgl?gS?3AN1$)&DEva*ZR2zOz4XvNsOWc%*v( zNfbn=rz-#1`w?zMC~<9)b*4BuYYiF+`6zj1|8f{*XZ``+y9%z0fQXnL2t)}9M>NNQ z?3X+fF-hdc)j4Guegd3-3F`7O1uvbWon|>ec81z2s`w*gP)-O=;U$6bvBoin~m>D?aro7@& zsg`dtS8@woMp`6E1n*e{yd?Y_;$9cYMI(I_4_s@(1ivz8_pcxx(!^GRGyD?)Qh2r( z!7^d>pmQ|F_$9hgDDC(f`!>+Pie2K@V^m&R==R+YJR_$3YRtY_1y97v9upHki-}*; z(m7@xqRj{Kf@5{jwr$ELVz~!g(#@uVo+-x6MY^JEsS-7eG5y_aEWTD~55)Oe|0Y(sx<#fts3V5G#?1ym4-v$>QB0eseetq$ZENJ4xU^hZPmD{&YJpMoQ8MwPfA zi*8M2+Ebnk=Vc}(poo5fV4k7bn|S)mxB7{=J0`NT_TC{m^^z6r(K90gppH_GwrjvT zfspG>8bT2X(Dg&%S?-UMO>rzzK~BT(=<_tW;x-F~!;tO&NW`)jMxP(!6Z=w8LJMp+ z5kMZubPnxx7);9DMuPHr`V-@DKSno3yPYHxlAz5DlI4s}ERp35%Y1{k;{TEv|9l`J z(kLqy3eeA#G=F36L1^>@m<|q67zD1mrHVa{+eHCE&(P~egk}+03i`^pm=n8@X zk~brN2sF0tj7*SLhAw_B9(XrwgWWa=Ka!za$cOJiPZv6D_0xe`Ny_^QJ;+w@2^Yd{gukA=zT{~?Fw{(AVv z@U6Xa2q!}%3Hh=U+@;GpK?-5st_pFf{jX6_6GU(k`ewiaqU3zcniY4(8#5hnpY4x%h=1)n=2t|mfCpIzvV2Waj1mH*2!=;RhKA_!u5v#SRRC%^#8^x}c)-zV!sSnO9x^*C{J9HG)9Cwcv!C6OWf zJGYB-&K^~EUBW@UzB?CVif#h$UZ>h!deyiU!TV1FYliR*!D%hW1!OW zf2E0-Z@)v?^dr|u7cY@(ip0e7Rh&~mm()v&)7;{Th4XPWQo6v}Y8qIe!#C@ww5g3( zJ}rVK;6I8t7Ko~}VBc4U4)4{&6D%|-7(=H`g4DDpdX@*rhq-hGhVLVp8AJfNV^6sF zrx#b1lhmue_v0BUAW|t1JXN+M6T?Xi8J_6(f>Z&!Pd82}Q;@gT~BvUE#q-{a#6y#;yfMbFZ9Wh&{$CO42NE z$*a23^YMsPL+@M-c${oPplmMH-lA>JpSyoi3K_r9<0HHyHU)4~N%ijE_ueDyil225$;@A*TXl7V{lTN%?|c>!F|)i5?I^AQsQS_Z=L|`PqyGO)#*rZ zG=eo!>6_FzeZbgqlQ_d|C@w9I*6|(!HYii8bP)oHI-9bAu`ilg{|3wb(t;ZZCeNDA zphIsSb$sUqb|KCt*0RfBtTS}~*#JFnYU}sprRUwi1XYrB_V+RbXc|J$z?lc+3Lr0k zU-K1+vWTj{_!D!D#QOsx(x+6p;Wn)PdLcOz6lauRlVw$eLM&W!VHniEeRbvshLD5# zVJ4aKMrQEYMCMa1{u9VFXHq7e!kS!^!aBH}Ai{)b`<#+|Ejgl64QTeyHlA}Tm7-c; zPWu;3@^RmZ_vLAczy~d}Fp3wLWn_#HfSq%QGRIYI2d|gTD#Za{w}`jZO}QAx6K(kA z0yoCM3i(|f$!)seFT`NQ%!4Xj_)AA2x`y?&geJ65NsjxF+Pj3${5sM~f2a&`>cQ8I zDalaV9hJ_;b#S3=>Ga8?UD>T&R5fO@Bc|b1OhW`mhuihUC=h{vGGDY2PZas9En*GI zjq1b2Kz%6>=vxjj`W{kt#k0ZbW3O#&7?D8W4LO6Y%CBo&5k@Qj=*X|iUxjI44);)Z zvSPqAG2jV!49tIulxFsxPvvdfHg&K9 z#`ei^>$Aa-XBu~7+O0|N!t&R@x!*N~m&TIo^Rdma_;#`Y-f`Wg=x=SR#bFWVFG}(n z+34@tZ=w)wL#p9#%hd;#O2JVfdbY?@@?k$VZnxHiB1WB8;n2n2!nD%CUPNjqY}-60 z@K*=kyX6O-2<3SHwiai@D+Q1vf&c|OEtn$$r_Lv-+N5>z)++_%<*wLC1!fWCG2i7- zrsOwwq2ooleF0oF{^dZKz-iv| zpP;Q&!Uw-qVE`HbiJd=NMHkWs4{W|lzvf@0v(Xo4*Z}kTToddUMLh`pQx-0crJY}l zptD7~R??NtpNSqwe%gHDU5Rea$-_Zfog3GT&+ij}&#&dS?e*;)t=dI6HT-iovF}Ky z5)h6W$EL;?y6qQBMlfA!yi0bFnj&UbLR|ZhK^qKH#Jo+!i&h>lmuWj9H6)XB_>}&+ zv285vqJTIE*fz$D8v_z>h41BqJ0QhV>?eK2dd^g_rf0n)JfZ|YiPTx-30#GbonChP zGRR@TuWk4G!*WiXy&tW)M3ma82eK|eOf+Fpfgzj0M(0+zLhEn=JOgI`XL0~X+pUkb zgmQKXtT~XKU)igwY2FIfN00?CJNy~>hI6D@(N`m#++)SvWp za~!kEzyE7~PXe)R?AafrD*}YISHd{BQz#q597`tCt=C4wep^4#ELW@}`UuSrh*4IX zZ9}l%#gLM-Pja+wtC7O>@+wJnLN0K0>}d-B&{F@Cfn9rs;hzh-1kG8dMFB_qASE3t z!JOoqPZFXJ48shH-Zr5G&of;S;ZW!=_0v(C})6pAwVEI{0z8uKa8$I$KUA zKNGH48cl(ZCrngjijI?@?;7C?7SP#AT?bqdu^)~%yxlb4)wp?x2a=vY5rA_V@rTJV zRs#w99Ln22QG3$eb3|kTrtJ*G;h)X>>6rfh{^?u;b0(yM9Ol2BIu8zB!2O|-jrm4G zlNv*lcJm9q?i)GPJBsarKLg@3d9WWby0#$uJU)}61&U&x{+#6C-?rNb9>(PfWC{2) ze_4?d`Z1zkn0*+8L^48Nx>Bc0=%?|-3gSE@y)HZ31rY#M=Pan|iCz)J`tt%b4dn<5 z7??1DJbnKjvw9+nMEYJgK&K5G^v$T!md|Z1!=L0wi8?m&3+&fMpFC!66as>z<=SMP za#s7R$HwCBOP(JHPEKWS`qQq!?dE8Dg78dI2GngBK`7#IZxI( zWsTCUB;U_lBlI##C}6<`O?YmDqVVm_23=Y}u^ZH8i8DUdcl)(_>ka-F?r?wX>uP65 zPS{R#m7kmY62P+p&{P^xQb6<*Si$X$tI5B(B)G=M!|$tQ7hM(P;vq8lN4#44#R&N> z6Aj_E-!1u1-9yF|-Aunta7X^77NwAOf?%JGsB_+S(HTBDEIjUm^cw@xTO)jFa78*2 zDpR_gcWX9#or?@g!16}_XjdD|PB}b%U|?WJlO05g2DxMpuslg^j_{>K3MCCtsF4-g z+e7jRe|?Tu7uQJiw>-M^0E)@YDsTG*0i-jEoa9|gEQ$C@tpOTS6KO!!o=He3>?4f0 z73md5q0GZ&4kQCP0Vj02b389}^VS?HvJfWb@^eHZskR1G4e0Ya=vUg=Gs3HN3L{=J zewtdXLO?{~qct1yuWB-2?Mew&Wit
=!2$_g&PG?ZyKNoonRtXNfJhC!D|fl2DbT1EJx@0GFrkBTiGF6C^jM|^C+Y6oY7eN)N zcE|34ajijDBzv&Q4-&;cF3T0+CH#_1GSn&~2!MDzJrt{n?Z`WFg|Jnb|HD7dAb1ll zGQZ76p#;N@xYJQ+8_ZDN1X(lK+PGc}zK_Dn<{cH?4GC>Pg0Q`fUt6`_y*Elynhi2( zl6p!FFo{uMAbgv*rJT1ttr%wFtC|%3TJkG|*6+69 zIP@xq8Rpmx;Kio4t zP3|e|bCpmXo3?ndU;-C}l9|H6y85ao^5jcH{7w;T1G!RZQcK$Co8Ht&!8Yk125{YL zq4|??Nuz~X&g^FMX*Ik!&5s(7oErz>^5$VZ`PxUIQ^$Zcr%F16Xdm8XIXW=G^x-6y zht$h5;O9Kn(>NVi#0(tm=WGE$c6gG)tZ%?>nh=aKoU%rhf9Qh*at@#Dc*N=Rh_{en z^HMaF;1N>g-NNEFFG6*t-N^#22FQ_l$}Bm=k5bDw#bFdt4Mdc?_Ofud99GwOc|pkV zLeupt6S~Ww01dOzQ|$6;XjT_It~s1$)RUE1p>B4OHA}++T@~EIx@gD{bgLu9clh(6 zzo>$axYmB#GFU?FZ34~DO8m|)^xOerO~xx6tJ*0hqwHnV8V} zfr+O$@$d|pP)0k(pJyE~wfNCL{&gZYjle23y>YS5#-Ce>Bw^k5BA~XqM^>4C$^}9a zIN@UzddbrRCF0Apq!#i>MbI4w=fJBCa5r_Fc_yRY2j>g!dQFlMj+t1AfPFP)w^&1bPTZz^0GM?xyQcVe^2_I|) zM;@dX0#4O8*ndYV8bPtOPBD%y{Hh+oWVCZ?ZLfeZ?-j35r&d?2L~4+7x!QNc;%Xd4 zR6{h9S8Rc*4~Hx2=j;Zb0lvz3?=?qgsjm8+C;b=nT#kBH)_-f61+W$nV=>}xL0?`R zZ~6I5MWz!dQh?dD)6w%^Ef2U~7hmifns9e_=pY;`C>PP*tP>)xF#rb>NC(QHBj*qK z>plodd$2$(X2Gir4-AfpCMO5)Q~>1&xOCQMo{ldID}74>X+L+;5S{A-`7hPsu`jyF z1miBBtF;1%rFi&|dswJOYF#HgXmJj5B$zvAlbL=Os-Ss0ZO)W;Rj zY=0xD!$>d=+QJiefT@l%3?yazfK8Hu~mx>AkMV6yKa*ag=<#)jKmawYixfwWzv+I76vvOyX`U`o zOyfudF-=JEdKY%14R8c;ONzCXC&CMW$6^TT$G+s#he=KD6(v91)$SByqG9Q*pXGm|^55Tr`USES<%!E{}L~?LyhxT#?m4Xg|>n1)-tSa_mJ zu?lH6dkAn9asw=#t{DdLSDu`U05>p96t9*1R|FoeT-D2-I?`dvAm`*1JD{9#$m0Gu zK^86N2dcc6#~lE`#i4&|vDn1EWFKq+^=Upz=s8xjFdQ*PpEI1JU2X?S%nrea(cN5iGO1nYe(da_4}V`K&-MzNy(?pw#K zU;P^cb$b?wMeT~ua-%pG0;uHl#Mlqss_J$Uxwe+pv22uLRcL#w5`k7wFJ@8a`c701 zmqpV{rx{^fd!e-2_vQrP+xc8~oBtZXj;{jfusSq8??sn&tit$uoMhjI;VN%#cKGG6VnM%+MmJH|k3@)fr*eaaV0J*1Dpi!EU-kR7^`EhqCN@)nS`QSc-R%O4AA zJPP?^(?!*BnBiD4uZ|H$Hp;o6SU zksY~ZE^B^)qk7Ng-GmK;TldM+CHWoP9c(h{(sK$ z=*niF>kyQZf?;Id#3M+oTG9YQ;ysozMG*S9r~mBzai70B0m##<1J#EKs#zNPboP=F z$Zk1IDzqvu)P&a!dsfKvdnSwLvRsXQ&WN(xCN7Gtu-kkGQ;`G-&iZh!LphFm$Hc+WOxfgB`m~-A&^S6T$|*X?l$%i+ciqc~^`6*R zECLfWLglI^+{?dS-7u*Fn|YHlBM^jXqib!6E66YZaZw$%wP(CM22?ukJ*2-pn{D~g z8>p}kK^j{4O1KJsRAHEg1Isg&^(Z(VTq3)IPk5$pivOPfJ zaq|Hnn67PSo0^A*!>kd77ouQV6ORl8)n%}dllNCPQAIS=_}k*2qGU8%N0*^uO1fB6 zvDX2_dUFqj<%KG#i8J?keCx-J`K9K~%Z{WyGc)+s?v)b zzR{4Lk--@?7Iv{D41%i%uVc}F8?f2PqtQ6izC~y(*wiLjyGbq*`sR& zOR)GV5V6Hgxe#d}7VIkmV&iahi@6rBjv2;&ZW(d-4!Om=Je7!n2scEI2$cj;{f&6$ z*t}Ymb>z2q*|&%rM(jW9D8gZe-RbB?rlar?2YY2I&h?UHn35HtUhX(&_$eO3&R3JD zZH+<)(^-7(=FohrCYNpF**UzIhoJz;U+4leB$ewg!onE9eSd7h1Rozlz~4VJ(>!SY zNNdU@EavK#PUg2Q|173Pt=Z^?)$iLv>Og$JmE7R?wfV>tT6fXl9G-F|$z496k|)P< zjbL5hHkySf-E0FC2=*D*-tP*iyfO+-HVvedAGj+6xJ$;P8Fg>_ccJnXMQQ*oGXURZ zNg>m)SwM({nSm?U$Bl8{^M9qeuzNF-MCz4!819$5zteq-kW~YAB=$L1A2Yn`ccw#? zw_A2|DLI1C39VY1ll7h%oJ!Lmf{k!tvw2J7v+GB-9kVL?G2<^ps28H}xA zHRN;f!gvN~BV&97><810Es%KO1w zyk~!W1f|V?NaSq)IR+#i8;sr09K2%QeZ-+y^vC%+Qn=clB~Rif@Xr~v&C_zXDtqUq z`Qzak$Ap-Gj%vYc9&TCeReX5Qskc2-JE=>E=3KR$xsv8wz278|3$$X1x{B z5)S3z0aw9Xdkz~Hr=32n;XUHS&vw$Q7v5>A%nsx~c)JuQy1 zI-JQ`3E#^*oX;FKq<`4OfPJP*HWU@t@y{4lc;R$_H*h=WQe`Q9f@g!+(H%Jp<1dnd z2J*Y`*WBfF05!ET`?>mHux(8c*y+={;?qa@A76Ez)s_+-->b3aT$_gCW!EKBO})j2 zF@loWzHf;}e){Z7SylWA^UNvs3_#cdps1pPG1E@0T)qzMMz)k+u4I#0y>c(w{iTVg zJ!>2wf5cBW?M-e}>0kK=ua{(St~cEnKp-vm9XT;1bJO-0>u=^%yA4HEoB5Gq55jP< z&5{3<|Io+`3bR`a>w;VF0v_6k7S@IeZha2WgaaNFP4$FYv0Elh*Hz$;F77xB z>d%rl+DRNSUD`UU$6y;+a5NK`KV*bH)xe?O?*~ z4+@-86G7HB9|%#^MCBKxfx6({)lf|c5%lM9w+g*(GvYxSZAu`A;F3&nm{bTOh2wC! zaSgr=-ime9fV)%V{dGw&J88oH7+*Zr7njv)*UY*O*x^0}r~D&hNUvKgr`A@L)$_f?uh{vFsd4dkag0+6DVuhj zGdr|eW~40JLvTv$1UM*V!{KlwaJ4dkZa4^pICO89rlb@y9i|GHoKzn@28n`%n5&?f zC0xKP?JO1(?BU=L&#&5P&SKQJR=-xQvTlVH7@S5n+@ihPe3`CVc=a{3_##EG(KJ5y?2MjAl0Qf@>%`qIor$P$=bK;rz zV@%OoUsUzXA6wtIX@ik}r4DBH%KuGYA4I=)!kYzrzgMsI|0VJ?3)nJ#a<079)kH=) z1vd-z7jAhr2N{HZYcfa8kBm3&FzcE{40RHE^y|v_{~Z2+#;RA z1}aL9zRgQpb5H-~a=dp}7F^Q29-~t@7kmHWpR10dF?KE_o0;>Eo#YCJFprrFCitw7 zoqTcLTo_sKK-OFXgHUhuVFnF8v4?cI5E+mzYzMqIWi%+HbE4A6iU*1$dEjs_4QX%yn7x4EL+~7!DWqn8u}lK}pb?TsyueIuHVl|L+u8^qfXj%Q8mG{QuQk=FsuQbL^7B#Aga6Gilvb7kwg4itq`)I4q)X4=wiUXw2irnu5Ij2M(B0;q2y2m_1A@Z=`?R|?@B3rD=U9bT&#RR*Q3osQaC ztL@0DGwX0@vDoMiUq6;B7V>@jdy$wROBN_P#v+C%aKg)rj>1$wnFB>I`72Jl`XH06R|q4>^u8@RYwS|&3uEm7lK5hOkT z#I-?te`JrG+ceO~#VX#>|xmX=8QCqxcuaHnd-XI@}JUfi} zpgb^5a+e3UXu_Q%V&I-SxF2YEP}NHLvVU|lsG0H@@5qx+Lq0EzW|-y2sfcI}THUP*&>Ud)Os-~P&O|6(KdA(1H~h6F?- zTkRCP)Qo`6@f4}#9I}9dd zKtJVs%yV8b_mNj_2H^1+s?}hf0RD7fp;GmpK=T9`<2D5LN00X=RKV%TFY1fh$S+!R zq(2drmGdJ(mWQJBX;+B#KEfcvh{LMvkHQS6Nn;2Z!X*nd8XJGV*0%0HM6TD4aW5(> zA80Hu)6kyjHgBuhIq7-^<;3GYU}1&v!#^ta1g#ZxQCQO}5Y+y~(iwpE1K4>!*_8B@ z)wXMu7lUgwNBU)__^9dC7O zP4iDVU+o)=I$w$YbG~Bzo8>(Lf8=+7NXVMvBKVKf#QS;MWcVpIz20bHfl?JWg^v5? zJ3h?<`3n4m27|$5XC~U51E4dcBcKB=#kZBYvt7uQRZP5{nFLbXT^ zX~u2wC?;<%WK5B}hZO5X?Rf^I7jV%F^4?rzj;&D4@)u8$I37s*Y-*5MbWv}T4)+QP zYeopgp5F4bC!6W18e)$zvlwfsM=9_zaAXZPqWAbH?}8u!U5M*T2|&U5R#=fHcf|?u z>TM|-SK0j5UBFp8qmuhaJJHXnI&H@bVOsN;5ycoHpikb-wk{wqSu} zD&I%AA2-Pl>z4TQ0s8Vgi0>mZ)M0D@2>)?R6j9vfU>E0;AR&zR;Xa=4BEJy+?gkrw zcF-XmC|d|IBd5K4Yik3fLtXK*nIluaPW{m}PNdfB>}^;BP+DyVs=qZ5gyZkhQbI^z zkdyVaolB6FogTU07lngpP32+ zNWOHup+AL(AqDNW=;R0`?Ddb25B4BinrrBL9;R}7A?4fC!~ORMX)3zS#S~{p2L~r< zg3!fy2Hy`(Py43_`zC*l`T%(Aj=tCLoe(&8QyH?5jyC(U5C;YHO>x z+11d<^wdswv)vJ-wf3_R!;>Ynu$_r6IQtX8cCVfpYj;)yYIpV+q}^%eqNnseMD3{H z9U@M-POR{d(ZLrxD=X6XD%OmYT=qweD6M<^>;Wim{t}@H?}dLwH6i5wnEZQ7{>{WA zysb^<+y6CGzAfO=UcSK6zQEGHz|y|J(pCnRKQLu%?*jIw5g{rVB~fIC*Yp?J^D#P; z=4*(t)u*b5Ed6pr+c_jxp?aWt2;8z_bX`%as~=AE-30wys! zLj$6f-^oN5Wo3U{_Rij;X*dRGK{TjYKcOKrwbK!S+IzKXCnaR+?pNgNUF)X@dk2S~ z4ld6Q-ya_yCnI3Zfdq@3A*kaFs>jx?C<>gbd4xkf^F5ByZt?6aujJkC;gRTYcT|0( zMrx+0e|$VR8?d5c4b63jM_|QaNV`etM~Pcdr1pWRjWvIru5@wzKrA)Bg!pmWgqUe` z9kMfmi$#<7=gkY#KFPZ0{o`TeHD{1 zMH)(R)2x3RXABn@%mFV!TUag*B30S*=PuB8QNyCJrD>u@IKK+-!w63sjz_}ZU4d#8 z2YRCibleqY(Odyu=d9re4c8x9?!*rxUC~f(q-CujTA)SJPebT)ES~~Cv-ydjli(qG zrG_)#3o$_p6?TCi>~rYQq3d8Tf}b#ND1= zjboKWj@nMVY;W-u6zsv)H%H%SpJ6_>plN5RUaWSizoea2n}5A}Ge*j5MSS%JUR{c>On4*m zb|-l|Eb;ydaRd~0A}EMT&d*4Geu}SQ57E<6@-~|k-w{`J;jmp@t^Qu;FqWTwbgzmB zU?d)Z={TKIF6_@f()lt^Hq=c!IfC>nJa)Wa@ck(sJ7E+M37@)%%MYLv>FFdcU*3Nq ziVNKsCjA;yo(u~;(;FW{95ie^Br!2T7J4$sxCQdaye<;3sm7-c=B^LN*#mGdaj9$T#{dLx%wRGe&PE?EhhmK1yDn zs#=Ub6asDMN!TEH6{wjOQWBQ7kdUx9ZEAWP@=JtR92VCwRHD9vs}%+6H4%SX$|vni z4UlX&=v4uybD$1X4`F&iq91deK|!%Qj-aKKbcfCp?+z%2*ctS*e|0+dK2bP9$);4l zXvk5od26J-agc0Hq`h&}ff^*e`C}OdNOH;U&^y+^>Ohs=htqHzQ!X;S_}`~vL>&l} zk0)mbrvs3uMLP-~kko=kGm3vNBYJ-&Nsv`2=Io?@e0Gp8C;zrkkZ&rbAGeDVbgnhP zsra1nIw&%e%RDrj+u=`mJACy@i_XJ~H1Tnm3YUb&NGM$MO05uCq7d0=f(U;EKF@NQ!#5r$ z_{QTLzA=c20dtz_xyT`Jy87p){_bF~_u=yG$HSxj%fsV${Y$nm4)#%?fmxZ_L?iuJ zQwbg~Kp-PWANtd&6P-3(&*^WF?6L6C>=O?roeYO%s(w}dSo z`_LQtrUU58=)8Tg&3b=kwm8&sg8eH%H@8p+p)LdNhwYz~q=ys#R@L&b!=X85pu-5O zwyCO7biGzJKr5v_7LsLydu-?>JriyMU zGO~CJ;1X=)bVdG>yEouiVey|8@`2ompJZp*FRH@yjh8?7-(G*7emp)?_`ti@`y_z; z>D&v2pY#+CQK)K~x}bq(jq`x(EiVv@H}DpZ{D8uv#E9r@E49r;6Z{3;w8_Iet`bhv z!Re{#Bnp%jHLIu6ih}Vy%L7^rB$ExRL99?3R@ktTBSxX4W0}gEkTP7M0w62?@jC+H1kabeglx$VA(wS!dA9F~ zdDtrjQ8|#BB+`U@*aL>p7W1)JLO%9JNV%dR#Bj-83O+1d(8Yj zoq1vrhi-+#;T{eLh|+avQ=2yksZqKdZkAk4oST0t+l(_m1hRiYD-^aPd??*#w`ip) z?u~=*F+yi_gj|2D2r9Y42pm+MlSlq|kJwI1k4j2xW=<|i23$P5lG74OC_A&x>K!s? z;y~VgkAWP}fux3vf@ZKVly_A_NpQ<*-#C!E-i1?n?hopn`-6-_$oCk-T{?zTj(5q0 zV+wydDj&^$IbkD_Pu3eOsW48SbvBREeEIRqj`A*R;%r{N<#)v)-uoUye8`DM$F(mV zZ{#azzkGD}N=KLMN!dDuUcEmUsE4`p{rG$I<|Nnj;|emDv!`%V@2mW~mZyRV2@Gl6 zd>TqVjazQ#&L*`r-s-l%c9z>3iwqH8D(alu;aMSQKp!5&4aNmvk=fdge##5MwxfSn zulPDmWnR%mVr?6Mw!_m3hJF((?B9CKoAjO<*?`P&bydaZ!G-Ca2NygtQv=6ZiM)Vv zVKPUTndRar;_@uDi4p}Zvl?G;^QXlXv7y}aT|Y3CAKo79?e4EDNLe)qnulU6z&&>y z00;?96cHJd@9DP_C&Eac|H{8Rn^=Fge`_esMtgSG=+5pM%|CEHISOmTgfB>1Xh~YnIB;CQRKIEB+_BGm3Sa!vT2uO(SgoOD) zzR9$OLt+HXjKt8$#5#cEAX|TMew*-T@ZCZ)_%(4{JHQ^gGO_M^d#*FQMpN?K^XDNx z!qyE&njuo^BgP{?jbP>&We4Y1NQIO?EhJ{E2 z3=h%jL1`7Ed2xmL8W>{@Wn_B3_Bpa({bFK=+SyubR#HDF%;)OMFXZ8-WN~h6G&__I z>aMMCZ4f$0_dskM0&Uc8H@np5YNOR{uR}`{GRY+=hs@WA5>$V76?vhDG@#|f!y;w@ z4Cwn?EASj|4DY%9FChWB*Xa=+MFqcI#6F&q@hy1uB37B~Qp?@;UKChiG{ARJ%&cS! zdD6DhThF$FYgR)3Q?@+TwPJ~0CLt@!BTa)-UK0C(3>oWHiepFCIID#$a=y5I@!U>i zT04ZYGF;M zC_l-KdF9*p?c}<2ya^7RNI^NwoEW7S5%@mNcuC|YH5a^(D=jvsE3ITQR$4Kd!I?M% z=1oZKtD1i0`!36p{Nx$=3wmK(Q4OoOoo&$YZByxOkQrqRIRUuK73N)CwZH z?uOB|6H%Emfa1Mz!f=kmHy#EUJ>_aXZUlJd2Y{7CdpkC#8L?*){-of&v;+5cGF>~u zvx>>6hv0uXl5>hG%}$%8G+GQ)q05DCRoT+maY8kuw5IPEZe)-4<6I zo&^?uL~x|;!SD9+tBOq4b+*t0X`$4>TRb>$`Q=93^h?mam|rM3x#aWR0t&v+c7VP@ zp5PUe&v2Q~-~sv(I+Gb=F~^PE@bG>meJUhKz7T(x4RY)L_(fCCH1$9utNG5nj?q@P zxmDv5{j&7#T-(~9S0}#*;qn9l1-(1jH41lUr`cR@QcqoWqr&aE-dt-p;r8^@&emqD ztDy;$y3uZKfgaFPiLbVXu1JElriP~QeXX;up>cY5-;f)5OnZ25div~@vNc+_H#==S z+S-4>o87I>#(Ed);mugt7W@$tiuCrcO_5&KxuT}}0NtvDin}Mo8U^KpQ?SvWF{e~Y zXKi1Kw*)2WZd6V8=F=-2aM~_?Lr=;B^KzRiDLi#+V`F1W%eW0yIH;&ibf)hgXv`Us zuheZSsrS^awQfsbC3??;Zd4!KX!ix%=t+OrMn``gXrsL>vJvra-eqt`hwSf>=Tc3o%e8OjiQ5y6+K$zQpIXHPMl+6DHGqyvA} ziAxCcMQ~2)SV9@?0WM0A06J+rBA#bP6w)aIzgfRD-GoNYo6*R5(`ARdf~S__k}!d* zs}3MG3$T_NQf5{d-ui*fQq1xx;#jcyfC6D(;2W^er#uf>ChFn*3QRejv3KaH3sR-w zAzrpI0SUy7z#!h6nCkj~bG!xdi0FTzgf0{Mk>3foJ4Ml&dx;j258&$qeK6BhfJuC# z#6_CBh=BEF9!AdSK3N>dg0*rO;c1w@6GU}-l3N7N3YLLqHBmS<)*+fl7rA4jgYI0T zE#pKP5^es&Fw4>2=)$%u7NdZ`N&yP@6CBAjRk56Gn> z9_QFbm2!d@tP2tuzzMoj7vf!M%=Dv;Sku&F$~b?a=(j0=nx7Hz?Q1G{$fDMIXRT91 zdhh`SA1IDm3UZc}9xxu!=L{Z|9uOR_oK3c1;vWGwjdx^t(?oQ}aZx;kz4?@~0I<|3 zT;M$UeH%CtdyX{&pGSWeriTQUZumIPpE777|Gy*tFcvWiIBgG>tw38#pmkV^F^&Y$ z0A*0Z)m1ex18x#ol@fe^S=eF;g(l6pkHcZ$%pyM^PGovIcm&QpD0VSCf2qiHY)knYi2GMzW;|_CwmrOM<#UHfhAwWSi8%!A+k%}q ziC%%A${=5#K|pL#N5Y}B^ScGel||`Hh7Y zPy~iNMT*&C(3O9h^fk(Xv?Q41`Y*7@&`2d?gOR79MLH@pCXuuvaF8(9ie6?t(lp;gbxp-4Y}Y+IObZR*>)DG?@u_j$1kV$(o=i7 zGqQs}oJsfcH$>xmU;3U<9#201@cii(a*2&5-9L zy_V$cSIO zKvJ`mgydw^!6_#Uop*sG1g{hv(x@yb0^pG)g{6N~abR-8Zf0Y_b+`dH1_^SaRss7a z0?2Bux?f34oYICY?^D_x+PkH!M$OV7hFs7fB2NI7;<7=2)CFkxAb>r=jk2QPzG02Q zC%1$f5K$=wtWE)xv#>T6fVCMhIL0`R;hx(wcek_J)IZ^#+kd&|mfmxROYXVj|KNM> zH2o;x)`*~u@mFW>AUJN*V18K;_!1h;OVpLLNB6tNYF;_zsE)_;q&?Y9Y( z1XXGr9v==4caJX52D^g;g-O&unvQ<6MOuIL!F(GdB0HCg=93^J1eIxyhR8)DWOI@I z;e<%)9n`xf4;K2|Bo867DLzerzRbvj4_1!c98jHSSxY(-z%bG$K-3Wi+*E`g3Q~ur z^YEZLGKt2_`6H<~}HAzE$<-cZ1N!}<(bxrHxLA5eWGrL+--kE>? zR*+jFP)r%>?0ZQLxULJy;iV)k>zC|pKD8kJ%w`Zi$nr?4NM0*Q9hv^agX;6qDMHGn zS;e;s8kK+&7Sbne8%Y89()8k6N$NuR+4o|Ok0<+*_KR;NsSD+2-_sl-ykEL{=x;Fv zZCjdxLs_LMXz6JR`WsSE?NA^}o&7iN6bnJIA#aTYdnUH31x_f-K zyO*g^cqdPJCQB-on&OHjDbrU9Qf)JQcu+&S2FpR=Or`vrg6s;IG)d0nn=~hdKa*sm zACwr83!_ST`k5ZGh_M;$zV?6oTTej@ zbTEArqwt%NS^g8ntfpxO)kuOn#5FHU@ftKPrJS2#j7TJ|s^xx6iHl^JO94ca!s8fi zbUNM25(CM`>44`z4*p;3~bLV~F*v5jJr*!`2bAu3Oh1r`s zdsbk7Al6*QB61=Z5AJ9FIIw?alY8#eoOgT%vrJ~JX)I_2JYzw8(ECtRbZ_V#!HwUg zRsOL?T6TNG zN=;&U?$OA$Y%9&(?RGlr3T=(@gWYM5+M|+Ar&hH_0@$GZFj^a}k2V!#&1P?{ARV|E zMZ|oTk29g&p&IOIYM{T}rNf|aXu@bJKWw%(vDJZqg-#fq(Aafn6a!K)>xFvpXalb$ zmO?*_@bIcTWEr`+mMwqHinm7ADD?sSp^NSA)*8V@m{>E+@eNKb+nI+(eo?|g3LG2L zB~0VKGmrYJjBnaxKnAJXvFCf>qYN(SM_`Yem_PGyG$Y@ONFZ(YTQI`TmW{G@)AEnZ z%~k%9ySe5%OSa$uj^RD*y3jxS-dH5vpkU;rwdC+L4x} z7Y85)b3k_B7>jv`kMUjfiCU|Hn;hxoJ8SB=_lEKsgc$fW#g<2J!RM!E4bRBWcfJ>) zQ~%13eDndkHyD4ISF{^AmWx8m3txvga7GHcVhc*PSdcKpdYcSAv6st?z220JJ^};7 z58S|C@2+>-Tab!vf&5@^ZfFW3CunfSPUqKpm)6!^QrlXgHgH9IYHh7!!3ZC6s_iY* zp#Rqjz05B`p&c!Kt+Yo^tOHuUR+fh zhizv*C5ttEd5Xt#*9vHpiuFud)r*97aXsI`PPT)s7){!B3hL+^Ycu%u)mg;u3qpz2=+g2(h4`&3{_T0MsuTVw7TiGY4h#;l@*fd*{V}vw^oH)%PJ(J)v8nB z`qBzFd4+2g6(*xqRUuiRo2=&Q3dt(0tZ|(W*RmQr&3ZMqmeshy$7^Yg?WHwt)v9rm z4_H-=(5z0ERlTG}DChNhMU7;UZq=!AeQAGt88a?(^I#z$?E>-zOZMU@>sO;uIGTz9*y?qyZ3EvvH2r)g=G>s3`= zB;a|}K@o&r6FkL$o);q$A4Vz+PqZ}wL!U^{F);(=IK?9zU~kA#Hvm?qF|k7Le;|L% zAod!7ROnbPcmX$FH^TW02db7y0e}?PR?>i{@%M{VlYx;0P>K{&CD9R`;*pDo(Zj^l)NL88F34ivV2|)lMgYe|OIlH3`%T>+HT2;Zl^2LS-r>N9PwvQ0ah) z(Mpp6tt9#m2#}g|*3atrRNu5zZKr=wx{(i~M^zu^pnJR64n#AifFq4K04c4$V;S`; z$Fo@y@H$F^L9DKhR0m9_ihB z0Im$=1S3gtd2S0!f%lfd)JG&fDgQ|PpE($d!8Ed1)Vb#Mu>koQ!6Xpml&pIy8=u#$ z71K;+vVa#uf(i6Ts&ejGk#mC^L*K?1;+}G|Mr^CAs^TZ0GBXvRZ6tdm(sm*v$c%c% zDN-HDCtd{C5~>wu*^Cg585n;QQ|o=A_DFBhH8fe zB!3lyWAtQ$-EbTg$!PSf*$zRBw`N&gs(NLX1WP0Q?x7(O zV2}wdAlr(VQ^J&iouDwc0-hrrOUbTBA%P^*!~sn$B}?}OUa~2&W(t3;Wm{xKwDY+` zVES)zSG@Io7hA$uP<)&IsO+|286JOOjMFtbRb`GW)Tkvu4FI4lcaz9BCh07ZCuH_{~BD$JBBM+ zg4PL!j1vfRwNrmM85VR(4CVd7KtaO*+dxBDZU_kMLw9atC60~59QSpYDLxZhK2s_t zRvbpO;~77n^^bKrRnF)h&_kq^F&xRzSO8SjEHV@ztQb-A=1T~%AQgtf_Zk+rB1sX8 zQM>muLIFya^7xn3bCGVzAu# z<70Zr(F}euRU{IkV`^z&t|0c*%_f1iR&8_g@IXUvYp}vhx{z%Bqz@nq@GtoVelMm% z{=jc;=+A!){K+0Y23yrGfy6o?fY!&tHG4{Dk%v~-$Y}|=LKB}`7pf14+aW!D*@OrGNnu!vOY;7pRs?oBw~G%|3 zLEv;l7&T|4wpN|<<^`+SNtZ2oju8Zd2d7-H9X`KE+@vjY0b^l=Y7=6~1^%rOsx1xC z&qk=WwHQg*QBDb{R^cX+glK^2j5TC!%S3n*#O}siJ;w;_+eMk1MdcgC!F`WCS~s{9 zTW)`VE&INK@9=OA=ZLOQf@<5})?i&j8D!_|RSOK-14afI>=&ux;Xzd$lYi1y zR~e-eXs8KLtT1re>gq~L!vx4WZ(VT0g^xe?E)2{jf`A~Fc}}ZE4&7208iJq9@32XM zmRg2mTH99vwyv{b?Hj&Mmcgr6-01=;MNoew!CWGV*Nik(V3GuudEUI(1`}t;n`4@6 z!>~+W_h%4&cBX2`*I}K|A8Ar<^-Pw!W2%lx(`kaEfOGD!U$0viK(nozrU|`zcxbaH zOcY@;fP7wnWXIt#Kr*#O-tjM&fBE?B_kADoNvO&=T}~+EiChV9fcPtFq;W^>6wn% zgx0K)HNaN0m2TK%Qo+$8b)H}o+yvX)x8felM!kHOje6gh#sO&`52!Mg(VjyMnDarLru4Xhh{T)a3HN%65a|sn{ zf!C93?lbnwR6{f3>wrWa(ge0S+zAcWXSkn!;EW+|7b4-O_K2>AH{e=z1$uu4jey3Y z*SbVJ{*kCmV5Q<%6)xhBLYfaH5hs$wAJPCCAIvYRBytlQlGF-aOH30vsUEuNgM z&PZ)HyCkwXl|-;(`n-dZ9eCbGk-3O3w)sI!u6UOI?`FH%1eS&V{HfDyYH1m5p$x18 zy{u}ioHmrxZ8oKKcO?0W!%Kh93Lt{+$q2KOJGA7MwB+u^cA5<$4Ds6p^0eF1JnKno zy68t0^Lo|{R+8!HK!K=KaB>Ullq6WE4cU?wy79;^9*AAs$WOvrX4tpn4c=r84zdlt zR0G!FEhDY(EE$_t)8H+=fRLD)wrs8bC@kzhmL>ipUD$u*7Iw*UP6&Ua@}UznY)lBZ z!ymHHGAU$AiHI%*O3{q>WDazCp%v*m`uU>P5WP?PS64b1$7rqDs*Waf^b7N8{n%zG z19-r|1)@y~Hz0cJwKulbvTm*dr1@_rprQh-d{s$eckz!0CHY|0Oyq&!IFWcn>4J|+UT}n&ajT}AaGuHYP%FwC;_cMiJShg;?QS?;JMuts9hlAS;3u)L?cmib zjiUId7-~L+PrH!{8jKWB#u`Hy0zL9S&Sp5+vqG$DER=up;ql4G0Sk^iIQZva_w-;_ zF(UoSod+soK@#SRqW`26XMm^v4c>KKQf&w{S=uXQ&kCr7l!hb*dZm~_?9Ic2Cv`T* zx@FrW2b@L3S|rj({%{_uguvVCu6H`bX`fGgBrm<>xzK!+9V1ffogaTe;E_?wngJ^=m?ri2d z5E#-P;}9h0+IIN*^|t1phZheIu8PmY3ltKf;S5I!F)Ro&h;<84@36wT#RDbfi8RzP z6-4X2wL(LAl{==fz%4qaqQsfr?A;GtXV|bYhzx(RH@sI~Ia(|XN3Qqpz|%L=Q@zo% zuA!p=1`We3@NXO&+YOLIIo=J(=WLQN)Ena1!DcKpm2M~>fCm=vues7Br@_daGuw`b z2R2mXPBYb!DG26A8W$MA8E)AmLX+*2!LrTK`Rmuw#kQ;3Xh=%4H2}rBod6>gX#r#4 zV8nl{^VhFI111WhbFuVTGZ59F@m09({S*)l8soKy4lN>0A;L4npId2cJfQ>PMIIFE z>shmU^}*CRbR|<;82FJaGQ<C8<|-SU?iq|XB110T`Xum z;TPP!C`qRit(6(YXrsBlwpMki{5)ag$8UcFM!a1P82N#3X!vh5eb30bnUf>uWQtlf zC^HLF7l{QJ!D|!*wq%M|SF`11EXLxzSy`f?B}YlU@QW}EB>bXxVMgcPg~qMWwk4LW zk2NgZBO+yd7h%s18$^WEP+l>9J3{V0g{!>6FOva1k(WTqV7yN zbfz4bDd$2kLN4QTwzFon{QeW@3lgal*J}VKkvf}yj}rSz61fwCcA5~rQ%lwBV2b!S zM4NPc$U(3S{m}U--~;TudZlF=1!I4cDA>|2%~&ai;Xz_%mvoHgfxetO7oA&GI~)NWmHC@X+NdMU`?}u&fTNQ{Qx#$O#}_)=l@R@xdT>$)m3`A0zN0f z=%i$FdIb=BAAXxQkppOE#p{$y$%2Q6sse~CtG%|lzT6)vgO?jUJS<|lai5@Zf$#t9 z9es$R8MBK;%vcR@*MV7`7Y~1^g@0|dO;dH4$ns6A*?eefC>3BDj%XjrB%b^ong^}{ z#%I*B^5f|d#f>T+gn4Uu87>#ixbJPjXL5gzZ-*PF+MT{m^DEEKq$s~l88iLtU zLW>RIm81JJ?5Pn`**!ccV+>XyXaxY>bl-D*%NA$e0U`+mD6H2M(J53lJ-{;;Y)aq! zA65U`j%J+ypMRbG%e(lSdj7BQUuPG8+tGe}GoGTnCl#}6jLaz8U^p|#m-7gD7a9UA zLzAEz!auJRq`dMBk6?f0&VdLZttG;KGe8arthblif0>E>muV6roqqsMlXgJ^{Yb=C zKkb$}Oh2Cwf#L)eimgUESe;QzN+3VVg_!}w#@*^}wG+W&ext$xt16zqk7ohq(%#f# zg_6)KEpdZWX^_YBlA|!2U6hDK+BPHtd*4i=9pG(z7whB`a4diP1>nw+{+KJxRM;k` z`HR-K4yOZ2BlWQkx>ffq@&jv(6Bmz^E==Aq5qmDjIZjA2O6&)#t4b8iVJ1z++XY&7 z?FbBe5TkCpyFtWr1;FOW%t%4gTv3cRyBq7BtjzUSKe)zF;Ko{eEBnb~3DZ+aC-NGt3j1&3QkOQx zd16!6TdlSH&^@Co@K=xJ+WPudQ#SYC&YbV7+qk*4(cXWQwNY4mu;3)yB_bJEkqz~6Gt~_j6$eL1@;tx-s;>b4ovG&8S-xcxVj*y&4^+t)1I2(Mj4MhPXkse zB2tdhf|Vq_f)=TNUWI(TScC$xzT@;UUbZXmhU{a;Sja9BJPs4B9i$_b#l~m zwz=*6&4G9fF_+?FI9GAnx3Ce%* za1tDq9M(!<@9pEj0ka5-F;O!laF;xPvlN}gyI*uvUm zbGU?Tu7LS@Dv1mX?bq|~>#YLO1|l39EreVGG+M~!dJ6)FK(r8YylQf#XFv?B9P+P4 z{`E8BzVL~RBrMlj%uR(-mqQ!nJ|us~@{Y`Sh@&7GB?wF9)yV;tR#))~e@;(23GC9J z$T^X@t|7#$>4hKsyL#c{Z|#N87?ZERf?Dg{$}oo8*RNf(`fi$jM9GdM5QxRX#B*aax=LgvAT$q1K@{4{9 zFnM8iFHD6!(+@M>b2vnTPn1xZK02nC?~Y}9*-rZaDIkBeAI!VyI_uFE zp&`7uivkNmZ6Vjh0?tqfcCLb3q)Uz(Q`v=u>{A3J=G8ingZ;#flVUg%JMGFdasQZ|i9hd=2N!=?XUuqc8n9-C_k}5@ zXCgSy6v-PVLt0%`PO&wNjtQbBh)c*CyZx+5eDFN$#u)>N1xwSO4MHwfh4hV0p!R{CeNMK06 zgtk9bfai-fqUV2d&H3u;$}mQ2osCv|nf;Kcm_ENik=ZO$f)GtkMg@`~!kE;RSV^Qu zzs$P@C(JoxZKZxVbopRX59j>|kp|5Ozz{=29;Z(H)c&H?Tc0 z_hkGl)N`Ej({kq>GLh`U0)h%8m?hFfI0xhd;0fgb3lD$SCUGF4X7ofSm?hhsk$QQ# zfAHz@a&>iu)#iln0{;)}5x<$>o(C`=1sMN5C0*UF5&3b9U4q#FtU#kv`$%ap9Vsv*H&n5)S3dq#NP(rC65K1!6U zrsHIZu8E%<-(^mszFg9PLNl>j@ONrS77QQFt4JwcoJSZbi_fG;_9)(bdW8eg*VLkJ zklrh$p@tYYCQ&pCjW=(`PBfWc0WQQFi(He07W#kPedF+6zMfgbYio={O)&OgBBfA*oP{Eysv*MrxV|YkxOKY+I_#it8L-JUnoVF4rG( zrwxDhO4JRfdv?NYxA=^!!hsOSYG4i@9@HTP<05@CZIyKrLiM^nc|p1Wcb64-@SF4- zUQo8nR@o3x-`klf^Q#}b{*~nphzb0|!=&^AE&B@2!DZiQ*=1iRBFC>Pf-%0LsT$jA zSEh1#si3KOeub_s7<;jQ@JXDyv6>l7hB<%C&txr+Gu)6-}z4V##v zK#EqHWuV#l^n&^v-a1qcXDvQZ=>on6;-=Z^c7&O}OZ#-Ke?Vs8F8mL-~x?A0L4GZ??vqH)^_tT4bqq|;%O3r&*{PY7}fdD(RdJ>6Kd4aY9ilk%T-L^LU?{r^eNt7z zLXovgLYzbbMafG(-*bW?gvPy47N zEPxlu3ZfG+@ti^hq@Wlcc=O2ZJfK=HoAJ}bJe zH(HIU9}pvysiGOd-&^3xnSM^zY=D$BWvFNxf&p|g18^bq-%cec_?&+`aOl5j7v%s% z(N1JYUSr+y!WkY$JINEr5YBQmCB7L2)nMwv^sjSf9PkDyityp$NAe=4IE<0#BG^!(_39tfW%MKie8Fs5hHS7FF)g*U>_WCx@oVqO9X%al8bYNvqm{E7b-v@v;WbJQJWjQ6`5Vs?)?{XZz?r@+TagbBf!fTH6l_e)2;>Gpb*10V9sRcp zlgS1A668`gSOj+>jI1D{0D=L-EybQ~0)n@V(i8*#8ha*A63~C&ECWON^kfK~v}Y2R zPExFq)_|~Q8@zZ9W@)KD9m}w)D*}`@UqqPw1FOA0e!?88BQ`-!IIV#ExYN^)#3As1S;X$+&r2g0g}C-DX1j$@jE zjSjt>UjRm1_OM!eGiMg>n1Eb6&K8#hcs%aTLM+Sq42{tS6NNqLr%ET)H52$|2GMx} zQVBUr!8+1A# zo?fL>uD6i=o_l8q?+qRfHjq4$+R5{i=qai-J&o%MB}Q~f($&X41debSv*~vH<~|))M`76g-4h9;Zn*65DB}{|IEr4kPEjh}wNdWmQ6;t(3MS zeogIj7+m0xT0CSVLSJF&?G2yCI_F(m)f2(8CA5V8a0 zH(mn3+XH3*gdmE7Zea#60w#nwAMDhDVwwUC!tlN14)=d!i6u)j?!?c_;GRhvW7C@Lm9$^w!H~$EIL7+Q`rkWb{+Tl5t2$~8v=>v9W9Am+3zmxcguTz zx76SDRWCdnm28wP$wkg4myGQIU57x1np|7_^7M~m7^LD|lY(sSfGsQy-^6mVrAxLo zbQ6Dkoy1t+_4FCYquhYk1C`NuH5vQ@IkVcj8Pq#g@byPXq9shq6K%?ah16`=ASf!N zi2rliMapz2D0cw`<&KPAsbcFv-R{7_K7fY@pSZ7nGN{Dh6aC^R17|`EBpGHs8NA!D zfg0VxKi#+gIasm{z2=n|(6*_rfHMoooCbfW$JVxCQeUfqFdrH$_3XhLDv3G&slWfv zL4C=0wS7hwu*^tPes-ZW>6{8nGdgmbdsme2S^XL1D?c}l3E7ZR7cQ>|Grq2$&o z2N@&A1>~3R07*c$ztYq0h$9WMD+8FkCZ4>_Dxx!D5no1R7kXFdrdd&#CBV(}C(zZn zg;&W2M$alP&lRb8B1n%_<~k*}-Q5CGfDlf9023SJOe$X|K|a#)qlSQKl?G9GHt}9^@GbtlL969*Zv$ zK|IwXmHd=HCL#qR0wOE5NkrukhJRjvtg_MD*RS85zxwgrW8eZFk^7}z0|^3!I~Ft% zv7l9Xqj3DZ?@PhHVn3WtX#GQw!^%}WJ+Ob&vxmtrWOq+>F6Hq!L9?FzO+>1(`SOse zvntml=(hUb?J)@&X+y<$+Nv$0_rwA~C)J%DCp@Y13V=)|-#pBTdOYSTguNwywHk|p zZ1Z+rFUUGC&9`K{Jz3>zTm4PGcDi|IhETS1Bv&AYbvtC0vn12Y>m}Q9kW|iyjRJ^GwlhfjVg=+8aD!M`6_-WxczRwp1INYz{;bY+`F-6YUo4i6L*V z5zaH(G=Hea;|e%<$ZaQ~WZybIP~;f*_QL&s2&n3bggQk#Q!(gA_k{_6-h`Qs^c+v0 zy?plWnN~+E4qGKI$OMM>@v_*qE0%SR)nV5MJA8MdhC6+Ca!YOY*o-V39>(YyzPo19 z2uil-h4KrFMC`!Fk8H=bmAzXs5qXUIXC^5xO%g{o?FOj12)9c_lGsqm*^$6*^H8Q3_h2 z>z3nLEA^L7zla%ewfvH+4xhxeM?Nv1zY%ojd_vk};j?rwx_G}G4H|ke`NXx4_7-~j z*GL_Ptecq)Anm~=-A8CaR_0{38dT-Lt_-i?(Q;3}jMu>w z-;1zlj(AIdiDpxQbxb3{{E9#dRF05{U-iL*p294;yq6rt_ryMU5HHBux$mf0$A#Oe zo9ToXWuON!2N>u+;d&lfuSxd!SDZ5Lua`*pUlL);7u~AIq1U%7UKdoX6j_tBw)_## zDSl{xYE{3(bdZ!)Gtg&5O#cE7@IkSmyi8qp>ZhlFZa59^3EJ$KPi8EJHqpj>ru!)+ z_jD0N-PgoBFx2r~*@r`OR^Jm^IieW&HgY*30XiVeU);vc#bPZ%rHFGxjimH+k3>51 zZg`qzOtLsj7TZ8K(6%Ia4z~B#lR8yjdN0x2+(x6_bqL@({;%m+ztF&_J_c&A#G7ec z4Mf0yVfBF1!$o5O+RC$-x#{O<3~dTv9of;c=ZDlwFlmziOcVFH{T`A_q2>m$K$ZSc zVUV@08^OomR}HxpNTq*P@DuFLge$JzxLHVAj>~V7(Ux7%;^XU*0W@C{aG;WJ4rxG_ z8mJ$7*X=X)(jG;~(So?qf{y5Qe)eoH5jNO=vCO7KO-vjl6^EvG!;vTi{XrKA0>qxg zoQH+#C=oNHHtFrKllSn3iV{*O%FGB-44Gie&LU`LBNeZijYertI>ZK}iOHua84c84 zB*m9+su|d%;b_YlP*{=>8`shB1VdT+uZjt+;+9Tc4Xs>v%1qb{mr!PeOSdnDU6vw$ zio6#Vx2%vrNlFqo)uRjn58(Nb=eCr#B%uvk7%FKeFi#CKTe8{ryEDB2>^~NRqI*Y2 zzv%?0(b%}oE=@(Fl;1N4#NQw4qnDrvpesCplu!?RQ#ovPwFR40fTOFXW$3go9mz~1 z-uDv3WRM-(wK>O~y#N?tsefpu>8*!<;8!qWib=#94Sz=ywx)Q}4pAC$Po4ev_1TlR zFWyK?sw1Y5*10?GhEVu5$cY*eVRrr=(Ra0fAnA+$Kzb5?Pm|nhnzDo|$`S{t*TuWK#3OvhvmRKi zW(e=vyBw<{`dHnt4g$PMJz!pNyGo4pI#;r;cFj7(m;uq#$v#Ug*NOpp#HbCAxDM7} zK}CHb8w&6|%dD7dvstLVUF8KH3u~1h130A%rH8I$S8Vd~1CSkqjX9xz`3j%kq{_}L zGyIkBlX2#^D`5==2!WQx(e+8-|aMf0*9fx`I$ExI2CHAVIeO^z7V_+pW#5s z8EgQOwaYcuXq7LR#%e3@!Kxj_w<4~mm)KZ6y*q2B%mB1)jjCjud+>0ww(9tH2AK80 znjlX-YcA?$lx=~3Bh%CKH}>_FeBHTgAmA&6=X4FnOAD9ZjmJB3l{d#6AmqY6e>EOo zk?XuMEBK?W$u*oSuE|aAvzNf8qq!Fp-7-P_(B{@>Z?83;-k8s@g6tEkY zSwq3-s56JZ{wP12wB&}A2I%P=L~q>TK_f!dih|h;0>GAk*r6ckT#__Iu-QGg#U&%U zZkTw8Ul=K-jb{;^iS{ay_V5rqAl2fbE8*G=VT)EetWO8 zi7JOUV?%EAtWsx|^IjrU$dx2V0JcV+4^O5hf5KUQp4_wt2+13jIA zanG;FNYl3g*1H=8Q)mnDR6Fpaww`GAB#^y@Vs*N$-e-*H0N2bh#FVLxXFg~o+SYzn zDGTcBQtwzIfJFh{Q2Vveg_E53x?PTh#n4G2^& zT4=CZZ^9URRN9OdV*IV(7+SJt&qjq%Wvh}={Z)RVeNXYoyV{#69VB<1l5L-sq9uHf zj*JTwtl&~6fh)naqWN2Qje9Cy!9Zhmxed1HBD(c%ovm|y$F{o)iOr@gG|dOXnWr(B zF%8wxgFd^(@{{R-2HT7iLMeO8SFn!qt{IJgOM`od%B;TM7Y^-EMQ#spy!dRM$Y?Lw1g;vT0v z?w{^tU8{ppRJPt2^>Bzo-FkPyTE*~dg8+o^n=?==6GW@S2hP{=*mv&PE}zwk^ES z^IdZ7p9a$fYGB2Ff6;yM#CtI%R|!0Se(W*%gi}|Sim0!~xUBwXJ}(1UkN3zXNxOZ5 zW%yyRe4X4?N!&mFP&Lg=y-)F0#L3T)`+rBD2#)r};&6!LU!wvIuzN8Ja0epBh=V>O zEW|U!(0s@8%mjE1pA*WFZGnZ%a8MjEF9w_eS&T^Fpt)hW$j{Gj*m6gU%X0;P7&|{t zPCq|6{WK+2*{@iG=KCj#ys0)B-Yta1y=SuXwt~w9Pl92p9J-Y(7aK-b zkjIG{UX02iv8b)G4xu)vYS*=RZfvYi*_MJjV7k1Won$T9O6Oe3isoJQlwH58s%`Dt z1x6Jfq^+2{;pM8j8IOnZkIDIe`QtaQU%q^O{^aG0XWzdAm$lkt(Pj`O=x|L3`#qQl zI@BJ^UP=uUvp&r8<#;S(%x%^$2rq}KK4t5geC*~`BR7g-nVf^8k_m8)k!Ol!1mxMX z{XTgHWY=&=gM)zJSxKA`$plg3k#Qibp%ZqsgM^nU8B%5G>%xiNRRe^7_u-h^SBEIG| zZ?eIrX?At?=+Q+rq4?>^id{b{9<8dPc2P=SIy9qT(0%4Id{E7~SHpNHeNpp3)cbw$ z)k!az$0o`MvOB^EqDL`*zb3_adPOAC>xi6q`s}B7uV24BJOAe8>#rZbJpbG4*WaCgpDS<8nSQyX*ZhJu zl^~b-*?4?5X=^4PU%+Ddpd%(bz?aMMIJvYZyeAt`U9m@_^s9%bvk&=5uYm%uPcEwJ zVhaNB>d_5b)-W`WR;;0X`$#U4hjPPsxMJ6A3ybh!^XRwLF-SO>3#fqZf z7u(DA@@iSGuSS`FQ-SAPuyyr8)?hqNoI23e3UU0^?|i$ZlS*7XV&%gh&mOJSJNSUE zh*JX)(T_%HN1^mSmB!zP9i8Ol#tPqeXs^vhryCH4HE-ZCW4;XhaJqRvS8U@ z^x%V{c2mMJFP9z09iMK8>O@B}R>>S3E;^ZxKDuB!4b#GZ(%?*~$a`#d4G=+@5k|xp z9$7@7kgnv(Hbm`{z}^z*1-GyhWH&@LH9J2L+sZKbgTyza?20(9>uf#q_*Pe{^Z!;= zmrs^pUGT3Yw=x(DGdtl|Z_a1H(Ii8EIKdeX?(-_fAo|B)_xf4|;(Z#t?Q!VqVk^~_JBcbd+{ zea@qrSyika05lr!K+YoT`EBmeqo*gw=j`z*`yZZ+@1yfDLcVomBFd-lo{91~|19YXGSOuy&n3K9L5 z-bC~1?(7MPbZ3!K{CjB7<00a`Vdc#41#3ZnNID@dr^t8HQ;wgZE@GtUi7Fi+U-yxM z`=Q@mP+lyA=YOkrPVV135i`wQz2mnN!{%Bb?wP2Lh*A&_2MI<@oo0IHfq&+S zi15B3LqAXstjz2k79rNjoiT?A<@x%j?lcs@*+h(+SMyNtQ=AAQO`Sn3bcEV zS2)_$*S_)^Oyi=!l$W_VOTz-Q%Hub7b{4Ao+yu7pG=Gi|~cieaUec5b0fJj6{xC$XaUU8&4lpxH1R3@Io5S_^t zt803}@{-h(9c?zbAlm=LiJOj(5+64sA5S4GxdPDSrnKq05{ZlskdG;h@Waz-`&E82 zefY3V?Q2O=VXAle=)7Gla&r?Xd@z#5{R%v0f(Rz(=QxhwPqHIQ>VxZ}|Mgvp937-N zBq}=vZ{tq)lRtkBPWR$}t`rhZGTyCwG{*sEHmNFKd0AbZoZ%Awy27=6&Q~hP-rwK> z%_C{DF4;#}qnv{VKI7Yjr#hVL_MERWe#n4T5A(ciC9NSogppuC8jV+V82-p8&LtUT zHcY#ND-sxw>{m<7L>9zz3&q~aH@OmwfOL{o&iIPZ)#{yUI6zB(r1St7u;PRcvkF3< zM%#%y+r@xxI-OK$!Z%?1u+J?0=~**BS!C{P`shcN z42On00$89E$u)a_DFa_7>>7k(+lVkWt#mU;W#UV)fy=A->vm*zzZc| z2r}Mw(yGG;gY4RKv4GNSCb`rd%o}gOEjz}LJ(d5PmU?sG+#%h;WLVCIk0GqhDex+%cd z9Mmf&e>Dhya=>1w47m6;b9Jh>ecjdOG?B1$ezH*Ld1*soFC0yv0TKt9*i69A#1Dtq znXsvp)bC7_F8Q3yismUc8+ydtq4S37NefIWo#T7Alk8NQtk{l~a)TpA1n8=efNBx0 z!K#s|d-dZGSE#$QoHvU@l+(4bFL*N>=c(RT>aQVxW`L>GYyFSR*#h-jHwJ>gRBwT2 zUJ(PrG>jz-l>HT-)!K0o^v~%0oPFSRQ;&K&YUXy)U9~d<)~Ix4N837!tkP(^a5ly$ z@>HgZsgk`3%k?@VxG_quJatJK3?tM??qn--mS%8_iLl4`&p{g%aZ%S<+|ifF2#sR0 zEr=_BDViGmxRU1X#Z%8S+I{`h5M$u>k?;cq^kc1Q5Hz_j^8P3xHqF*&@BIArHr? zLbIZdF>NH-lCV={L+kI@$H(HLPAXR`#dODi^}Ja?1uU*}&KCQ<@F(SduUZXvAtI-C z3W7ZvLbset8q<4Zx|Rz-+Iz*QZ@6W99aA4=T^4#NLdM;sBpA|nxWjbQVL$fdWa>%v z*d9m$vReU)to=f0?@%5_`5wH3yfg`ko2j&wPpo5<(#@>Nnt8j}@0)pnudOu?!x|#WE@%8K!{`^OJZ#gxJSvdv z+%~Kr*o^1qLW>vZ1DdITtN;8(KD^(1gIz`(-yPJP zV7o0Xl-Rn%h2^@*HF=0uPZQ~XUkrKE-r_0Z3?e9_dH8f6vttS!_K0>(0_~f!CZSp6 z{QT9kcaQU1tgZYU5CPYfXe29TXyL~8_PLh>`DV51ZtY7Xoi+`SW;H!0FjkYfMjxnU z$KWh4gI)G6sS5rmBPaxH^3V}*gm4>f-cw`SP%aZ;cKz0HtJlA%4u2qjZIa-^et(ia z=r}YG6_*EUN$}=ZC%UU2J`8S|X=4gNB1aU zu~i(N6znW#Y1S#Ze`ZHM#*X=&y35aBVx$ZgWz5wt?6NDRwZ^S7$dhvQWW%?sw`~1l zRbw7IGq13oO-gh&uen%%XpDf!-Et%!l2A)Ez10?Bt`?f#qtle4G!}wrX z3xb$uzXf?mU3Miq=<4RA+T>P$XN#z6*FDS*OS7G8bAX&?$-D%YOPps{9i^JNI!Y}t zfw5=n^2Q}DK$U=*H;bux6*dcj+_5Ec4jg=(4>m2#268DG8NOqGy&0|L&U48=zM_}l z0Y_~>x&o-UK=*8IJQJ^uTB&>=qGL5uha_#TlJmjXtDHRA2scv3<0R@!cc19&daK<1 z+)VtOq?s*Tw^6cWoXZTyX{a#4!M?{fveKVP_-nkQiADJ}&})@)|92lLHT+aISs#<6 zgmH{4ffz?UAm(0wU+LnNs-WuOXoF}1AFV5K!J1JvLbg!Rd>o}=(r)#tnF|j_|7Y~T zwMai!jen}xi#^Ln<0_zsVRzf@@nAWLf3*C>yg#1XfN&efC-!@Rqy;r&E6Mt4Jzf|# z%3mcs)xIx7P*ykXm859nPm(Gna0QP7?*wQ541gSZmC=}gXiBOcACr&8c}YKd0F}_C zh&3<|Di}o5;ZzKY@yhU@x5t^jwd^#pcOf?iQ1#ga_LsalB>dfepYV5}Xe$%X%ih5w z=z!Em1aBzpaPnX*=!CEGhEToiOG0I5f6N7;%683(fS#xSTF;lhb0Cp&hLq01={|iQ zlG?b7)p@~xagVTEnOga3mUOK`zNkN@bsGOeV-9^hFWs}*Ow5EdN!_JWmg%jbpb%iL z;;>(V7V94&(Myyx{Rc}=o8s{=#R^Tc#@)?HnIgY})19bkWu;vmsuPJlynGBs>^=tb zuIXHjp4FUE&!pbmN4xNBM!LjMn`*i)GjqOd(pi6hGM*y}jOn&!NjZeF^3jKl_W{LAnl?rG5EWb@Fz!vx+%+6dGxGocq60ACTAcFN2GB9yaz45 z8-LXh^;-+|yJf;3m85||+!vy1fbkjCAI|ko&%AW^)E5CO6Ry6znU@PoEua=A;pt3d z+}Ut{pE}U8VZuC3`kmc@wZ++a^LzW|JaETC-UpcZuZ1-_TIOu?SLiY)3+df_bANUM z1SnA6U^g?9Ay9fN6$Ox0KWfJw3s5?B6MWpMSQKd|z|%1P)f=^TDO;fCOQ2q$5@@m5HNF|lu6*%*$P6i)a;K{8kUo-Ys(7`;B+Yz|gintRpTNz3yr#8wR zqcYD5qHCY69V#v47?qPED?h-wChUssf$(R*+2?eJhQQPiNdfb4qd|9gP@m&}He4tC zt-S%6!!=Y-kSbk}VVf!n62LBLbd3^Q8=X^HGd5+zhN$1(r&uGaY8u^C<>0$ zq%7=g$8eHz=ZBlyLLpNC>^H1`j`>%)vNqv!QltQGMqSq8#%wdTLy%&|jMeBVEibm< zQ5U*?5dN%g+n^k-v2uzoW|STjvt8vZ{WiCCCPl6*cHFJBg?Og5^3z-0YUOZ0TGiE^ z$7^LsZ-{mrm5ZF&X$;F;XP7^@>%&ns#^a77wHS|wt+pe7{ZT(TFBZUm04cL>+XiHX zVIb7jLg4`M(&?uE@JDutLx7gnsYU3?yUVBx@-U;QL=WvIpEH|AQK^r`U#0P139iw>GRrsg~-F)^)N>9rVW1Ou;1C=^hxdL)Nf=GQi*-W0lef-TUpz%3>d-L|$Q{Ptu zy{!yXQmEK8NF55OKc~|RAddFATk7P36zO<;;dP>mUDfMlgHDPKa>Pz$3I-$3o&#dQ zZa8F_ce--s2tBD@?{HE{z`@Qa>PsaeV%rap)#>{XEVYbm4-p0P_!c3RMsAeGWBUQA zJA$#jQ!v(lL@-)^z0?^FB>d$%j8@BWg;znAY953!JJwJMozE3Bse|vGwRbOKp%yVa zwuqZF^Xu!C+`n+eT??0W7A{L?to!xE1i|v(boUU1f8se+Pt$wMNuFlh*PMK-{ac+= zJ&=|z6M7%$wb2Tk@yi}`T6M>EeQ*p5ziE4h%(LzGmH|wE-{BLJ)=2BYN+M}pp8}`t z=#^43%vT1GArrWz)D{6v__$+^7IKAiA2ZEC<=F}!mz*zhcd{E$&z<~I-{|h<>yN+?!E3N#j*L_}He6-btzFJA0&7z5w!E8SFHI-E zRlH0_|82N`)V><2FpXcL5JX$)uWhBnI$0CuFY{&rZUOi|n%L9ng&%E!Sh$&7U^hl> zrG8$5LgD@n$(L~|#ifU%^)yI|0fuoWYUWQt765rH;6H1tgnW)LVlmqG=sF%Zn4`pb z(m^B>Ha}UUQuzH0KMDUP#%*LN?d>e?Do1k2CZiO8bR(JgRbg@9dDA(PQm8+_V(Ly_ z=gSb?WYTauQ9u&|u5`nJLS+l*wjI>J9UD}z4cQ@;zoG+Ln!U|Qh66b@9aL2nPQ&Pc zf-n4Jfv*-DDjqk<2`Vt7|BHD`Q9ub~NN(N$L$Uye1jAteIyEVGCiRvVEIEa|JMI%` zc<)Jn0%l|e;8zcjA*CLV*{@0M*!J4-nE#x#gqaU$d(8pr_$O6IiJ!E!PzO*w-8d;! zRe?WMK6GNfv7MhR@`CW66Hc~n@%qp@kW&<4jvBPS-;Zt&zzS8tET#|gQ8s!|fuGGC z>_549Ii+6cGJgkzf?%t*VD9d2GnC0NNEZixO05^7%7qOPtYnB_mC`&(IO-u{UM&_m z4YRz2-a)tAbd<+Hp3+PeYW!dUEZ$QC126J!y_2kWH>mkElX7 zI6q0VL>T4`tM<(KgHv$FCFXrS)ZWW3z(ZEwY4kUK5F3P7*qc8GNs7w6-0%4}gnyTR zG~rMVmHNDi<9|v5JdDKnkyv=! z&(e*adZBYa#R6a?SaT--%aoEmW4~(rC2>rY5+rh9-%XJ0Mhl|ygK~(!&podd|Fy^K zZ>8FS@W1!ui~_fZoanOI&^HJT;NSLt6nh~2hkiGV>r!Es;P#CU5$mVHt-fZD;k@7f zNZn#c?2f&nJCjsf=Hh98|NY}xyM&vyf2(6DIUbDWnX&pGMee*eRbBJtmc7HT4o^dW zlAAdph*Ldi$e*Gd?wE^JizV<*S1K9lJks&IuM{I@?*lF`+z6e$ZWGiIlde{OUdxi; zF?i1%Q~TOG=W60V6!jQHC^4L1AcY7AnT{A-tvGJOlG_7V{Ug)=+0|d0=t(brKz)MR97Se4G0S%Wc`jO1n@i~m*E2Sp z;L~ENHHYE|;Xsv=8aGHIinnQ6So$1|NnbP3yhjipEO^(r_gtN=BnCuBS317en zafK|O>V$F*YsGkfEa3Esk*1BW`>FgbZ`sAO4?B4TisZ|Vik>h+$H(uxx=a{x?%wOc z^G}tHAs&%yQ=@r0u5vG9gH;YXaTKc=k&{A8MxTJGB>vtb9~v!EV|LUJs`r5sNSX9< zUtf0uYcLL1M@@0G7UD^=XQG7rfWm8%Sf_Tz(2KQF~82CMTJ@94sns2|eN>)-r$q&@^?_W;Hn8@|QbZozJTUX(J1i#{|Y{I+Z#& zE|Zh5YLlLS0(b*z6W2$Id^k*WCd@!~@ZT9Y{D-Gxou5qC|E-hGP9Hol@xk?cjr;FP zx5i-nZ zjDdjV+L*P*<1Pn|ioYtLVOtR6k+vU6ZJ9Sp_%c_2_BP{ji;+KlF|ao9zkhYaw4773 zKyaK&sT_2LxF6Ts0~zy3u&kArM?Vi|PM{>GmQL{qBHNo`IOJi@t$p*Brv&i|IQ>M+#g?S3!(^H36MK-#kOP294?z5}Q) zd>a#ghr)Y+`vq+TqlRWpCLVxQwuw+SLUGZtWSI0<4_z@c>X$Hp5u^1Sq z^uahV{Sy0bF1#J78|%$*EUy!e(cwK`;Hi^|+?$Pd_E4M`Xls`&2P&hhq98cc0YET; zo$r`%e{ku|N`*9qPnyHJ`1=G{hGk`(lrSxSnOCG(7_&)rh%nyL)pIo(|KbuG-~xjN zbxMB)N_w<-KbdRK2SD{Oy1rh}d^|4EeU(J_MsV9x)2#y>R(Kgo21*T0=LU@ot&nLzqP4C~cA3^jgIkGir!SgBAsQh|2SP_FrZ zMYuvi5FSkvmZsfkxzlc|BSH}z$rUUBnqvFS$AF>5#l@)}027bL2eQpu4Xe-)OEh5f zpP*>jp3)O|w&_*Kg+aZH^han(3PYN~iOiLxvjJ*;l5LEX#3Sn01~AV?)&N}xI0#&W zcjn9h*PVV6(o-mxADf>p5Cfxh1Czpk-bXj^naCYj9G7Uf>Z{Wk&6-1&h}<)WacgD~ zz^7VWjX;$UC|UEyx_QTA8;poI)H5;dvri zIN?>?D>TRpziNgN&+wMJvrLI_I`C7+5#qaJ-CYiOfb@?t?L~O0qc?4v3R3@nK~H@g zNcts&`!&zuiA2v(5zZWzC^podz?MKqh%g1Akg){L63MLDmG4B zUKZ6AFE7CKlxg>yGo-^)JEm~Dl2b=Nc}R7@#79}z)SyIoVBmUs&|S#O<+|``@18 zJ=hS;HPaZJZgPvMR&Wr1hTxVL3jaXIV+vkvd8$>Xj8aB|p(0f$l+*;!8%kWYTAoaK z-U5`v>?^~qoyS_~joGoPI0r?D-7MxVkOdhj6ohsiq5!Ee>QAu?U#9dIpxk z*HyJ;RFWl5AZe`rU#Xaf>0J@U5LhaCU|0AbZ2)LP7};utAw4jEL$Aq^jz_WHBqq{p z9j1!z%<=x1Z>A-S$TcJuMXfixsRPIb#l%jK+D%DiLLb_wU%P;u?r~G{e$T#5kn7tq zKJ8L8nNfS(>1>a&;Dw}h{I7YTrQC7nW=p7Ziq-t6sGb-~73!}k$@2r*It17}=y`sZ-jPp-5m)6PQo@CfUIuFj?l?#GOlj5JP}7XC-lZKyHjzhm3zATh!`Ble9!*!B&fW2M2Y@3vWfCtLETOy|InQLld$B z$l_rg9@2w)rlIDJnTC>n$mZV>m#o2>AdO{Y6i9`Bgr+coE9iojzVj1u%09#RI{MKvw9XN2i}Pm%=cir1nx8JF2m;%X9ms>6n$Cwv5s3g_ zN|1M{Hsj?XN?R}I{1xnaWlAn`I#CJ{3a!Nbna>xvZZC{sn5SRmC;NSJA&tX4b=5{? zAeKLLj9?t7?p~jg^)dM0 zwWkT7ctG%F7F4Z9IeqI7mDP{I|5&v?I*MrSOYUK58jGy3AU zz|R(cFsyk3Kh`zobd3z}>|2C)m)>@(DUY>&O{1H8rP+iWE1z>(s);dM>JTir<_I;? z8j+Sxi^(;wdBaxwePaGb!r53zlxbHbS*lh^MI5V>VI}rH2R0}DK~%z%dOR*t2R&W6 z=xHEFa-q^a?ocp=`<|n z_d`+{h%|bok}92UvG5u~;k;HBaK-d2;kXhj!aqw&QUli7#>lN9Mh?0z79+QY9{3N( z$W=Wta(_*yYf$mR7`Zh>F?*df9xXBI<2mL}AyOG(AjZYvM@~rJA};S}@~O`8Fv?>n0<{h3i6lwjUjSlnZC`)(9amR$ zXM7>(!IdUB(X% z`*>x->SU34UQW~g30$VP%J_iVhU^@3LNAfw!XvS*q7adw47UWryy9$h0(HjZOUH`9 z_WNO?yUTWgJA_|!rUp?^Jmk}V8jtyxnC~cod4aJKFcVZW8kLxc8v0i|=@1>}DM8)s zN_0epQ6M`>M!=wP0N17pFtG|zqBeKdqx0oH61szx8R{F!2n?m(KUg{H2tfUjiQo70>Y9g!r2mIKA0naF{zYK)b%Jp zi|3S7izAxC9W5|sjG^iO{T?lN+jhmI#MnB-(J^-na_J1fmNU4b9|ub|*j9BjxY@9B zAgLbVDA#NpOh`*c>Ihh^2h=&=)rRI`@{jT#bt(6(j+x{}Bpx*a5K-J+v} z!f3)yoeoOY+*IOnpmKkI*WePuoVc=j&4xCE8z$JGYBo&VKtfy;&nx-03d$F(t`V;Y zIdhj=b~Q+DHoVvjc#ZZ^I#{+B16~du@2cazQoC?!rSw#t7t8!-+a8nCi%1sgyj zUfH_ZM%X^ss&K^tEg^{Z!Dz6d*K9z`!HcJZN(|_rXzQlBQXV0HJ;ns?jk3`Q6+K?E zz6UW-7rWn7u+aTa26Z)fQNChVmG~$JvY_RlrfX(gP|b$bOxHVujv5S*w-7Ap{bzHU z>Wvi7<75Qy>Eqgw_p0uD|0thVLZVJV#)&H`MbENo8(lqwbk}6CLn3X-sRF|f4PU9` zr}&y`!G8^&!Jxo@)MUt>XGR8l|Hacf8*G|pS7(nNT~rf_gAGaN9~F--Sjhy1_CIV( z{=Q`om34tLQOm-g!jM4W(IGifHarLgmsR<&gr;u!?`-u@Rqh|<2vtrgj>}`*uReI@ z_K=#**dRXx`p|N6qhNPR$`gw*(D`F=j+kRwiDX(oQIU&(PvPMYPpY~a^wWR zn-&qCjPs1kBw^T~cgO^r+#0?qkK8=S=NIQk2R|8_wOKoW<_oEEt-oo%sk|~n%W0{23Lw?E8w3iPR*bcdGn1PU>OSK5EHsVR}$jZ zVTiknKrTXL=)9rWyfS7YsQ@g5*NhFY#ypThna-~0$0hq(RCHC)y7?LNOnWqWP8eu2 zS$Ypj@bACRdsq7DsGDF8WYSlw=GycRQ_NoF_yHrB;|+X z*2x_#2qevP?CSI&PsGG7xnX)mmnn)*HU7iKtb) zqF>;V{PRId1b~DkDmPa+B9@3)XR7bio35gXjJrgBWp0zsjmHg|w?j^9wZP)sgU8%K z%Iofb&97q(B61G9^OFk_UtEGRGa(yaY}1R%O*tCG7Vq1H4(xDl*Vt+^kO0pq7z5=CCGBq7z6p zjfprR8;%E2Z}R((z_h>VCbdsDd$|Ix*8ll`R>PF*U4H+&bF)8rdw14i@@;R9p=|F7 zp7FAO%Z|Xa_I@u;q)tV=d(u|{wvDSRw&JwW0w}Vdz=JNks42uSe2>S&#{2AeEKWhe zYGUP0WNrfRl>~g&h1b0DgOsgFI(0I5gfhBFEEhY}!wA)=T8^p6Nxcc@L72)*`Xx~+MFf_WR4hNTSotb*SKJ{z92e2SJTpnWEO-2WT2SHq zxz7UE`oCEppgw@0s|zYts(6)+K(ESwBPz^Yi!=}&m~IRLJ0%!9Ro=aB^T-=fUGW+l zR&B2%+CFf$zc&5c)AVp8f;& znl1`>JLq<5^RInOKc zl9!i#BC%uU(3J&-2wjH4M0jE?7__7D=w?GZzLAv2Hxiwg_eec@0^GKLv~HgA^;+9@ zKtG3pNx;pQxKcO5+1z-yRZxc&!S0*{P{ObY1Tt*nFyVsB-ii~D-3!x(q9<2+d`d$O zs~N??_oXcriEUPnuger7K*%QYTi-}{`*^n#)iwLJTD}q0uBz$wY{!Z>^y9Xot86}s z-#=>$fZ2@5=-X=fcnb%A`H#;qpU*P@yN$@``>J_fwdG3wUXZT^UtKU;uKXQ&@ClrW zx4rd=-nP~0l(wO~bl!%avBwZG`}oa^chx0xpZBiY&%7viZG$h@=IyYB?p6J!e)h@P zFEZ&a3UU3V5Irf43l}biuyu8?Y zZ~EVZu?;@+ZM8h!_phJ4{q#Hb@$0r+Z97BY-3)v3^^>>9UhIAE&8Kht5p=HFXP@Hc z*qvAY^}e>rr^0#VUWM`8@}kjw>)v}&Uehf{NO0_S|C*6cg;UhMde^&mPS2x{-Br3b zLCmGQ-s+hmk(>8_DCt;1_bw-#LhjYO-u>zA^T@mM>XCPO4W!TCR!h9%yzbxVF9HAW z5m^7m#I*DN-dhS8y=}{HtECJeeA||H%a>=(#@Ul?>;3DIRzGL7X$7n8EBXrFjLAp$ zYNW((SabHn%a_#!I6UoJ_8L61t(J8AvbuQ5uG!W;QT$_o%)Y zf8}jkdQZP?%lLz^3B#tot%}RPp`{Ai&jef_5qW(>>kXPa^~I`c>PFC=`u#*yrTX(J z0zuzOB!jy4eA|9_Rh7J{bgAFahTYJQ>eqLS?aT*ZJ=;IkUuO+1S5&N?&>da!Et=TW zt)JdLSAYF~%$A#~y41faak<`BH~4cw05NSl1b#)j;|;ywCFpUXvZJRDv=yYC^V^?+ zkDCVarS#r+ZpcCLFF3!Tist8nyk+1g?$xb23oQ1y-Q48*JMwybeag$Wm^0S&&2(Rp z=sf6^5nWF1W&dd=u6e;~T~vMKqn&4MNm64Ecj&NxBiyILckcl$0n+~5Dvv8uM+-Uj zt$+OkVX49VkmwIzz{U&heKGvP8(P;lm00!F*?-Eu9d43gHT>;zaX3u3tQkEzc5)NIQjO;?+w07a+mwt0?Fp?vhqFTecq z@YSn_PoEAp+0|86*Mr9+GBS+*7X7A?LJFMS5?T5?&I0h2!ON6bAjX~%^x*J<3{}635aGYBe9}G z2LP8h-4G^!!>f-5(T(F?QU*qU#Lv1I+ovb#J__SUALWMb{l&Aj%i9B<2QudR6^?_| zP2oJ427hu)%UvHQ`ZR{bHJOy?!Gan{0>Ne1ty$j9D;&A_Pb{jcl9ED3hS+B z2E7&_+Ls^n_jPecC$}2~x6cPrkUW~0PDs8?P}e=L4}FPmbW&|f-Uobh)614b-jvHBOMWc4BL4mXdVO%2)#8D=x5v0$gL&+&j zNp?nm8Y3q|QZlxRo|fk^X@ZgN!E-aj6LYqv{Wr7}YizoP51!u#^VXUwCaf440{%m| zBzrwmbt^Q%7G)osBeUZS98e;!9qHlFbeZ6kYHV6#G$$$z=3byISyynU=XrhUC&=6{ z^DmG8CaP;ekM!Af#)6%9ILOx!Pa-ooq^fG14Sn}S$2lljU*oA-XO+n%smU+U>q@tuTOKJJCJ|P z)t}N7bgH8v_@EbHy~`m?A)op)&x(RmYEj95FMJDr41(wGQ8IEytQx^Cp;t z@%<)dF+e^(0N~^LO4!iTlht6MVb!shr7UUj2UnxBl9S-dPmcR)m{Wpn*oOU;ZD=xu zDe*&DHv*(NDHZFcjoDk-80H0kRL}_Nn##Hdg&Fstd_~7-PPTJ^*jMR-g8?`KCp&wl zD<4cBqWAR5WzPvJlsHu^({;TN_-W*V5V56DOP4=<8ik?fUgBv;Qu)Fy1!x4l)Kf_G z8j64rFOdbzdXRdR+#zq0EBU6YQ}+cleh*g0+U{epGJZB(wcdF6cuzxr98w7>Du4>PIyG3*>4nLe+(*RsY>mLkS$7h6~^VjlD|~<$U6edgJ5Sm9kr_Dc2e}INLWki3wF| z$tyY6Qe`v+o4B?-RL6CHBUmidz?d&J?P^@Ff~zRR!yC10L*YLZG_J$LlY}MKuMH*n z$qUfvC!=v~DD;v)0C#a?_u7C+wLl?~(4^-c_e}Q&>uFE2&@hbXDjAyV?QKVu$sOaDkZ`C2zTwHT3OzmbGNSED z-IH(|p)PR^vf7e=TVj2}-IX=wp1g5+|GQUfi)?Q6yRC{-$(>T~br?G#p)3}{Z zI`yVuLc+ua3rVlv>bbagrn;jSp@(oGPknvTSO4ruhp)Julp>_ixo30 z7c1bP!BjUyVL${6&%KCTB2sXv!!*W^MMaIG5Jin=n4qW$3=a1gUc4ayIfvPUV^Oz+HffutdtaGr|MM z#g$Wc6onEObU}xc*4&WxiJZo%3e$_YR>GBt0lTr1L2~%JOnde_)zqq!gzZeSFYu*@ zhG2z+-hp`Udy_yvNaAh02r?*x0aGH@#8f6wag_#tw=sgflpUwNX^}#O2KUAv6-6mB zJP~EbG#;Gr+?fl9!@WoQ`vT9M`FFx|XHI#ZJ2UTj?yY$4%=>wG?kq_0T(UkE3pVwO z#Vq0%p2&0A?J_)7g`o=7fmkw8#ABzmvWOrpCo3lzp?TZq^?_C^l2w-m~moJ7+utFA7sE=?4J1lPuM-*{1g zUt@E;szT~5IU7jEaQsvy=9n^OkCGv3;`y=w_+w^?!!uJ54T)K58zo>9*ffigr@A5t z?^_WkI`U;ufvd9nWVJp$bwAKPLHj0Q6A`k(dM$lHfk3dn(K|_RaEj@6(9ELs8B=zZ%t!umFX@>!S zk{p}9tAPn`_=3s<_TX5=#bJ7(}|>v28;^ykkG-{t@x2!nc)!5rieHH-?i=S z(i}EnKE!OpE=!e0qAz!YN_`f3aMaPFqbWb~*>vS3+Li9&HjA zfOix%KISancL8=-roIQm9^9bhbQ^$e`)OjT4qvbnadiy#-E=S~4Jjqf0JV;=qt&o#hN16tq7Vm0QUt*%h8$VPhO0i_ zs~_xXXf|7Qe7)iVznV+rntVb_XU|MMk|%Nn--Sb$QiFnx%VhYk-y+F|g^DGFqQiXN zFj90yBgj}Bp~E*)oe=OD}1d^g zatulj<9$T781f8PvM>&})X-2(!%J_hL#U2c92h3uTQFqUFpL1G9Jk~wlYQkw3!Kcp z3i-bB;(g^w_m$7~m9tzf34w^&HyJhk>KXw?99#gH!__r%fFEp=6)s38M->yj&i-c%sglss@g90|GWjR|=^PR0cc58oguhDu_FA>OLaku{FWH=kXy z+pG}TRp%gow8J<6Zh{%&o0+03ty5SfnbH#o3I^hyD){#K>t?%o@|>48!N)tifVeqD zSL)ST7vhgItz_x|MOUsuZ)EJ(Pz7LW$pwX}C6~m@!PvjfG=%F;V3Yud^(hV~7`r4# zQ2-xh<-d5|@X~wcgpiTz;$5~sz-j=a^o?iZ!5J`rWwB@H7tLqQ3(~Vz=EcZ$F|2jd zpFPDa?l9orST40{*u!p4BzF%P83RI>Y+%88SKPh;TbU(;xH<)2Q%-Qy~ z_s7V8^aF^@hcBag4Fo&S$ll~cFfitzFNSbS>jHxuXKd@9TuICRS z;xw*0el5bn-DmvuN9lXKnhwFb7=j(}IHM*)Ufft8lI-}eiHqb`J(aL_7u3Uj?7yHD z@}KPClJxTh|MFAZGslic0Az>el#Jaj8aghys_r6K9Gi{GUa3(b)GR+J^@CNT5v}C(~+cxCrskUbkVI82e7&m@8JGE7X>CtxV-5slE z`eDLaA(otomZTa7*o0}+Yloo`{pLeGPeD5mfDdE@EHJFd%?`BAj9 z=B*u5kA4GXjkThFNstH-c%>qLI zLj06)(ByHLdHm(nwed8mbqRrw`6I_I=OiSGF=+>CV2hQtVW+Modba{a71M(Qp?GEv zoxx030@Dq40_;0oMMgj*n(o=S+JA`(1ux=*;IKFsJ>bq2;8jmJj~(BMLUN>hPUhr5np!;I^mIXoM&=&s#R+ja*18xVPcrez)1=JuFOSo2(pR8K!jQx!)w$I{XaOnAmEcsaD-6Z!|=)h%^Zu|743Sna|pL} z#7?rpnzl66Ir%#9E=J9NJiwEf$H?9Sup~M168%wyyre9(B_0I0k}Ch!s{le=g-HFC zXTWZuAi4rc*}Rt6kIVUFl1f25r#dSt^bF1E4iRpZm2Q_L2N-YSN*kM*PERDs&j@45 zt76&3NL%vN&YqxotX0=pu_bj$``g$@v#0U|zH1Zo75a>Ya$m83Q05~R3LZP}B(5`0 zOXYt-zC4yTHh=pxxZ43oc6DqB!{m2$hx%*ROWB~w) zE@jRnGW8sP`{%I4Eb$jNk6zVlsIiasYp7nUU6W;|M?3X6aFx87_OkA>B^&-$PnM+x zl4#OSEzhNqzi=1^i*71dc;w^p4%seC1RQ2faVWxy z6K*ar^Urs~%s+0x%>TM)=C@L|s?0C`&StBz!E0QMW5>l*bdnPqS_O_6WBKxS7 z8bjHCDCCk;h-uPm6$SFvK=(wQsxZ6SRHzm?Bn5l>JqokKiFxoj2%1KQYdM3ZKH%fU=% zuZWjw4*Pw5$9-`Z2~hHqfk{4;evtG!?k!7|>hA}_gVit#Fc(TbQBpU$- zW$9f4`XArnSue8mPDp(b&%8X{Me1=r=S9)uRN{-czdZXzra76VCP|EudBn40@Y|W3 z7_uqKr^FEHQ$CY}>{%o8EJ@tJ@1(Ogq&8JHOGELjCHWdkQA#XttB_+NS^LGQHddB@ ziL*Tvj%+q>#(&7*7AML04#QuNJtG!}ic)Blo4(ATiy1cZoHl7`iXIjdR0*YA%L+DR zk#Y_p<_ynvQb@v)bTO54qf|9wCXS?@B=JV}4k0Dko3e_F@^FarLDFsr1G1*k>7>ZB zMp07aM0npVC%i*gb1IKJKy77GxyL$xDf*LYkR-X?E0sjyBx&^S`bO`SYcy?5s@dcg zZ@2(zL2n3v9nyBkm>H60@2zk4LB826_jdY^tS_lvWJey3g!C!}Sk5|?HS0*bmdY_n zZ-ucylgUm-Z}N1LY)Z2kCt0&}<*g z9--M|4NdUMyc!9HvoB`ZaAK@RGl73bo)ii?p!)v@PdWHAij3Kx5_B!gh(ImhHKG;h zTI-a@rSq0=WK4c6fj^w_fL>UCpo@jFv!j$Sv+i;?O976Cgr$H_V=DI%K|9JMILI55 z*Wn!I*G!jTjRE|jBF$d@3IPTW!7HQlO$^+*Vh!Q}3$aN^00h@F5KSmvLb{7`t3&rB zHTSB1AfLrv^~nbS{{a8>*pd=tpuHs~>;dbM3`3IEiKnI&QrG!hXw6t1703 zdr7tL`3%IiHQg-x35g5A>|N4KNiDOG<$bVLV9IrAY6i0Fbtmm$I|=W^I52U`8wVyn z_3i_^05XwBlls!oAbe$B11u~U0EudssogC|LSb==y9|i>{wP!87!MY4FzC-6i++D*0-Ij+BJ`= z7o;w@UZT*Sk)V1o6klD(ku|0}vb+R&Cr;vUY)glgtisYJ8| zY6(H4hiPJ#C9a{6|K|!L@a0ZcPo$dE=~v6`%Q$Ma0$Gd(fE_fe;3>AE5Eh9-8P%b8 zNc@DM4x^4>B{)WZV;iu?k9l=3OCx@lb1t`9+McH9WlVh?qHfP(NwL3QMfR1JAmSSR#H zQk2KYJ6#nzt2zcPCn6s?R}TBNQ@;j+eqa~`*L|^Quq#cQL(njB5q#JZZ;N64xUH1GBSm{Y=_=Vyzgf|?qXd_j$agEqG02eYf z{?b*0)W2qbgqEfeGFpT@?)4pLbJMswK*2TgjatlmT*EPH(3*X+2H0vglMNeBYVG<6 zZtIk@vk9&(#nh;iZmd_BL}|Uk=Lq|=$}^BTUwR$&fn)2H(~~X4&(eD3)D00kNs}M( zar%?jQK9$)$JW-I;4@l@{CT+G%*|eX>xIOfJ*As}p=WY}dMi7Dr;pN;?po!`#Lf@W zFbau2qe2fw;s|Mpj)*_X4+b|z^CB$Q+ikul}&0OzQc&vtCS0qp0ST6BhVhe z;z6^A8k%&-Pa6~qlVKq!S=nQ}!Um%o4F)r=Y~s$>3PJhGrDFUNdqt-K3MpC!L)u!R z$&HbJL&hN*iFaq9k#KB8vQ|8)p4Pxa(G`6ceKBzrb>u^i;eCcsTNBKOZ`hh3LyyeW z-g*+xM;{#KuEFndosVOXF9E5V7mG|1J>bm)vi{AP)Vv0)&yOSj%itci>P6!cDG!$TN z>69$RP*rOvoK-)Enws8v^y_r%i2>Q#5;bbIRATTH*->;}=j$^~1y@T#dg5%|SG#DJ z4N`-TwWCJKkRYMNE-P`>AbDj{U;*rZ-C;o%L=DXh^(M78k|5jMa`5Bj;7gao)gI#A z3ZG~yMlPBRk@;4b@E9zW_5%UK&$l~~TyF{+KFP@OBX!OlD0Jd;roIUez3oDZsUB6(01S9-JHs>7AYx=HwsTlKvO>H$)@GzpL#nboaY zfXP~nL@!Y}_tF&ro(hr%2BlcwTD*1$h@@)lBl<@t%Ivl8NmKBye=VCQ_p8zA(}``x z5TwcMZWNP~4HT2@d;Qw&^lQz3pGd#fO6%7qRKM2dYBdg^34IdY>fgP7ZCYNxHv4t- zYqPA^^5il(5B4QK1VL;wrbgx4+uyT>_VpHVsk3UKSE|(Mv)F}m<*D&<<*D%vIU!z> z6XKclgqXq!Kg_E3L`3aW$*SX8g9z}vVUEz`i7e@LUPGwBy18Oq zYbioE107|DK!;#l6D-oe8)DU^FyfQrB1=CFBPXG7KD!{Ha1NOw5aCSmQ0y6#mLw%( z990MLbI4kG6rMa$gKFr1J3|!?7FR2R#Y)@rzsiUYl5SASe7`K=S@0^^mF@sf zcOco!>c(x7s7nm;PRV{Q29Z&Dizhs%VVRh3$&fU;ia1CTG)9O7GlCmFKtE9x21!{V zi;MqW*`?OXv8N{`q*eu_=Q8C$$|zH=$tVCJ_2rtt({`0fc=g?XGhOX2k@B|}5fR7z z|Nfu#~O_5CIA~xR0fkg*lsyg+wNB z<^-4&+0d;D0d-R0p1w5P(`PZB?&=s%Q&hEN!g?X@Q`sJ2Ux@4VwRPd2+WZcpInyp1 zr*|)Fo+L8V=_h_8iq{J>)3R0*C@1L+b6{G~A>4)HY4hJLzU_>e8dduZ8XPDRs&> zIBe<#?#7r1;tex<0|t|N7l%h`4f$sErKW}`zNzUU3K(!3oZcCNK3C>>RkEeD?QMDk z5U-A09UnS>yaK~RW_%rxQ(a{EGu7{@Apk;C#8(Xk)B+F%bQp*>v{oHCns7A-9XOf? zeNf26O$3Lvu3>SYm<~bmB$T%5&}f@y$r@WMB3QL2ly3S^eT_nBuu*D^-~ z-d=oEFm+f%b8)vbL=QeM-KD0do_Cjr^zaa`%Xm>Cp<=QC^>~dfg|!RRDymX%i`C02 zjF(k^eW^)+(52&oQ4h3$F-QhgPl?P{LoT(u+1CPpdiH}bIVXSL!!@pjYvi+22-i4y zDxTrR?qi}KTGa_=J~UQ#6jM}U7?SDP1q?Gbm~2Z&cIC@Yve^umzpf0#?TkL}39 zs>I*T2uW-~k~Qvs9Cs9j|NQI zuE`gYjcf8iLzCx5XAFJ-J#&QBIb?R$M>Udo?sMe$*jAMbcBN=krO47h$6D&kvp27Q z6_gY4vYQ>8qhh|DZ0(x3&uiDZq7Z#P>)Uu*B@&fR@t(Op&IhcZueyYV;71Uej125-_Aso+Dl{5i(^>3Fve1!y_#r zL^ig@`PQ-T3CI0XiXr4*2{mJWp>_D1X1-agP+8kW0E|Nxw)DM=oQl<3H#lvXt zFNVSmD}q|t=rwiF1Qk?;=x|jSYfV9XS&`He(O^JR0YJJ0h;;^FZ1@4^SiMgFzA>kI zV?Tk*^rCP;Oi2imVeo9Sy5e=a3VP=G!xwlk!u};mT}Ka)>A`~r?(|5Z9SB%|AqUAa zP=Z5Sf0!Q-uP;fX$A{d`r|$$tML<7?4oxOZqQF7&C5Yeyz(i8wB$~0_i|pZ7hO6$^ z>NVKI?+rK%1r7!OPy{jkv$*nz#DZKYL|LfOLzNh45=$6I>f}{5e56j^BUeL|GPoc% zk*mq8>br(Ic@JkXh577$l6T_>2qDHOubcg&o z`6qhTeD>^`X3spNO-}+-Chs*6yWH(<;A_jxQ^==aG`T)HO8kUuKv+^T zG9(lwrP%oEZcM%}H!%7Bd2jN)oyoWU6PbK#X_N0uYV!S)TY4M(qMkB;`8LYiU;p}b z?5}@`@eR8Lw!`57xyGa>F-7@?OI+m*cReO}0s|fkP@#4xfge9|RLNa##nK)4INKJk zHm5%UC{lv8Er-xhM0D(NnvNY%I=0Wr*F%2sC`HE} zmZxKTzYZPS6X;kQuao(ICXd(AGVWo{b$v3G%jAnHOUnhJsY|q911I+-x^nKsqBF~%G4>=i?=k`0UuH~R?YoImZf_8!-2M?!%I&+3Qf`-tQf_Y)rQ9}C zRElZCwzpUDppa9*o*A4ndU}1dwI#i;VoguTuGg)E!pFUPK6opCKG+U^9zNJk2RpZE zh%}q}#iBjn7lFtJ+t!_%)mcl*u-^8s6C&LfL!{f?`w;2-5b666>H84rav{>~B>J~) zWut$ovYAHzf{95_?wrE!BpBF=OR|FWg?vbGT){UB2_`LRW>ClSIAjEq(hPgz?@Z7z zbtSiP@kb?2Pwka|@x<*OI6bvV>~MP|w@2Au9XVVaH4J7LR&a+Dl*dp(02SB-+nt9&X!><7^{Cwc=Lf<7^}DAQe^P z-HB{)3ZfNs`SWf*8Zx^}laSYNUsKy7q}o--HoD+=2A-<6rlsO#g*};$mW?G~QUcu2 zJ$3Rz?TW#Fvj^81cGXM9IyDRXyudgqFpGz0WCXb}8Sy^zLLFm7oae+s9bTvtd)`gr zT8G9sSL-la>y0tY)q2AV-Nd!dwzntS+cU=X{+Pu6&uvrfAwQ^EPqd@d=z-xhkP(4S z6jm%R8rT)r3oFEXuL4R}$HIC=`K^~2{&iRFkqBgeKFkM&5y+y05H5=4Eh1iRET}z9 z6306%KqpA>5(^FPo5AE^q!4Fp3Eo`0L)|j9@-^v>EvspAv%01R|v*g{z_CzDRzU{*B|3{Hi#edY(SHAO+Kp zmdLT7?yl#C#ErcEh$J&>PxJ5r?f&|lti(CqH`+}J&TT=);*5#VtsZ-$*`;?pa7G=^ z^ld~SV|5oINxaca0?}zQWY?UdMO$#lIQB+=4z{-xL=Zon6^NfELHv}UiOS#%!YZ8} z33Itg!zF}O7;37V7wP(CGL|`ixVqFIt}gn+)rsFL_yH0|k9;GRGTfsB-9?TORB4cAWh5C*tHMX-phiLc2VoLz2wKm$7_KH`8&o&2; z1r!(@JEtm++rz#S!bA}mymYIfVSBlX{K$Rjb(0e}HM@z!%Kj7(#Ho|MyF#7gNtip%H@GCPo8)YWm7T_H@9_vyIGu44Y} zJg<%$@bOo87F5ZWR85Lj(|#u5#GBcISo)<(^ZgsZJOXuP`)_02$sLEiS9nH-fy0_Q zqOr#`+9xWHxh3a%jUVhiLeWt`IaVYq=vJM8CqB(5y+J+6J2bMmp`np~(SxELqX$KY z#qGE;hEQ;9458pG)n!}-5DDz^NNZI?eRYIxNLKraIObh-%Sr=HVr|~Zq#`FElj31d z-MZ11s3qPDNV~@5{~gwyZe}Qiwb{=^;a(Of+2a>3;{~E#8tvDq=)l+-7F)c|GZwEP zIS71;AzqVpZn$(^f^!62AsepvCCVuRGOG0ea>^KV#BHPw8JFbSvx(*?k!6b#=j^DCJrpv@t=BM-5C1H2HJPgoUL z(K6O7wU7WyGQf6crsxVGl{@tRL^GwZQZ&n2M^a44za{}xQfQEWUt(UFZ4%{UTnt*pYIGkYYZj2N)l|L`uJ(7OtV6zXs@oc9%bKD!C#}x%7+em?oa22xC$bG)&)_4L- zbe*SZU85i<#5u8lTFXLktklHWByG6kxe%l{h=#J+={#PIRoeTK(|$6cLpE}N2D!IeJorVnr>tcDjr*+6_tXCm;>#9$8}De7)JT?6LXXFteN!e z2`vt3Fe?lfgMu)cWXS~;H41PA><$&njNsOmyrV0KT8i`lz%mSTOnBIh4Je-|z^(56bg<)0(GSzbrfE?6r8ejVr7J?n@C&!V0{Jv z`t&4-%i|7g+@B=H&|*j6x9WCg~aX8#YCNXezVE z9>v@{c_~G+P6#$b#E$tB{Vi|{iBs`|wP~B$U-F&ILrk*X@aP!JYg*cB)XdNzT3(x^e~p^Sq@*84qIv)@T@$P zvlJI80dLB}B5`3bV0hohttXXNpx{Q_$BW%SLDcDClVEngF7wzCD@hjOH5^XBq@M9EGZON`+x^3yij0{(OT-)7!q@ku|xa#g+?O;zs%|S`$;(-%{U>QHBT9u5KW!A@% zmu_*N0DW#{9FcE)Ji9um)vlMw9GjuJ(rcONa;ihqaY>+Ivzs^AH3#bh4OvA*@ftfU z6fLJoqGqzO8_03c+pBedpPp5uqG?81j|w^t`A;-?9WotI6KY}I(pP9+#SdjB6J@lr zVwUA#WP%@$3mMY+T;{YeZlM-NXaMM7TqJ8oyh@UW1W|`5=NhucV2!GBmKti>(%sV` zX(1UdI8CShy_DO{Zt?Id9fc|KfLxxQ=oN(|nO>*qc5LumNe29XYON>lG0CA)N%V#E zQ#7^8IoB-bS5Mw0*tr1@v`{rz&br+lY75Rb%y-M&_D#7OX=TQkZXDQ_#*;tDOoBG9~$q^@@Pr_T1()u|@5q<^z z9P298&o$fk`nh}k+`WG8UO%@oJhj>U3in8U@@CElR3bx>(VU4uFmXs%D*Eg2mLWMM zeHgxx(}BmF4$h7*(oP47YHV>_)Ru#G^dB#*l&_=8;P@XR|RNLZOJ?z^2&*07Mr%UWhGI~TXnuh zX~lf)^0`K!CCKfMW&oRq3I*0uqgg%uA&q_@QN#3*3Q=bO$wV&o=1`J*q1n!;P;sn6 z#TgZ$-Z+L1it}_O$ADFW#o~ z92a-bdp?y{tvva4R4Y$J)ylJb)ylnU@GEn4!W9L(dxR{eHUg z9Pp0F{(qBmzzcHylw3cMI6@&;bcOPZU7;MKd8V%RgE9?=YUez|5dwf5<_8rKxr+Kh zSw{1m_(8qneo$S0=LNrGgCA1!RFyQEaI|=TG@j+rgc#KfgBS|T+Uo+9;=k}M$bmU7jmsj4P-;xQ6spGu8k@)|IMYWt!QHobqA4eD*5eL8DPp}k{Yz)W5~usli3wK0iR@V;HLO=(ACZOhD z8fyMYe!eG<>g4(}xvr7xkL0@XolF}q2{cD@SJHMkru+#H_X-}?;o-q|YFI5}bJ@Qe zo6DmOY%Y)QO$WC#9X$MbOb0E0oHiXiqNW2LEZqvZ>ENMgI$*a;>GAh}9X&OY=-S18A5VbS}ES^U8N$uvM~3Q8MLdIm=G zK&2*8uEMd5fT?i0EORAvKUyrfk3{awrP$7xo{Z@9rQ<2QJbragq?Imz#j0j>(FBNP zQ(K~uQIH$9ksUuLK7Q3&6GUpXKoJ3ez@4Z4{S0U3ah^jmE z;SRu{BMMgvx0!@P(9sbDV6jhvp=N+-qDBT+O3zEsWd$)sZvty-qaGfNu+RKTGVP>N zj>1!{#_2{!MI)BW+1pHi2i;)S0!+JtX#kDfLx)tPq#rSaK7Gp+9Cv!R^N?|Ak~EPk zw){KciY=!+S8SO-z!Rb6-LWS^%PirEkS?^&6QLE{ixamJCtA@@Bu-cd3`&a=j3WFB;som|6DPX&ZUOgh0rzeJ_ih0zBQ9Eh_WFnmejqT#xQa}~ zMaz-~Swu!a(JmlKEb3;8v79-!(S<@iqx;iDV&n-^k7I$e0FB1_2#v<(F&d3uElR`r zx+smtEyFZchhj9oLoCLZO=2;u^064v>R61%X2BRy>0peOCke)AbvFveh~&W-rW#3t zF|6+yjA6yW7`d^3Zn?z7NbT4jlIUx68x?75z}lTUzupaEKx+fUfL159aOs&T+}>Vw z{tCG$*E54tc9yt4+S-!dSFxriM-H!B35Aaj@6Uj@I|JVQL}$Qp`V2^;?%C8Y7Ofe- zxJjJ>XXVd;zfRPBON_d2P4c#=)>xFli2M~A800V4z#yc5`QRDYtM(7TGf+&wm`G+( zfScVewn8<1aHO-*>Zl>|gR1pJ;~(9sA=lWdBh#RqG2U4uKOhQ>uzKU0qu!sd$wCbz z3+HePJn_IwEw%9up>q0}2w8?lcOMLDEEz+2FxIIT$>g_8(g5Q5WK6@r6Utd8!l3dTvGh+A*e z=B}E501?CQJv9l)QL)kL7shN@Xuv5^>q$nN(~Y$`U3tt#w-}xHD`Gaf8^vrS$~$Cj z7PQeQj@qzFM{QWzDuiQS9VFc;7qt%V{2bxpiCue7P}#G;jVL zg#xip>vPt>1Ymi6kkC2CK8q4^t0Rp4)01`ij%le)qlMBTHExpRPW!fzH2y}BG{O;o zwsmqhYJ;~Ms1444gxcWZuGI$TWz+`e8>tOG-K!05r#5)@6R8dUPOA;xQndlchiN_K z7tc~^gQw-y1}DFc+TcV~8@#($8{Df6?$rkOYJ=5kgBRZc5V!UBe;Xj~dE-3oZpCgC zJ6Ev+_kg$MT&d`3>rS9*uP5S|2pjdjEaGq+74jVbZP7ccXFmxPivuuOFdtczM@<8i&8i zXdM39NaOJ5y~g2o8i)E%q;aUFH4Y!C#^Fz{XxQZ!^_0e;arYc!x4e?$^RJ`i_$(?p z_U@G&_ezd?CC9yzqZ~AC>mZSH8)-Q=gHW56xGl-O3>*}FD8YfEVsaV>s-#$43cIOw zuwK01U*Bzdu%xXjf(~O(*IC_2SzC%=WPqZOI8}w))^1HsKV1#NcWQJxgxn zYFC?N$p@eqK1rh#5>NOE;QV41pa^>*v^SH1o4Yu;|Z-{kFZdpp;4 zhbJkA$qMtzBLB7ORF7Lv3Rg@Yqj|w}>X0&2qhXYH=?k-&RZFOI0}Pn`Yp^)Je>n`V8OP9W81cE+cqb5CdtH_=)|^-i8HZn z+nCtq#C&sKy?3it@9H1Wr%u=2-&#GbVQO12_6Kw-!ctt?SNe~EuyfSw*+ciPrAVL3 zwz#-n8UvF92J*&fgxzc>lCZqv!;4hQ>eR zZp?*r@|;EikFCu%`>%f^bCK$~>Q}=DyXcR)AZn@0KPu12kPm{M&-HGP%VkFRaQZY7 zA4_p}SGga?T^*%ne|s1I*NH1_xf)azB%&1w_6~&%bY)Xa(_%7!qs0AcZIgM~jMF#C zYtIZFwTY1V{dXqe?ya=frSBM zgXpN{ePR}LNCKkZW}6(J^VH3=+7rc_d|8wNR1LIWxLf>o{_ Hrtse_5<{=DB?rM z@Rev4KxN0suLaQMa}KVrA2^I+NJjQA=6vMBSq7uuaQ5Ow)`&9_^?l0tnuT`Rc7VxBc-{U8D2uy%ny1@2LquZEA=PTyep^OT`oP%2E2a%j zyvQcs#iJFJT)>o!I&HtRu7mg43SJvF8)2>4aH*Y5KQGK0%_ddWJVyww*D8 zEpZ?R<8u)L_XEWzm8^DjeIY|U@eE%}@LdIgGWt|rXEB!@pS}$fsT0yCvKl1C5d$&- z7HQDt?+=}hJorB;5CAO;qe|^D_PsJ-J5QG8$y4yKgpgETAisVrDgK#}vJ+oy(?TLU zr_;deNGo<`E4#V#%2ox@MGS4_GQJ zL|4aX+j6{Bu(rJyy*@LRNs8k25n1<3fK2!8qkuXol#$L>zQI(-*u}4x;MNp?;G#}5 zzoR}06m&f&>K!t5NzTcLA)BFgFsrAfhCvmOX)VYQPJZCGRytC7LUsSKso=zIqKJB& zQS4s!=zw5br@~0atg+qY`|x-%peLeBf(>`Jtud43pschl#Es!DYM)rnd4iCH?{gL7 ziOKTQR87LrWUlX(+)Osr2zdaw+JB6S|L$DbYTsoX>VW4Xr7v+l>s#cHWC~qr6kBxy zSIW-scW}j%dQ2yO8Na0LrK=N{{)c^?Li=*$VX2;O z&_+@b__Dttf5qRCzSn!&f^4~CI(Y(!t^+?gC@CIk5y1X4Xa>fZUx8m9pdALoi`!pr z#wf332x4D~vZvEeot-+`uK!3VzLIa^n2$zHTeC=*gUD4cK{ir+3fkvhOj_YGqvrC@ z&4$t_*sFw|=mxBXvr)g9<0pDE(qX(wBD(SynR($ZCT6BL;4?a{$M#5{NQn|w3$R%l~aF%tFU?-jkXrY~kN4LLgb5qNB z&_%CQ0kL2ll;2_!YpaGaf9tw374&Fc81y74iy3>yErrQ#c!7By6-u1UAkm|sF}QDm zCQt^j1A|h3+s|5;N$Q>Q1F5CQQbTBAXt+=dyXpm5kRo)>QKUx;YA8mg%Q3+y~c<_dp?GXu=-@VI%5y1 zi1`j|cnufXgBl_xI;40LqkK?UZc>0Bt=gYW&C!sQRlVkEt|y)i!)i`4c6SNS;(5#o zGhxMXR<(bSD7*D42N97%wp6~8tZr%f4jd2u)Rfg3Hvp_qOpQ`8#b1wLkr=jdL-Gs6 zbbeD!1VDU$UaCIkRsy^&6~G*v)p%kx+4;>Ux*Z9vxTRW27;2|q zPlzP%fs>hj#RAKX>}8kG%eR-~5;C1ruq7b_0 zu3_Ki?=L{{y7~=7z5V+J)Qy%G9pY3zfZBGif93{u5f_mrHxcCnPi|BVX%fWQ0V*W1 z>S@7rR-6_|MLke0ia^n97brenC+Z}xV1D3(Chtyd^QDu6Ue8PYZa4xfir8DG+(>0o zhbAx=`8?z4U4jhnxvvx@m-#bpW*ORzPKtFpbJ+B&aMi_^I~G;?hi!FC(eiT66(vSH;q5ZQSHKZ-w%}{sA=5Tp z`;+sJ+CatrA5Sl+`;ToY#i)>H2{eMbZ-8=;r9j^XD2~98X4v`a9<6(@VGr}d`3qXc z+E7>fX+|hBmKghv65 zQm`(C?BG!2pSFbp6s^9n@Fl5~47<+N$s$u>Ek#3i}TTKwizaeG5 zCBTP$zBh!MFBX4xZubv)0uC=-osVw~gT1|ksHQX629DK|urafe+RKNGIagLQBDE8h zqFvTMsNfL?C)r}VYhOS+pUTfxuVqf1hXa zU|samr`gdQEUPJBJa0eMb`EHktDOuVmUAz&cJK3DTLfou=alLWd}_kxX@#Fj0ebV2 zKUTatzXyQY3ZFv)TnRVPna01K&t<4YZiK%=yJGWB=E=%VN$uL^j=hq*9my|$VQjy= zLNgO`RjD&z7et8$+f%w(1}msyB*SGSVhSK?SM8L;)2Fu*7nBQtMKVjL)u`&Ek%xD? ztV&M21SZfPrQB&{@}111&32!RN3r%DNLiib^o~R|_SeY*_dK$E(8J4z*X|J=0Pw=K+3)`s6zL z?LF#YJTpWIOLM-j^i62O=w;7RLcL&rcf#`(zaz@dg8@tx$};WXjLwJp zgbVE!?rfAu9=*t*hfF$T(@M0*j`uiP0Q7d|o=PyLk>$^q#WwG6mQ;1;T6_g8z&Rk5Co0_4kB72=&(hI=amLJ0IByxA>)|+#2Pn6pcA@ zjX4cY4mVB?#5mI6Y_K|e$1*zez@{Owa{4kuaOezu*o!2v7~gOG(5NP7 z#S#!);Wn-6E1!pCe8E>}#fiZ>B})VRCAQbKuB0d)&@e2)GFhR_{vodl@jG)T(nDZ@ zEsJ*m6Tcr?&X4&MyD;NGC2Hm704ht(0YC@?AV_^Nh zDBw%v%t}HcocHsy_GaN9uv+Kf!P*>@Lkjx+!GokkQrFJ~QBpM6;acBZrK>02>>N&^ zIB+z$-WE&rDfNA)0o=`_u+QHlU>W894f0# zM0dl>sNM3mXWp$LJh#qvl0KfWG0fi4h9wCF>nfY8MRx?n&3H4qN_H@d)HnAunS!kB zVIA<@bGb1UAB95=@E54!NKz*qYJh^JQmUIgzJp~1ncLEjGS>X%IukgJfbR`r}0h_M=xstrfe8a{Qglw(g2qKqY+#E#~^&EB@SB zLbJC9UBWd?x(1m&lQ%ohqds<0sBoQ_6+>qhFHsG~jTb#+Co1ZV*TL#~0+0-mVV9iQ zw3{Qrq3AF!&7n9V3}Wrh*I|~wcG?OtYu7%@_iuLq-6pEA{={nC5-FO+1?1v1em~z@ zv8bwn-wq7vW?Jxzlt*iC)u}~n)KU0JL0pNjTXnkmcloX_C_3yNt}m$aH;1R=>k$$4 z^Z%=rKn{P}riYf8vL?#a>zdV{;zLO+eW3WSYA{U&yJwI(lrG-UEEy9Cj%C5ObVY6)Vf z!^<{41##s+ow^`xmeBVk;jJqizIDJqTN)b;y%H253F^Gf)sD~}F?x=s{(bAA9XnL^f1kuG< zf1rkmvyczA_8I%F(-$=>%E3Ru$GcQ&TBZL3*DlrG~ z=-+Dc8__LUlH}y&^~WsgQU};Uy2h&?9ZLej-oCHF8@j(vqmthO zme>iO?#)BuKxsksd?axf$hLHq?beyK&jii}4dH8fOe}&HZIKB*6d7|5SGFaBW?A>0 z(OKyAX>Wo_o5gpE4_B0f{x2mm8L;*DSUGG3TVLNr3vl}N+#$xER?aoxF^zwGOyRxH zZ9B8P!g+$3JE#Bai&fDEV_KJdDSw!7O1IE)+I};)h9Do)<*_i+^#U!Snx7w`D3cssaj__`H(E>j9 zSF|5GXMl*2s`0a<0%dIMU<8N;RJp*G-h&U8gSoo!IsArZleqKRg*$1a=B&%ACjFi7 zMQCW7g!U0rd}v2Hn6p&1-?{FL>LM7J+S3$2g$?Y7s%Y(N^;l}T&?3fKEZr7 zF`X7h@K*dz7;(A5zYsvuI(J2F*^jX)6n!eWBbx2ZZgoXil5f`pirZ-E_#DVLAnMnm z6=99Bo>{KUk5HkDtZf1WA-X*MmUyEG+KTO3Yt(z&6c=%ZU;?;w_JI9XlB^E-MjEYK z)K7NKe`zZme|f$2O^h_kQpK*qB*J!N)pn6+D;d;tmD2>XtD4XtSF2qG^KeAz%r&v! zR2lzK%U~l8n~o|85^OZ@p!j&p9dP6nDKUgS`EMG?dZ+uir;R@O6P|vDe=`1pfRFzb zKwjnXttE=YUssX=4+HiZ$FClnD*7UfxPRL9nZZAhkOfnfNEIG@N6vjzffh1izU *m`#MR;6%*jm`yH8pDIziW({q44Q|<6h+w z4CTl4q9=@6r=%z8)eR+Em+@!a zMOdM)&gbVSrG?z7V&2;0LxeL~F)){vrs?K+QGw8@Bl> z!)GR`(N@}ztldKT5VdLUQpz3_sK*EV+SzD=Wll6kGaveL5a8M~@tu0khH}m8$c>?A zh>;mWptCF<_+1vw@)&nQF>iu#Cj1JeSnADFY_1->1;edd7{Xutbh~ydN$FR^cFL<& zv-eWM*$bFE1Y!EOCk+r;%~@lPK=KC5P#n5@Rdls&Rs$b=tHE?7i~mqyIPRY`u){(o zXOsu27o+tahtY)>`9q51&i8YdGxg+ZCO*lp8tBl1Zdr)@6b&WZ z4*buxmFi7Cn;bAPlS+d(kLbIrw-h{F3jSuctN_s{HAA1>Z@20KSL zww3iLkNAF;Q|Rz!ZRjw7W@|mFBfc*j$I0>Ots^czjfb}#!^zQ2>R?^DgSd}rLs7y< zCcBPUoe^Xtf4T0G?BJ98>nK;Pv^*&0q;_z;DVAtKdpxI@%Qkw_zqy+8BIkN88-9Zo z8rUh`cUb&&&~!aV6EWmy5OhMnUCR2??BI1d-h*qd+iozwVOc4m`!LUm5fnhl;?js4 zRXY+<*HUk>f2UiS_5Xs0wG}oCxJW7T8nryl($dNOW3isi?ToVPrUq341NC=zWu$Wf zwxkym4i2PN0@puAZA`M;*7{X6_p?us2=D|gnY$*xKtrflb>4$%)~S6EQaPsW#G-n? z@VqiEVc@)C+VV@Gr5rLW_WJ8Gj*v zE1y~P^-wyMh7-%aQ>`|DiOmonzf)saMA!`ou$3dIMmJ&M*MdY~nx1=wdK_pvt%45_ z0Ek4<(K|FdM?$xvBjK@RmZyb<$zB2+mE^xO@g#45Ca6vdfd1)yBoWb$uKnGyp>Vg@ z_}Y9OLz5jcNq3Ob_g49AkOFuWLnHXeE9fraWfytBN-rB1qLs)uuEM4unY9#Z4)Q7RQc$|`R}QbBf#rHdZ6&GR*V1kLOG1eq^C~la<&nG; z|3#IShWg#DIXg*U;wIE?j1)*T!CiAM91a&6b4s)u^SfghGL>lyZDfwoH^K|?{cip` zPjezqzK|v*YJ}I;%@GN_k?q^I{W;aGu}P>O5~w*5#9NMr$2Fbv7FTOd*Tw3QhO0R! zlDvL(`pH{5)x9!>p~Dv2PD@;Jq17Ko+mUj!n?5)GauYKrc;?4Q>`qJk2!Ie%wJL7M zqGsVr*-=NY%HlXNn+z7Fqk5Q12`J#)BAR~c41!? z{^9S%`82_SBR*tMl7|QZ+u^jrJ)|hl7u5LMM@hPg+TFA%aO4f98$5?}V&=SuSf;If zwV=1$q}O9H!InT;IQ3U2*W2X1nIEBL!%TRTVmCy?Ia424xGD(S?U!W2msWlHLb-|7 zb;KU&bE_ZBCtU~Tzp#PTD??+XdB>A?`&*u!@8P~H1fBPMJ^|03Cn3+9{GWQk62vCh z8!z84*t$4bL|K>cOz3gb2*mnv-U9a9h6Zj|UUxlpTgd<|#%Qrd&o#cW$x@!MykJ%) zLy(sYnyb5s2ZPUs+6i1c(OBA>K3MNI%hVCvN!L;Ysm4kxpgK6J481jc27>9ARJAY| zoU4KO0@TY3_D_jB^1hIuZ+mR~ zzuaj2(XN1isN&w>r)#RC_cdz0;@9QU3qZ)+3>>6pN!0xXP-sYs%@%oMC#Ixk}9&9Ww4VYpX;LXbVaVj*6;YQyjtDCg$p2|MTu7I;~Xg|$>35F8wj?l*%&3;gAicdH*4!J zC_Oz=Qe^Y5LnX)LP+zWu@e}QLm=ANIOoqO#jxaIh)rgr3cCh_q-66s+8vh1-c2Q|@ z4e#Eu=4wYfp|U78Z=c9mc^FwJja_AFFE?Vi*K-J%TJRfkmAKAL{!ahuL-F+FDdyyG z9CMM$l|J~XlzW+3hAvKD8#A;BHyr!497hIx3(gQ>p8#iXpzn9A)sVAwUxD#8Hkj9u ze4TW5!Z6u%CxMgAuj_>NV4naQoYa!$qURjtpp+{Fc)UAqY|zqDLm1a3nkDC z(GjDjdq_Q>F_Qx266b0rkNyF#KE{k&BMFDC1)zBO8Md4F<0AC>8}gMO zYpn#ks^&D86{;qGkbG@;b3?6HWSdvA!UKHb^Rm{YE|9)gwly-6V{ZerCldnE*>i%8 z!4Qo>Ej4vk^wxG$!6<4kPLksnN^>w?qsFGoEYm6J9UP@@iJjk{)5XZH<<%Bs5hP4(biTTSsQ@ULmI-AT4n8F-38q z++k_J*;Pz-5Z>=2T0a5c7?m&)H&JaBp|3bJSa;Gccid#Bx_T)n{;&8F#}tXE4kt&t z-$>nab|b z=?u6=$U)4gSpFg9jM%BMUJV3xt_A=376Kr>N`E=4Z!ED&G;sOodx)^S=yD<^)}?`z z60g?Wa-!uZW_BnqonUa9^uyiGH19qY@1Y_Y;nRtn4TpMO_{R;|?t??6E00WO+q|xR zHaG_lIETc^O9kn5Xi6?`p6fmjkt#e^12 z--f>!Fl@{UaK4hzRw##o6Cl2yfdyk9XteXnSRyvh$HE)BM>7-7%;wvWna8erClR;V zQJqvb-3d!>MX*yz4}5PSe6jV)8KjXR+0o;L@uUv$j}s~7VhHh%;~DoZ(jLD=P8`CdcZ~z=beaHghn*g&>`-DdL|antSEEY%FHJb!dG(j0smvHKe_VjuBLzRizz#39a${Stt$hn~HHcGoBT z%X`d)LKj~5042YBa^MjCFONc6JbD9L@tHXRtn|y)`KN#BJ%V>l>1q}|+HUwnHaNxn z%n5+TXZmv>f|#In81bRk^ZbpeS>QoRe1m(x67OH%THbh_8Y1&WVaZfBDYV!g!}~Bs za3`bpN8(Q%^50CJL-!EvnY~)ICDd|pDO!9#0nIZf>7Ah`H2&BXZTIbwT=ffWDfxSz~AyP&NODbd_lx_bTY zz7o_Ezv;$oCaSnRG60_S8Wtv+Cyc=6zVh)$YSzx=iyKF@p_+~SWb@aSv?a3mNkevl zWOV3a9-{hu6mJa@6ECA{_p+Vg;Eo=HvS++J42bx~eF%<^YdPz1g2Y%0J)m7oCFH)E zTCQPRCR9+$8VSd@(#N;~7BLosro^~{`CVLj=AMlS3?Jz#4J(28w~ZS6zUC&_sB1po zE)?cOut^9J?bs|$Xg#w=(X70QGTcgEAQs6C!F^HYc<+6(#R@nM1>o*G^pu0I5IOr6XaUXs28Sd9T7cJZG+ZnuOGsKYqmZDg1|Q}%fG!5r~P;Y zSTmMZ-2$sq(fo<2;~`uVSUo}VJrEW~fiVQLhr8Xuv&=NpO>BOBts2d`sGZBnPCOjI~2{o zOs+trH;~*Gd3^yQ@0&Jig>LTHl&%ou*BeiEuATpeZGTH?C-!< z>|fx3&HEC|3~td??8mN<^&G*3A$}P+j;7i*^HuCW1>&f7H5Ms+Sg;kvd3kxZga!O+ z@>2_Z1lG0*0fKDWvL7@Z)YPRP%Fu6cXE@`heKXMB;LmfM$z7ZKT|tH9&rOyzZ_v`v z2NQf0Z;M}t#zqly`Sy*^qwR3Y5!JsY>7SrGVZSs@T`ktkvO^QJGh@D07u@yUB>)H8 zd&Vsbmp=n({wQ{xO!8p3ydJeZ%`%PQ8d@z(bLmJI5Ux98b!NY@rf zy%s3|y-w4X1J$TO3jG$-mP57PFow$XcM1iG?UFTB1p;zy5OU?N1m^J!Zos7W!90g$ zM7W#Q-{0Ca^R#Sa>^KTsaRF|h?`J924{7#f;OAp;cA4fYxH`u(YZyL%adoWXUeHcL zDInuVv}^XvCxYB4Y`L@bFCKnt*M&MpPj|rsHwj78pu}}K2cs;CE;qXyZL7C*1Fpxb zn|4kbo4_lbbbex)$h+p zq{gqu=pz)32Iu7%jWzbk=2$s5b|`L?c`1>}XrTELl5U{32C1Pn(%l&A`jK|XKY6?l z@W=(yo9S0r=vyM45jbv2!<==&ra$4haJW>F<~~=)fQ$1EXt892q*{@Gk5GscLoh6E z+IUCGMywhcW8r$&5|6dw7tgnUbf$`w{at@P^=n10pk!N(Rb_XbI>Iw;D}_MSWc10s zB!L2UdlJOHV!AMINyXnIKiaKKX}&$^bP3`OxLvrJ zH!~->F9(O>-oz`tYgx?K8$h0uahBLu2~VZ}X|n=j+xt6btVFCFqanO14!;aZ?q%ci z(uY`wjrh|OH&i$l1_MmTa#fk>#ba4Fo`cGNPWkGBd2fp7luU~&$o<6%wNm%TuLz-M z5D}z=pDl*uILLRC;ZoPIlQPiOfXxU#`AD>Dpgm-^OMXfOg>v~TA{uXT#N%8bh6N96 z3X%@hadYRArt*x)cj^F1p0j-=S+L&pk|7G8k+TZTM#DEo1NPKGjvv1|(gwM{gZ3J5 z_?b-0jSaNGfjMKxmx2K{JLy*sc~g*6BAxgmcz;H#T{w^ljH%EIG0|r1fSb5P7T-m! zw#TdJ^I=yzQV%=3p}71}HYMp&&x>GGB10NuIB^f+j>LyId5VSu3mB}EIR$eYPs{& zXld#$4-$-4uh)AcR$VG_foFksmM(<&z1JxHx9`rEO+E4YS;p^w*-6;+*5{O8;vv`P zerwy|rn`>Mt3W2;w2%b0LelKapWFHn2j1%hDo&|IJ1zD+Jnt1VB57+c^&+&&G|?5G zea95T`abPTfCO%Z^%8JKT6ubkMT(UWpz%E1vcubJ;6l7Qx!atw1R!ygyBp`wLVCf@ zzI~J8uf4r^zN(~b!a%F~A_|d^SCP5@h3)h7UwJ)WbtU@}*fETFXiw~J&_=pK`n~Oo zu2cHYlFP=IlaV#z#7BKn!zvH^XEunAd#3aJEUQmM(Z}pvu!`k&XE%7^gE{+xAvw?0 zhBV)V2LWpFQVT=9lp-AW|FII>5VB#^d)iQk&ndA#JtTuR{?a@uk^M91g~18TZV=dk zN|-Uni*QV%g-f;eeeeY)IJOy6mJ%KSd?*Bq< z{t>RvA$LSMULdy?5jZtnAlG*il3qn>o@Ok!W&xzDxoB#JImeInm9&%G$#XD-{B}Zb z#oN{pUtkLPecR@n!yHg3&tkK|hvN#%f>`n~HWr3~`19XwO-im`iGx2(Q{9<|#li$> zY#2S>ZUbXXia~jGdF>u{K}yY^VP4HaxXhjsMJYdaKA{RWn7kHrz(R$mFlR)5w;rt( zh5~Sur$4E#yN0mE)>+WIc2e@%GXo9Ue$nfnj(_Ni;AFvHS$Tp zC1A_xBYP`l9RI46VMu`a`pXJwzAhoaNEy@4zlVgudiJ8$Mu9DcF6zWHFrY%ro6BgT zqwdDpM^=CZb_gT$Sp+utLMxQHiI#o*O$f*=&)R;_P@GgbIye<@qXTYEaDW#1|3A2vow-h34T1V*=V1D3c>%$20%(^PZ`sOS|A&t%n}sDO57 zIKAN@rsf{pqRaW3#bhNeQW@oam6YPR*`KY^&URH!!E7D&N~Um(KcplP4J8$) zpr5{15dY$=)E^}-G`-yC@(YjUz!_muJ3&e6!_Sn^0s}zJ<53W@l_*VcKx7M}Lqu~UE1xMq?}W%4`{B;{I1Z#{_2kmCz& zWQLJEC+cdLKK#w1qs?Uey8i}!KSjw&eLlHBe`oWjy+wCLqaHG(kRQ6aHy<0_ zA%9Z|y$tTHKuUyBRjbgjDQYNT@#hqC4+!}^Nj6BF{C%35TExVOx@t@~!3+qBz%=TF z`?Zny9NN}K^-%n5_bK2U(T|=0B2U0Ued8crDEakR$zRwN`t0sMvn+7;^nQv^*@`ek z9D{-Ndt608IQ?67pp?tXM~WS{DQB>OheKf4N+?_X28z5a*H<;h;bD8Y>3&fTh)&+( zzYLvQ$|GfGr_g>T&o?rzj%EOr)X)HhJfvD2>XWwJ@quc_G>}+|!6CadqkA6HFW}~`s z>lGj)cd>sul2>$ir_Iz{38ADz)sGPqjcygk1Pec9P~|RZ#Wkp3^oRn2)9rLu<>wMa zs~zTiHK;Bj{!y7(-wgX9@w#1VZNu_~QHA=jt66s=OYgBtdde{(gxK2x%J9rGi?U-6 z+SR0;rCljjB&6BOP6 z=yP<{EKzZG+|@Uu$c}1+$&i?@M9ZL&i7KM9Jv6Emmso$1%TBO?s)WT}Tk_36h>rVP zdEEWH-mOgn&XEh_QA3wBtiPtwrEDbOgb()(v;-K%zWGFZ`NCRp>0FtddfQ#WdhB|; z>fi)P>5cJloDqY+WjlVCc#IKKr4ZuwZc(!vE#QSV85zw+=apo_h0o?@{UO7_{zJw! z1wAN60}AB3asCTApfk20$1P@rTq{Uy%KJC0?cnYj75LNFxa#sHCcZyj?+smHbh$P% z?vt~alT`ShsD!LdY$ z-zlK2jou^Vh^dqb4cqaFj1SB%kf9~5=v0ilUYue zFQCbC2z`pTHUON5aNcDS?xnAs`|ZHz)J&qN1y9M8>s*}3ye)4<>4UC%uQ zp@A~Y&f1)W*W^t#ONv_tZ%aMLRNrjyDv%-mY0wuKGM1k{@jf~zEP6L6An%^rJX<3< z1Rydb@Mc9U03;6VtSVeoQVfAuY3xjZ!dpkuBm%0cC_aRf#-14Cfu|>mmU>B%gl7sC zrRp+fd=*2ZBN>izN-z z7UQ)t+ciM~xhKcx1N<7FmT8hAWxOmg@4;0VgKpI%KvGUcL~QLo`iIWkmZyD8U4g{s zBBU95xCJ{BynRb|46ky~L-J-4blc5S`g4X{Noe?d|3Hr6wa;j#cL6(ChU!3DT(TGy zIph{|A4e$|=D^3iKy=BTRnBg?xX3ozRLCl$8N`rsGzc5PD=iUgw)3=gXO1-LKE=yJ zFb^UlkTFc*?d0gig`X`e2@#JQ1CpreAKso-&H^h!HLyu8fl#-{@T%qT^diY4U0!CA z7J-MMLFdF%chyIwO6NQph0ivOdar52F9raz!l<8=X3lzKCn%HL4P?;>ZKMhM1e$V8 zkKqSz$-=uoSTPz#Ede+@`QYyovt z*dQ!-cHr*R=if5(SmJ_2-WPVe0HwTjtdpWx#@R8mcS&y}Lkvk}b&Rezc-lxID^3<* zL?h!igx-*cfb?E=^x^TP=K2*T`~u~*X144i3Mq`(km32ivf(56Om~)WXdsxob|Ki{ z-U?Vq>CG+^=4+ng*-$oshvXo@?EW}e4dgaCTTF5Rl5W%_wP*$ce5?2kLzp+>EH>2m zQ~(TUy4%U314kv&t~?fCfUYV%j^Io3gE{S>*e^St5_j<>@y{wn{xBNy3?--hhG10E z3*pgT+@Z^Dw<#0N-^6oGrzNO)^Pz`{S4u`rHn9TZ2o=}hn4bOGE+Zkk9xViXv-|O3 zL{2|~mp&AHL@Wy?Tr&AwR^4C*{3$~Mou6G_TI6r%cL^WGrslN3dZ()>Qt_A^c2VOZ z@Z03ASPkqULMGo20(LPs)T<{c4?t1R+#dbwefO?>_fG%wGeh7@EcZ)wPvN-^c{(^& zu`98Syq@}%UfYWjn%m|Y9X&osyt2;G4g~l2ZpFr%f_@6X+)no-L|HvgbzZUB=f z&q_xiCOKMHW<(Qy702~twu^Qw#FLq@o3_$N41a`!$DRW~P?94h7OB+M<5WRPkN9QE6> zM(K>;+M|nN^L=LZzfhp4Z(M5w7<|v$*3G5G4Zhzi%+~B0+NAzoJHEzgXg*jp#LzUs zrh@pLHinG>jr=7xn%TEVd0NtG>TP44VM9M_DC{sD-4eldf_d69lOW|TsJ@pU4A71wz4M$2McUtH{Zp`p9A<4yU#qp79|nva>jko#z?%6J zgd%>ejVu)A9E^EFjP}o$ynAVNkhYNifO?@1)3z4wc`Z$HUc2lp9IbOOqhjn-K;+u_ zv86^1U>YSfC9t&!fbM@^!vyt8Nx={qrF0 z&{M1`PV~d(w(0qfBl812VcA=;(f>-$xXjyjre}w10kTDljv$Ov3*%UXnTQ+-Tbs_? zK!1K)^;?5(n@r0n*(StyMQ!n}m_1IYz@(~9V26S{5tI~e5(o8{KU@mDYHvObXzSA% z3~k_{SfoEJZR?QO;8=M0RVhLYDT)^)9=K&ecB_un`O-^?s~GVLGB*6u3ap-}S*m4_ zhJcVp`BPJYT$e(bnzav9MmU0xzF+u(SwIQ4Pfp{(Np(s*;RXLVuD2S(VQ_}>3a$SJ z0Lgz*Q$TP{r@KGmch4ZD=3CR9pdsv8_wX~ZN_qR`eD(FdYLZdz|GTe#qr?Pr%ca-C zZ<`a})JB%WE{ngQ^oW-=oo=U+=v%KR!uR5nP)ae<8Z&vSsUpk44(&q2LHdd_cG78ZO#xS(L%4&+M=s^6V0q49m&HQIka=#U; zbQP;xXb5z;r6fZoxp2L{dBit{?F&6+MDEPzhLgRQo9_No`)_BV%FFAUh;=oICOJF?~J>9haQdrS$TV-U{^Z-{(l4?6E9Dnnui~J zluz^|)lXq~XK_*Q9e+ba+GZ+A2Ez=COvBv@>CA1K!k~+b^R>_!XyIsg5d0ygs1(us z8S;gvM!{BbD(22pAGwj|Q14BXVIxMscDo(}HX~(ye$X-0PLiNvJzMq$LuR9G(fC{ zThawqW|w-J-WT5Dos~626t9+qkW!Z1Hf0WdE82Qm+$VH^N1;P8+fVH01q)8F(x<93 z{O1XqsCNg>+QA?XUAIN@>fEd7#pfS?9=G7|sRJ5(%44eHi{7+?z%YsXE;R~G6R*lq zZ9@2ztJa61eWuaMiZP`W|W5wO3XKY7?wGqC_)7shAa+s z?-b^IWb3Q|TH~DgEBCNm?7n;G+3#fM(dAH8@k9F=JN!!YUIQ8=Xt%8rf!P#yxX%O# z{=tDAl|?&9FpwUy6cko*odJ19uw~)uy)2x$P=AH4v$`60_(EvBpc+nAcPT- z;e%~;AU&t+HFNM{G5HMY&C0wBFpDwm>6T(`f15Z%FLd=`w~?%GGIixOp0O5nB#%)H z7F=IVj`Zr5T9Tm)>?qPv?dnYU3eJwct1jP(b|=Rhq%6(w@zY85gPWM&uIj#;Xu?%) zds+b2g}UZmI2pTUT}BKkN9FSTD@C?B7SqTpW#ZU=fjLTG`qMlEh6*X|9s+F}f)V~{ zgzYqRe!taM@~DE9C15!ZcH&U`(L?KF5w>cQBAxd+(a^SjMwA&EIL}emv)HE_XIlQ{ zAHQEQEAn|fmgu|u0KT5SVtCZp`-Cu*Uxxufs#fzR{&;cd=y6PNUuSGHFi0FhQEC-C zaV?c}Ra_pm6w%)ie{8L*BEC&gEf7I)HbL)^EUA$3$fv-x8t#e~Sc}>a==R~TkAcBN z7tC8}DO?DDVR~d6I=yl7hVjuwZk)Y-vyjZ0c+9F`jHP#&MRyJ&0^hGKE%-e3P|*V# zS0t*2#`c@A#BF){Y8YqyrtYyHG_fb{(L)waP#E(y21F|r2I%OhK+fB~4!1=vXRm#$ z{_Jw7^2203ZT{7n_Vo)s+*rq+Xe-s7_I-!{S4O{0`Ba!dQ;IRyEkIJwZAOzdTmFcg7Wc+ABAMRcfdADf5D1611t2MmQ@dn6IpEn4S zH_7Y4U`B|?52OGM%%ri8VG;oOhb-%|RE%jg*a(rCE`9a#c_Y|O$VlSGzG2LUZk$>K zufJwt{J%jFrAJosL*Yt=b~wZJVWZTRF;mV^$IqC~m1o1$r$4_F(r_WLA`-IjG9+_l zw1(3v*wm2bTWDr}4Xrc9;sGB<0iIc>EySFdwl<>i>tEvPZ`TpvH?Nj0Q{>(>e^I!1 z+Hs}En@fXe&->drHKyL*q%kfN!-(gYr4M$&`HJ#{3O<1NFr&E}#-BL(g+f113an!U z^b5Di?;OMYh!VpDT^mJ-gbKkkpBd5f(N9Dd)K^y4v-FHx&dN8JErABu=8D`a)e}u+ zgYDI`#-<YOpxqXo9HE50{_*j_9%M^%4SmnUR8B9X ze0zGh|NbCNMYp+_;_T?);3Q3d5V{!8;QPVpY5(+K-=t9=0B_yV_ximP0_ScjLl)A} zR>+tQO;6q2Xtp{Ua!pTdZ8bN$8XB3N+Uah#JA$;eMfzUFnvs&r{-_aurFD;=Jpkp+ zUm`T&y|AbzgxnvKe{adZnRtY^waI+@zlO@U1zg(87g*XCSlSm@+80>b%E0mmri|@f zz}_?>Le0lb9Z|~sjOfXh|z$8XzXh5{`JDKRBtc=Uv*?Tk%#{eye1~uy^G-RfBIwDYe zuU74(giPK2ihR9m{q$h(;PBJI<=Nr;{4GmWl8c1CcqX!8ENd7<0H{!Lp%>aMCKG;T44{w0I~$~BMH zz2fEbbD}yhe?IFU>qNhyN~$IHPWo(qoMs zazlOO2M3loI9OYMfZvq4uVNCWNJA-Znswuh;R1s>;3a4a%f&&YDtrFi1==oZSQNH2 zP1FeISK)ma;c3J1Ncg)eP>te1Z}fnUyTUA*E5PfVHT8BuhgWV8+HzIP(%T5_`6q1Z&0{3d4Q2mdCl5=pSB_3OcLWf~=hzi5M=fjg9omBg& z?y0h|iP#wwu`_5v6Y^CE7h1HWr%BuPg|>Zkyl7Kk1FXmgW*SL-tA`US*z;|?8>!7q zi98q&+a#PwRH!^7GJ(}jYl8AUlW{sw>mDnYG2BFdS}e3FO8VKjihN7;G(Et?n^%4F zuUBuzNO`S@uin6`OYxNnZ$#eiByWc$-d`b(fWl4$1yRZQ8OhI2@ipurdOAwpW|QJO z;;JqjwyUev-|HO4^3#v*Rq+6f!~-xLr&G#>{n}w|jYda=72HJe&RKpB}zHJZ@m`#tD3n zn0h9r7Y!@GjSxrrzdYp?IIofM`(pAV`O7Rh9i_wQdpzS;f8zip+HPb>$!qOHJ685G|O^-uB=fN~Ipj@O|J>By9Srt9T)zEyc(i|c zc>Jz^$ri@JJ_!!dvk$u~fVJ^C{SA^m7CxGN;=!bo z;jm2Aud1IMkO%t*`^eX?=8kKBA9^F-bO2o$owqNxSWx)Ng z{gaaPaN^&pS{`;dG{+2d7-7{mRdup#oYHnqgm#8#LSc)$IoRUHOswI`RMqLS8bB;@ zu#cvc!!~DVs%Z$;n>x!>(Je(r7HX+so6B$7c#3c=vjr1duFurGbK#PH7vSBrd6-vVj8&-0} zD0FlzQ+X3ohAULyg~`Y@z+9JZZ=x#PcIdPKB|mXO-I_UOL?1IOu59Q%PFWKa zL&%cl`y}Lo$CIc$3oXLrm9yWcIP~Yi5CiirmYk-u>CEzUzGyZ%{~qHzG?h0u?KiND zE@|bL#B2k(<%2sf9o)idln*c;t^5d=j>AwKhtc;K2b+!qGakZ!H&X>oglpF3HnM0| zJ}#ruaT()?5PYF@@i?B1?{Z6rB!ATMtjNK~o88MasshhWkA-}0QIpM*kmEqiN!p#x z8L_EOrp(rA?F75#PMBz7Ytv-(w~$O&C|BQOp-kyQ0sACaCUnIpXk5N5uFB7%!juW3 zmeV7OZ+2n@)->FIj^Mh%o~7`iV0YC_%0%T zMyH&dC07`MgQ|1#$RFJp+u4*U=ZdvUc2U6F&a4OIJ zLA`T-kZ}lq`5t4qOUIDP@h-V=OhHHGquDPfY$Wo@dV?hu#>unJ=24n2KYrO!-epak z&C9p^t~kVd-(!dmIq~SY_NC*EdZyj_k;fDDREtrov$a{p zPyR;ONLyqhH`-fW5R76-YsA)gv$NjWq_)Oe-4@u+a$94OA>vC#opU=pD+CSb z!-Keg!MFe{GF#ixPkABOcJ%5MU#F?eE4oOmZ3EDDcv`{GZ(@c0TaS5@-cutRkQuJ7 zs`xy(Fun8Of=6a*;8-h>7f>!t=IAoBTpUGQo~1TXqM&6~;|p&7w74QRlzYDG2Zr*) z+k?H`{dEN?s|G>yP>cn*=Z*saA)$#PB4hG@J^gm#L>S5QU-@@u6U+8*4W-#=&+Z!C z*F}K`_NXQ)TV-pO=C%Q@PGkl z@?v`{dzQ&ww-2qYsy?*VNFPEx^gWyOqW0LvF|xrMJIKybM5R#KJ_@g%Hg}mKzUlOT zv88tE%x2(u#9JKUJAfi#!vf+mCPC#GI&5}03=Z|y1)qEFh-E9(Qcy{XRfyf8 zLWi-K(Vs^|ZKtqtOsa@;P&yS^(z?*VpARRrpUf|vd7K%G!1n~;ZLPCjb=3^WRWq!*YSO#JO79ZuuYH&JrtGG$JZEY}pnoP05K&hNXO7qCh7H&W zpyu*O&{{xeQ2zHC-;V-oio*t^Qj7(l1OGpYu^|3YBR`k|)(7#s?5sC!JcdIe)=((j z2VpQIAUU^=9ZkrhpI~P^i4gIB&~PKN^!d^bA;Zk^(46g>71In?SHrTEq&U;Df)-&g zG$NEPqWO-m^Ij_ovfRk95NUwnAzD2stztAUt}tH%W2~W!OwZRoM;5GKOzcoQTWifq z>gR;{Tz&b4JlvEl&W(*`htfgawe_tHLI>#{h>b&_joR&Im-<|7w7Ttob!cfqCb=Z# zkog)>g37KUFZ7TGw0wA2#4LaTeSd2Op5u+-J-7cQBp~-XJ;I}?;J1s|$5S%C1+QMj zDwADmx!c~00xOIL_%4c>m24qT+E#k&*;a7PO2~i8mdCnQEYZs(WMz4zX>iI*Vn2`} zW4%go?8q8twU9;57q>5ep4*8`YbP=-UWgHpU$n~(@c^@UQ5tepO|^8G2jqimh9Hlw zSfpVV=xst2zQ50{fCgGEtmzcxC%G}NeEYtgT$heF!GRMgD2JI7qx2#I-^Up*iQJ^- zg7cO(x;)=twz`~CRj?_K)-CllGk;%Hw7J48plp1)82L~>{+=!cg z3Az{a3k4^ae7;*i!57*N&{xP4ykhbhF7p{YKtDofGGi=%=D3j?9^S8{PlW`@7vi!( zZrvZhXzH1!9%y7W-;qL4-o9j*L zsmpFuxINdKYwaf7o}Sv-+H7?-G=Wk#+RZJ{19~d))z;7zNwC(`&=kI}b=EaBPVep; zawCsv5ARKXPoKR~wnpprW~YruTN`+@yVcoP?_xc?87td@KVm|W-u|^I(#twm)Knj! zTa{38_k>uZpnPx&Hu^K>luGHW?Mv~Npd{Ums_EW*dW8c{+of;lNqJyiZc`kIYaW5x=khZp1QTxZ3(P@MDKafjp~CN?Y>|eJqg?B=&u89 zw3kITBHqor49@6~{XG)Boeyh!JNN!;yq$Y;NTdBSL?epbvtZ{9WsqYuv;upN;~fbA zJ?kZ$5@Dmdm26butFmgiRv5h|q_&b&!?2Xr3s_2Mf-M^dr~a+60EykM>x?}^8DcLY z_%bzr`74+3>?wv*yTIO&big`s31Pkn&Pg3hD5E{VMF|o>CyhtM^UR1sIz`|&>zAgR z(8zf+8aZ#e>~L4`)N))BCUAAt0mNnj)>1>t%nHL>Kd@PfSw2M^3sxUcAnXf#0~Y#} z=K;$^J)B>GDW@~`4n1{2sx&;r%Qhw;fw&QW7{q%MQ(Yf$j<+Bl5j~X9WkNslJK=Vx zC|Ywb(IWBze0`t~W||5xiEos+NOKnvu)fU0$Qj)yivwA(Rt_UP4byjms7_CEi{M$o zGVrV>3a7?8MDyq(cWiXfoolpZoG3%0&3_nXIocat*mlKY6cAV`K;eFZ!y80GD^28o zduL>FjB!bWrO;rTHG0>6Oo4TVtDPD0WH%Rc9w0^#tu+B}{M!}mN@N0)HQ-7U>I~qH z(51j*T$aQ1)@T@G`D9CC5m-)0{Pi-;CmSP{t`+Gba!ceKEu~m26&w-ZrZ2yMO9BCR z(w?*yMkI}GuoDPT>$%0upU8Dk&K}$u*I3qW5QTebwOje4VB%*+IGZ$MkU|fsCIXW zOI@bB$RkWL_p?Sp(l;;8+sN}($reDg6Twt3sWaRuhf80U6+FHSmyI29|0>Lkr!C61 zhqtVJ?hwh)#ceb(hoF61uoEZID-cu}KkR}1e;m}GEQRy>(zp=0aiolSkNHJRsx>A$AMmdm{1e09<1@;&ksbp+0@-(za zM}@{Dl2!x`QU+bw!iZ)I4upb(x&;#-B%^!?=y&RCSz5Cr)a;}+Gn1F_;eoUv7d#2a zTq`u&&LZ{w38(h><X;ggAT|gf0-bx&t5&QT@|>jClAJv&n&?yOPGv>BZXv*QDJg}H(xZzpO*7POM?XE- zKRi9y8x-@C!_L5e^q@U657LA7`cFD&?_Lhtr3dZxl7n{eAAHdE{>+1R@LUIN-%P19 zK`VcLfrj%Sz+Ut*aJfN$7U1uzj?Mnp(#W=>_jbW||Fr*ca9||bnL9Xk`f%)|&5uYV z9MBu3^k)I9kyFm8u~H=1*D?S|YL=3aoUA%H<%FU0E|7$O;FW?y8kGe_06em!u#_qe zOm5iCY%I7AH{iw~K~B^vVBbUlS*=y~D`|;S+K}aaO1ndQx0KbWSsKKU3mQb^37}G3 zHVBZq01Y1muqU`tRutSftTFiHmT&_iDy4wcDS&bo*2V&`HX{bd7{@W(b9?6Qc2=AE zC){)UFZbMk(tGZ3$vt=cAAHZ9{F(RM@pIjCrzR*n`9=2Sn_Xn5-{2zSRI`!b*6s7N zF7koG_R~{Re(z;-aR0k9ImbKm3*mx3r|~D=g5=!NKYj)`fQ+EtxI&4r{|sf#|MpOT zZ3m84;~h#I9*xiXZ?U%hHi43$N{z$g!@=S1(dF5HV0Un!Fp2s{)6s9XNUJ`WZ(~Gc z=Tgyp5@dv+GR@HtxoCuJF0wzI5J|m*de`K^LZ6%DAw)LCrwP!P8F}!*%8{D`s`D&s zNoN8WM*0MZI>LaPits~0>d;&qSeLgxxNVznt_*Oxq5>UcI`lM|mDF9!ZUVJM_T_`{MUd-|FWM9&L z@vS6vq5SN7nnQ&5OIHv5EvBGtOH*(tt270FEj>*^e?tn2d`Bbvy#IK*OJnuO-U_K1 z^i`6M{Vt|B%O^P#(hN>_kI#1ZGBpbC+CO$(ekU=A`gvl5F&Y5+ib9R4GqC(?b?fFYdWuft^>3I)4&HY`sv#ODST1 zM@|t_=fOpSJqVV;*PegtDTsj%rf*^tels%5f1;SxG|iwINpOd_=0z!9gT|$lb2E$) ziNsa4+>a@7kt}m5fM`;99HWg+r(0QKAlWz_@Epj&AFOS)z~2Cj57s(uf_|`Iyl8Lk zybm1PSa9={&fk1)5W=i5dvj;c3hWPm#G1=kL{8-5!Tro12i9zI&z+j{j?ZA0$&59P z1&x4bEQk+!A8Ly34ZS0{@w?RO^@oGCcdd8tz^n(1dVc5(yUpP`SfZqUbcXW7Xf#qX z{_{M!z1G@jDuQDmFBfl)tWk@V8|e62-`!|75%~C#pXVD8Og&Rgpx-x{(|ziH;>XK- z_wL=>cdewIqtR&nO43ftZf{trNi5Gj8rha@rMbJ^PG?=AtxRMP3xs@6yV z8B;I+hmQs{>f9$s~aEF(A9vZYz^*2o&AK7c=TvEAKTBe)0? zYlb<#!Kr0C^U%mIN?1sNV`I96Y20__QD2quO`8nJAay(Td=Gq-!3F&Y>~RzGXC97b zRktRdNI_R@LCF>i z5{6iBlc6W}a+$H$o08E-U|{%x8~E$p^=^9$Qn4+NAMDKyO+n-Y4bIr<{95nQ+S*HM zTPxHCu4qrKt#vFI;X_Wfy@eX||5~A!`6Vc{qouEv_UMUqK+D&EYSv>r;moyQs`#nH zPCB8yw%%&5EuXx0b8T~z)LL3iySkdqTJ^L#olXZ*2|G!7tvB1%b$6=j?&vit?le1V z8;`HJD=f@bSE%BM6x?BRN8k0Z?aZfSv8FFi@p$f90c}#To=K~EkPIT4gO6^_Jd*4tDF5RcD#D^wvgvW_OvM!!QO?|Ua z&f2#+i`acZD6tw{TE58FN)~fCzan&Q>s!>*(l^$sDyg*&(_^mulyB*48W9 zp!}jYn9`ixHQ<)-07BF3u6WODh$m^4Bmr;dCIfkbG_PBKvP5l7sBNvfwgfV&qP7mN zt-Z9i&Fb1Z9KvczZJp({aWpLH5U}dH75(Sck>PHZB}%I6u%fD}TdNp=Om*FFQr&uG z%fGQz71YqYuU%Es&H#rg=Dl^bt+t6THz+IaIK=kWVEU(Bnxzt)m&X6S%sA~uJhqqR%54G zug2E08aMcOEv>P=w8pJkHE!|&tEv&2)#85U#?d)!P>UK6+-CtcLsjX9^%5Jk}mEC1k!gzMp>QvcYUS)D!zuu^*vcspTs!Eva zZkN@)tje`zRd)F_Ev<6Bs>+K5JdZjkg3xP%rx?)lVnpJ@NQL2vwkBZc6A3ydW`G>0 zc!UFg>aDkz%SOI-*lNa`7;FcvxXiDe}d`L*bPkPOK>drdVkapo^l~=_K&)?s=jnfm&gm z-M1oKiqcW2Ooim=`~nFo9WXIkX)>UdMBf2_0aBCB`dJ;H>YJ9T?G#Ek@?rF->f;=A zZx`EvXvP$9q!9-orPX&VqkiRhHcJ9tM`T9 zuEsN1=?#203urVV3KoN%Xo3U4m4TdKBq=V>ZDA?!-ZGf_h{Px5ABq1n2V*gqMiz@Y z*StO!AU`9R1cIEBbx&pE^SZTSn#oKS@M1_Xf&NHU&OIw~Zg6Ah+xSA;PGkg`QO`I1A}5}y-(C0=`Fh4$l!XC z0CQ5c;p%E7?vjX#W11#?zoUfYuVQeFo@}rij-w(Ojh;2zA&BwTEUQaZugsDFst*q< zLlIAETfSQHH(H~~EkM>iG$aBHGNA=zTM=_gm@=>v6y{dIbA)3l+4U$SkYt*FIH0Me zWa+-ZOEyK;Orf=Gi;ReNK6eOA|4r_Sx4!RUOBf4^Z_^)@-4-mv<1dVHx<;p}EL0_f zC^Nb7ZNvj`N@j7}GmA|Ngqe3(1aZ#{%REGJ?Eag*5*b24=-2KE^2KZG^M zx)W?CaZ_1INClI9GJfQZvYRn~ykr|C3EQdDaD4=GR?z^Tff@Rn=RA@hPlKoxx`AVK zfr8ZLSG`h6sQ?-A_zn<^+AOY6d0*aI_9^~-j>Cx5sHCm6N?LULJ%;q7Hw%2Q8Gwy; z;6+Y!pKlK?Y0u^NXwMlAZg5by2?yVKk|2VJ>kMm8(b@NzB4RFd%A#L?e~V==j6ZhKPR@+qyj_&pwN$UyrU3D180i; zc_fKx8>yVlp-BMU7mgzhU1)JW($sgxl^oQ^mF&IXNx>?L@T z^lx9pl{~7AD|z={gDZJ|$8aS}&^p18aROnkb_yrMf=-E{ygwKyXc%A{Xb8&<0fBw! z&TXv3v2mE=z78|RXJX4|O2x#A!-#e~BN-YCfU25Bh602Y zBWm7!2_Y7w!ch2L!{SyXDPl2d_kKnwK*>@b|B`wx(k+=B0**d^g)4uIx9JvQ+lTyV z+)hC710+0vUCjfx0T@vYa1k}dkm;xa2>PZFI2|cQBmHSGObN(4n?~FcoZU;*gxxJCQoqjO3QZq3_;cbh`yN5;KAROG@681T?Q0?koNfrC=8V+Vs&n4FU^P4GvL(+kf?)9Alnb`Q=NE~a zv}G<}ER0ZXLM*w!zcoU&r6Ky+2-UV0BMCdoDFM|g+(eQP4KSUthOBLw2v368-I%NA z7=eAeD08!asC=V1xbLw?>jsx%%MGw)-#73b9?sz$(G^NiZTs6AtZOL4Y$3R39J9S@ zfkAt~$N+==B2_#*sH$V~Pul7#qf`P7H35nh22NXDT}f$}09og)3r@K3@#o%!f!Rb5 z5X3UiX|>3qTk1kX@RRu+HYw0j%WzC<`zpZJbvCSjeZ$wuGI;fhJ6%Af2&yEQOC<4{ zk){evlE5<0n-|+);_P^HOp|RGmg(#M45H7@R1Nt$tP}bpP0FpF$x?Sr)iG&0O>h)& z&K>sab?X9Xwsq4qp;r$NZT6&T3*T%e#m3G^?XXX)tLlpL@Br=nyF-4%<4?|chvcGN zA>E*VBLaEXlf3NvPq5O{)bI->V+c7MF=;!Kw0(itH~^t(X*|<;o0Pv~gkp>HO&Iz7 z$_urHWuC92@B#&9Ga)ZM(=nUSnl-Wp*lM=Y4Vz3VI9jC66KsN;V4M3^++*3Om+!Js zFZ~&D2j!73Gf_xspGy!}7v^g|j3{He{(hHQZ7xIk~o$CCWzYElCbn z9WRvJeoK>O1CqMTpnNk)B`Db>mTG~vLjf0+ov0cCFmPN9q-;JV zxt__@jOM1lOjwD}kcw!xQbz#6<|r1hO8W7BFHyrmZq5>wNbt<@ieh5g5Wvc!L+ z3;U1U!Y*0P31L(|bb^MB3E_75Ll#;lg-j_C(WO8sn(>~@fle>9B3(y6U(_0+_i6v? zN(bW@tu8PUnh3Oo1Rx}&t$@bl zL;w*9Xb8y1RipPyNF5r{V8);soKrTQvnd@$Vf4skfUl!61BcQu`gnSz$YO9d0{vrK zbwIPL~q5mlN!dd(x zqvP#(x_=eo;0DBUJCP~=G}OrSK%LEBD1hsd{xl=ah)m^w|5r$XqS(^|6@<=o4mfqq z@h{TwB{0$wDQt+{(GL70mC@chp6%c6&_9V7!u0g!8Eks53b(zV0-`}YgVs5m^z29WNHfoKaxd;c!HLgpp{85W|_2Nd!sl@ z-PCR)Gs^*t#FX!hV#%?K12#vCGNTxOZ8X={)~YU*pC^p`_-(+5x61(| zKky9=|Ba^a896s|a^##$QL6@JW?||gu>d1@je@|IO!4Y!w!DnRSe!R2OEk3PD5)2I z5r%<;U-T}_=-j)|xE0#A#Ip6VhJ|}Xq>S$(?Ac+1h>#k}E5@%!+A9T)K@dS(4MDR8 zW?WEzrjjub04@xKJAw@xjwy&85^WKgsadp>GfLD9RW!{KEfir5vLLWlQBYhnb~_^S z+k!nnvXXg1hfI!O8sJ^johgUTlmj#6TnI+UWqi(d)~uG_e*%3$B6Z?=4ZtK)XY=n- zVqZxjcS6uk6T)|Dsd^nu5g&(Wla3EL2$rFLA38q;e1M%-ue3~~U~CcvTiT@=E9Ede zNX+b#j?p~OmviTWbO-*XHo-aW1`*kqlw-?iUA!G^kkyqTUm_}rO4UcI_wb;4CQ~A5 znt*7CETJC4tiT06SE;0*uz&QfCLC8rBOHpU$=<9?KBx37QJHxvGuYD%CwZjIy^lhF zEuO0ce~4R8M-V4L)3}L5T(nAlQ5n6cj9yemFDj#q%1AWrr}P-CX*STgdo;Npz$UDT zprQQy|H&eEz)G;XN-tNy=Oh@NluS;q0AlaMZ__4n0L`p;opLEz@bFMo0Fh<2*EZLe z`y*xWa-)ZbMJzY&6ErUH{hz&~4^cFKV|KBK8LI*AIxwsA;sLeruZ^~8styxbzG*d^ z4^0iF0!+gZ?IW4QlfOgrz%{`5j9ONHJUybgQN@EWZ%vVAf^xMOfjIc_`REOkN*c8o zUAg{Mje=mf-n#ykdY%?}0Tz!#7na*RH8KLkJxPI9jF>HsF^*)8I^j8gNKuab zTP{Vph|$Cf6`zf>VMnOjPw8Vud{!77k^XF{}ul0?BZ`b+K+F>Qfj)lJf+&R)8bETOI+vGHV(fZcmbRcP@KGs3E>Yhb@V2yF&;*rvY$r~nO&*eDB z2}wqY{a|%fiGn%Iq{(=@K+CQjfng6~)NOY+h%x1Hhd0xjZ{RLZmwCL@K$ zjL}-Vv)+P^g21x1PM$V8n_C+)(dG9s(H2Hn5SCnC;;`r2a~Fe1J$=tMl9{}T(R!!b zT+2FPdMfEeUZYiE|4m%#(xy01Y|478wU!^cXLJSr>ako~U*Bqf%I5ytne%;h8#lK$ z+MBXA3TqD*oMgL1WaSBPvZnas;bEnP2&8S|=mw2Z2o6;q$by?QC{i>&3BsKE&g% zULCDwx6{q_Kp=pBlG3vhwVli_;+U;!hE&S76nt4kTFy$jyn0eDk4U*x5NMeo+7eFe zr;G_m@1^(jSC92ZXS12#iC)!U*KtOd4gRBi(w{a)s`m{BWW6Ow_W4z`-fXRD-$IuC zZ|Efdgi|V7U8Q91*I&0Ao9i3(M!RAZM34p1U@;@+N8hS{$?M(C&U%qTNd4!rP}&Yo zp_Os`4fg9=d%cq%u-4}K)~3dj7bzymD*Y8(*F9^d2{ib2s!L;EkthD*e)*0RHekmy zqMRGKU?&l+uI2_NaDJNIUjwG`{+{z z%_2s=DP8)1iO|0c&px>jLaO$F0cI_MW``23fm{(1GIcswyDks26lw;UrTOZrN|e$M z4|6z;wUUe6f`B!eVV#FSu7?+izhAnn5E&;5Szu|%5|*d+#O1lw-P)8=&s9#BOx+`K zz2sjq4ww?pIQ$Jx{%*Uy*(#77b=)Dt8A#d7JR!e-k0a#QpCrw8tH^UTH(Jt*jycfs zoyRsDqSjW#U9wh0GJmN~j(W~Ex1FDSQ8(wA{<(93R@78Q=V^a8n~&Ae5k0lVSy(M~ zg8llNthv!DVY^BO4}{Q*7+Lw)ZZHJYD2sanQ-dtiIu9;TZU7($ za?+8>9u-eK=72)U6U_o!SetAPmypdBFh5Tvk%6K8dj5UARUq0xghQi+kV}9@3)x(6 zLEsRG7DA3!O|J9|h=G+u{FMRy1z3>@h^7U6xYrR_;#&A0u zjEafqSAa7AX@et%9kRHEeQuM6K<}SKD+JB9Phiu{)`h9CX9a=EJH#}Q#+8dhvwdNI zD&h;8gt+PT`~aJs3sXsc(T@QpFU;hoI@pUcugD%8`fmC%)p>h3y7hx=@`;Ehs0F$B8f-k} z0ig+8XQ&ab4|6PqhX)3rzq@NYUwp??m4AUy8Vxgj&K~)R5-QVwN5}N? z-LXtB+i4#l1%&p4c{g2WJ=!8Pgco;FU_q!YS3}<40r(Jm_?jN%= z@#j7A;3Dgc881%*)~xWpFvavt1m~F|dBbE#tEwuaF$LDU3s30Y&epEZdOo@d=S zV<53$Y1;E)1Xgopg@Z}FUrEQ6eS+nOLepPeWxuWP-Wwh=@(#@mmylXLo`*Qt9YXxUYlczRvBQjDLlCj#GYG?z}@Ll3iFpP=N%0vqX9b=YV_wJfR$5 z;o;gO4kXl!p6CR#WScWmFE95GK3!g}uCB1!obX-X|A9T?Hxu0R0Oq3r<3Difio+Ol zQ3srG*BMbT<-8+FPJe(r-9f zxw^VYo((dRGlx-sHt+!P$>I1*(r994;>wT6VyNL-nXy+P*6E3KBjLYTH^X$9l9g9A zB=`$+6}f)T2+vy@&33{^iE`C+oGj5b@ss1b%t_RjOBzsUCUy({PA$oT;iGvKDaDKP z2qR_jnH0$$#hXvBa3K1cTGS2Fd!;ng5aY%qie{nl=FQlDi6-+az=e2Yk!zCBLchCj z9Nx>dXy-*Mf%cw}xY-i0#xp!yk zLq7*Qcj&2Wo+~!KnvWHvxIX*~hE)n;EC*6T$HiWxT%eKZrl&U~6>72N7*WnhP4i&w z@8*bYOO;uFah>CfhX-!a<@#gpw8379y5V%sPPpwBpK(<<5aL)3%;Cd>I;3D+q;ICJ zvQ9#%Ue_ltNEhJlvH}l&lYYYs%68c*8v^QkJ2Pc|^<&q+vfKeNfq!_IlwP1^U%@%J z>>Dk+?CV72_*F$P##b~|V_WUYR4y+SG&Rq!(A5QhV=wj(K8aH|Rx^XiFo*e>tmScr z8*=J%hNhg}R2X?fm0Yr66H^pO(Mq!nG&`SOP@m%)b1d?u_tlF6M&s7JUpj^Nl~Z_M zF@^V)Qz-j-zhny0WyYlPK-Cs2x6-1r11hhLVfe!55)R^)D9Is_!sl{<1i040`x`=5RTU51u}3H`@)18CZtJIZ-dg8(NEpOA6^60PL>g+fbWOoSoW!LYS| zrVs~azAPwVn)siwx6D=^Yk5y7vUW*`lSrT_dCBK{PB4VfxEBiJ?$0k$7+T|tl68zZM8aV)4=N0}M?^oL#y-f#(QrlQQoR6codwyi1S>oKZsozw=lrgm7_2 zDlrk~*7SV1FBF0sku)dyKnCGL5v=ZeRy5J44glgM#R#YduRY{Y_pRo3_>;H&>J|97 z5J~%-qIyJW7@`&^-gnq%Mc4I4t102$OkJ4%biZ#+25cX_?7tg^gE!C%E8CG>gfYOHi*N$iNrqb>S z9rNfTgq1b}hO6qk^QmV#^cNxVO`ral1^C9a=rg#J=U|~~bo2jb@9mc3Mz%Gv>v@YJ zX1fF&rb;YQKP^Y4i+KURf@7`xTL~mcY4_eI&Wuk-v{(QViItfvGgq#kZvio}A&bca zg#8faw~h@-x4D-Q#bN>Vmx}rkM}MQ-61iWJexFXRn7Cj`Yl@cLbm;2vc|`)1aP9K5 zMpOagPLcy*)x?wd0&&MN&A>*7Ud}H7qb++_t-YBui+4;wt{rEKO9DI|cV{7%<$Q+5 zXoHEup7c|tlj@oYd^3aSJOQbMoTXqLX+4zba%yL4VskaC4<-{3cN8z~YkyrPYYoQY zz#xVX$d7BTREZtr$2uE~`chA?(ka(l$bQegGlcgB4+k4a9!c%w`APH?)ta8hb%hcm zx+Ll9V;=&?J$`zT=<#eo-O`U|iHVdGuy?wZ_cz&qfKF?P{yGXCLMxBcBpZqCG}C_s zGGvF5b6-U5KBKZKA<$Mz+kX+iC@X=h7vqDsTl|xVd|1AA0>s65EW^QQLlI{H6hQ)K z5@&bDS@Y(PU?#UfLkSJ^GyWm`4VU9nwrY1VH5nO@Rhs_+D~{ z`?185r5ShP=VfruqzyA5(1=CTv)Q2xVM5#9gf?;n*P+(Xcbyx&e7@xun+BLb?RhAu zmd2hcZMwYF#0dU)0h4!(t;E*X8%F>^$9hlO7ES->YZ*HyK2J0h%}@o(Va{6x>5L9i zJ{+!yIyKp8l2@r-W`DYOFiTT3+$Cly43+UPs8)@BPuv-^^o8G7rcz01PCimud&5dF z6e6)7s}pUlYtFfES-q>u8lBZnT7LtM&<>M0OJDL5h0Yh5 z6c7~1ci;L?Zml3G#$zcWWbr5-D#_8QGMAEq;0W$1x02 z@vcchHg~`lmVbtCVmaB;CEFUh3BFEZEbw~z4CGO6!0Um^XuO&Xeu11>ZQTs&9V__y zBP7uhCgq7X<-tN~Hf#_S6;j0iIqf24Iuw+kvF zNNwg=Qs;RX`&56i3RT2R}kD(?En}0?=)hsac&%=!= zifM)t$bWUZ(8MM@UruTO5dcd-w7;iBP1O8T&2XaRqyj;D+fa0GnzKcItFL6jIazSa zXMCbFxdMzlCDhOhiA&w7)-0G%a%+`?j1l7k@=JH=X?Mht2HBMXOkNXD-ewii8L@~j zBeDy4#*+QMk+6bJ2Cd!^ZE%%s zl%xq81n!V%HOi#HJdB_e0Ra@urdg9YGt2X`HVO=pE)HFcPXAx*${!Pvf)RfKk(JscqH+ksKQC6<=RMK%pjamAx6+j;>w_J>J5j@( zzB{?4HhXMF77h<%^bFr!Gid}RTl7Ntg+(HE;NwTOW82E!Et!ZsM*TCBl$R!nBb#=E z)PP1rtfGGYB%}f^V>)4f2%;8Za;ksBkVDM1q!i-ubP!x->$GZSNJnQf`Syi=T4NDD zW>tIjoK3h>l7P{NGVg|R4L=c`FKWkaNkeB zYQnxu*r#|(Q=8MVFv68hWS^B2=a&!Ew=oSS_T{O0R;uJOFk^(_tNQa-6L`TFt1=LXjuy$`{-Q%f!*zEnUe$uLuX zrc_^L=9j<`gA;=srwa4P4sp4L;AoQt6xlLi`XtVpQH=_edoN9{mnMIllzxA|?+A78 z%y}erV+57nv7YKam(%n=V8M0E@vN2lOQ&DNjJR5U$yJ9>;@Tshn9tt`x^q4uZL;uL zIv8EN-;M?iy_kIB+DCf}J^gE>4nx+>%m$G5;F9hmv>+>UGFuI*a$r}6*YIe$r(ecv z;3jh=Blp+8@?EdAPfvebkCDpnMOZXPyro35slYm>kzjsBAO$K%NW`!D;6YDe7G2&; z4&!@bA3TT`WbNE{RIKB|?bOY5!izG{gO~#hbf0iNkF3`ud;BX-8TZ#qB>XRlFy)JG z)#K3X+ZC@1DprcDNm^U}i02ePG(feg-(fmP%BmUYGa{yc0SABhpx97ermj2n(^EH` zhW7+*cFZR;7DJn8V?NXUl#+Y82%_$5;vE?3_^#~3p*gGX39TGa41628oR9z=5aus# zfu5SLr*o z$$zGa``msH$)!+pgIJ(S|EMs?+SZNWWALkn+zO=9KP&hNc4xvBS8v=bBrV6~H_2$r zE@<)bb;$slF9|qM$v1~Ipi2$Z554R5nR;oDBIIa6+-QG6NAx;Bd$yMd8|+wSQ=%p& z4w8yP)4SnF6oUSsiv$5;Ph!r)LUojg8B&|{cG$^#ctb@AsT5^q1Sy70FlJ{FG_#S4 z*UUzvv?m>6gVDs~)0B(`YA=%F%Qw{wY|?PFXn2C5Ed5u-gjR7&C$EN9 zt~+HWY=(bJC^N#P+n2&FOA$rh3yWJ;NT4JoiJR(ChJXj~e8_WKN?Vf9hAj-0v=f-8 z2AM6{?EBrBUI6wVi$T%7qodz+g41YhTxXZ2qEX84nFHeQ5B1SYPz2Bw9zaT{2fnEs zwz}GaO)9|ARnszb+Lw-GrV;OZ31TwHj_ul<siC6;T&06k*VhDTfnYp|fAzK{(Cc%Efe%(dApRNt=h0*{5Y%8vn@(uLAPSF(RA zHhK90$d19roX~uQ&u>y?XOcVtIqPWFOX9N2X3T#Ms5=Ef`%MXrao~d9)U!ae)*l4e`({0JIWeaG z9z@;|AcpyCYN20U<&nOA2i<}5x2SW=2jw>#k+?(`KLHhNu!c7X488a{!;P~H5@ zn+==_wbQVWmm^;YUWm_dpyUiT0Lj|r8f&!57ffTd75HG)j^bMp*V9XEte)PTHB)8) z+O|ejvduksI9XeDd^-codSHJ|kf)wC7j-krw!o3;>G>P``bxg;+%*vJ6~c46hU2A$ z%kReH9l6SzV-65CimG(VAIju3zZ|+Y7fJ>_Arbw z=+KfJsbh9wWamdX?t2Q@jmxZ|V06@(!(V@tpG{hFLrMembPl37?(l!05us{D!E6Qr zU`y;!5Ogj{8Y0;2p4;M*5nVS-Jj5@I6w}7Dh|WZNl}LMd2%eDUIJYmJB`G<|%pi1J zGLtNE!HT)jE2eWY5qiJ9*V#msL!7Z8H+oj7Gs}4|5h~wLtED^w>fN!Y%TIlh33_yRX2xO@yRf(PkjZo^- zgj8_93+xqN!fvN-#OMYDDiXg!g49CmH6AT?IY{!-aIdmEcMkIx@V-`KbqqasE_xETP(gopcLUtJ0EYRF59nsD$ z!^zY}%~rV+nSOr|d7E%jfnBu)%5SjW0L@pgYkA-D3I4^gx4c#tDC+l)dFESVwu+jK-zGy+dVI z-|q{DcBmq^2RL5-8S<2Ij9}7-?3mcclbmy)l|%qW^){3-ptJ^!hAgDYRVcYMZ+CKF z&^wtL)f~MmUY~ZMNi%Ve(;fFuce1Y4!6+(QZ;X04#G!7zyI`$i__aX*Lio)YsFew# z)!_r@>v(_cJNImt&uYban`YpDI*_FwSWwMQvTkW3B&Prcsh*u?pOUK>F=OPYnlQ3- zaXi%N6IUs$Jf*OOQ^-ZWhI3wfwPeD2T~_1qYAC0rodHu7f>@=uN-@tMw9D76VX9r{ z8=33y+HyB2>NKj#dV!waC=)QR3y_k}#1Rg*3n0&&it4l@H zS7TgO|1+PL0j$S+WRs-bKEX2lFj&4$?y4m2AAhKtW~Sb!cq`)MXUP4(qfZ1!`(kl8 z#PP3Dfd<&Um<6~45o5$bpAi<~8DeO@V|iu*yoS#S<;b?cLS{H9j+hq%&VVdNByiB& zuv~xS=jS(UxueD9xdM!xpC_lEpPYW063!u%i_^OZE4=JitU>er6Gh%sn+)$3!s6aD z*?C*RWr8QcFjWrSN|uWaqbtbcL=7)S<&ap^R#}Ho8&tLHT0A#4)~9SsK^-t%-p)?4 zmTaYSu4F~?u6oL@-&NJN_U!_r3J=m&%-w(Ra#h`o$3ywYlcKVLsg%$bxl5Y^Qw^> zMX^lI!BNQsxW>pc#WDi&?Ad;wJOi?8IHbWrK=7<2&WL1!sPV`+5Z2HMyV^m*%anf% zsj~ES;Y9DM0YY-=mjBKMj{(zG4dn5a02a{)C(^+uDu8>ZI8!t-QF*cla$qKdf53h{ zxB{#aFF{?9eLUE083Yku^O`r=VAC|aI(zi!qMA_r^kl`Z9~F;QRZ+Vrr7s`gQ$#eCiX4`c{PCR|~)4SKNU!I+R^YVZ7*N+C$} z;XP&UNjRZ_3*)uRY=D22*H9Psp%Jubk|CVn3bb}8U^q61YEctnqJ=pDu~Gm z;bQWw;$rRha~Qoex+g#wXGl20qMi@;#1lT0>Kfe(Na&vS4rycsIMwfH(C`09m%YDV zZ@o7i)eT{YGtYYFr_no2=i)x+QO&F>Ru2Fgjdvh*&Ooj`_3eMbk`=VAnRj(iP!$-U z-3}z*PsaDrc^Dzz zIx-RE(|6BA`J8`$mh=S~>tYu*l&iNgfiQ|g9V6f=y80m!rWB7&0xlTO7OY;zce(}Z z)GYsM+4}uR@s^$RXdYLW#nkdRN^X;7fW`7UFoIfbA~lG#u&)xfG5^_moS)0h6t>pq zmC%Y$7YgU^!C|J~^K*rWeoJqn`E+;oghaZt$SD3jH0Xcv5b@rya_0AfwIC#&5SLTr zyXh&%&rlaJQuIWX4v??=NWuNk?=C1W7Q*wt)jKEm@12O5=C0oH+lk@xoq6CJi-KI? zo#9Y)1;o=QW5%WE)ybM~8z!Q>i?G%XA&GZYK8eRy^;9|5N6{+BY+li;f4Iu`3OVTA z7(-Zfhf(ihAVW}#Vf7hL!!l2x^rI00DIl1aw z5Fm?g0=%q$SX{AXdy$M@lvz4O37^F%~=Uyz|6D2H-}brXM?$CGMDKq+ok%TDaa{Yr5kjD_t* zO6h|@dygmG3RyVybN^g_R|SK|V~q{qqq-Ql+MNS?vHGEn&%#(M*4e|<;v~;W90Ns#DhleV33gLXg)`1USfHX zA|HS4>XjWXe_pL zl^i*6iK=RVLUF=Z`@Ki)-=4sFft$U)rgGX&S>G&RLFlYEFaP-B*WH=6(sWVx>(az#;bPZloHm? z=?dB5an_Lj>f8xYV$47~en~{&Fkd<5kXmV59 zbX|!=MhD2p6h`>r>9qYSKbby!*rxWiB&jgfyL@!sE*81D2^2mU$>M$m9y37%lk;;N zNAM@v5heA(_0j+OE=7(G(i{?%oq~V2ai{yqpFanudvR9^2`3rv);*fz05h9Zm9M<4 zu1?Ny34dMT+CJwi6=d&k@POu#G+CGIqpVTRK?9%hZNgI>&UJgvR~bKKz^aFNUbd3f z5Ff%wFd&V_t2zvSWEAI;j4~Uh-N6+Jj7RpXC1xTE;<<%l@8p|Y2}VFV$tr(md`0ML z^-eV$pe0gz01Q}hLWfxeAy1?2#GUP8KsTLEsx;vnuzlEPmVWXMuedJ1&x~)vhqA^g z?aEvH>?wqjFqz^B?K5lQ(hjB>hI!g6vM(<3NB?hrP9Ofhn4h0K{1X27uSeWz*R@;c zE6H4UVa4>UnV&2&cQ$?WBTIjVL&F^bEYOMMn!S{PFB5hRLNRihHN_mf)Yx_ShRia} zevojS6~bx_l=$z~dN$yNk}w1rZ#!w#;e$bT?YUS$X*QEw>JH|OH{g~XW5}M$|4mE1 zIdJZf?qD)3=iW1KA-+r)WEM;s_Ry>~%#0K(3nAVYT_iyCjiDvtv?DJ^i}8U#6DFH{Cx{F=Es)!V-AYIB-MSUNvhDD=Fv zp|BT@CeQ$hgG_8DU}xfoL+ni0R7&c1rb(B4PG&{(6q^k_V(!p+L-nKuCY8?dz1vB4 zDos{w$4a@u5hDV0RY*X!2-jfM$ke_1afmC_-C53?#UaY++Sq>=yqS&jRPQVG*AO$n zRO+?nwln=u2dTMlsnI#FZ3H4SrlnbNAw@=Naw3erkv@aQjI3i&U*rWJuD} z9|x*j zUE%vZpR)zPFXwEL-qw(Z<5ZzpQOB4zl59!Xsj{Kvb~O}kFqWcy%Zti zZc-8q={wwEy6LbVdvY@Mq_dh*;`Qqtg`1OJC+U!Ib zdrF**DGPshDx$W(%-stK9yMW?b%@b{x4^It+J4qg#>kp(4YhXGV1!>L_Iup#4p~EP zaXn!KJ_7vRo{t5_wVIxVUngx!wz-(MDD%x!+R7)^F-qxX)@04RUF`SGyujDinulQx z5oMP%ewJbMi&P%AXCuEzi;6!8^Jsu|&_|;*V(A2dlNb$nJxKb(F zlbGyRdxQF@mkwLqa^;P#v9s}{WO#Cjn4HwI@(^s{gV*{kB!G=uqmrP zw7(@=KJi+JXd;px<< zUwj3F+1;ime1)uZI?`Q+9>W=)IsEi&0##Ok5`QG6{2NO1sVYY8=~%Nwir*4wz-)e;);`7PE~eh!F$>q<0|l`^z&V|)AD%Yl5eT6MSf zC6Z2?21v7-o)Z|W$y}ok)Uso6mY2aUdzVxNf0Pjv0ycT*2slEx4L9$pv27@qi7t9rdKae&_aAChcNgs3^8iKAs| zmC{<{RvF|;xq7nU+tpjPezB@CkDY&+S6I&`B|4keTr4z3K;&*Yk`GC!rJCMqi!fIU z&F|4^%5$!IbSjRibKGHku&f0^%(LHuyrV9=k{xt)b5d<`tG}~FRJH3KW{0KO&b2u} zPP1fQg3Be&v#X9$&0HO&7MQ@;vvqmn5*MIKz|5P))VvCtg+T7u5;+GBKF)s!n-*pR zxs;3y-?83|)^g{$WFKGAOYnfBHXvOAR9v8Ywlz7Nr{8mU8)Hdo2{VC+>+ z9&LmhDdTYx^`*N{bauT}?tX42eooTN7OvYUSu)OLhT}9;nBZXFV;foN&m{ac-qFOO z{2J)BO1b~LkCYmIDx0j2Nm75pI7XI0jH4b9bFZ&-@k&)t^>DO7G=Y!SmAGKdC>tSL zsAxWp(lBYadezK@2c!Qpdf-~5AFIYcRqVx{<)d*G(8I91?e=)EoWws`eq!Dq&uu`s zjpGyhy+G1}nz5B+{j?r03>)RI5}s<`mmw&toAydlwDBiNl@hpuM}dELf-`>xKn}gi zXiPLERgaI!$Kt%CA3cCd=u*TQmLY?T6m~dyFcx&eS9wFIUiKxSva>(tf>33<=0rfx z(|@h!OW!$=NI64F=iq;IpS}-CZQRA`yx_P;SguU1d^JnDRv};1AJaOG|DiF5KAxBE z*=#0eLYk!R(kaXI)=*FgFjsNduRx3SkC5mkN}B$IrKe5t_?KdZrdi|e=A=xKU%}~4 z)U>kFt`60S#2#Kg1|xPKgL&67Z|mPIbSyEtUnpg z5e3ItUrm}ynvc80f!4>ETiYqqf23gI)%uu2i=s-BBwmnq(U%zfT}t?qBSPJjWve`T zRyMqmQDu`e5QZbtxB%XR7T=A(YKZ!+h5Fqx;g3qvz##4mQ8mE$jOq{PdZ%Yzx_j!2 zfRzbXU*62ig{6NMPz#grbS5(HY`9MyXxT7fo+kay?!emO?7aECeRCeTV38F z8XYZjw)rb`nUjU|ZoaucI{|XYtJh(JmAmWgXGSl<_xg(Nv^H3kYkrX%e?KF)9*96j zY&e%X7y^U@I9WHUQX>N-nQM6|Z?O-oXd8CsbO^vSL#cmTN@|3jp5Qt5@08C!TjWDA zm75<}d1B?KlO1E1YTlHD8?iuVqE8A?oAOS5enMAQyh*6ii$GA*ECH3wR1@u(17ZVTDz1jU@O#O!jaSB_78SSP^#*f z`}IptXIP{M+UyYOhv^L5c{PKzVUTdV&syBx5%Y^*}u~Vdy%I^xC`BW!^k1g=z)|Iar`zz>R zp2+P8+-ybM37M@7C6rSe<&IIAX9dx<&(;o=7IKWrNs*Nw;9L`S#r8n>GvMrVxWxkacM{UEesN90n8u5zam_;q`Y=9wLO`bK^1S z@H)mNHK3&)H$z0M9s~9Vn=w)rcD7?UNx6UX!_94>kSPH68&=2st6W)|@Hr_`05_v9 zYjI5(^~oIt!}k)xF4dxb}GNd;|JC4dl&g?XXWv(;KAKdlfs2byO$B|l$$HRYC z+mXNisGpn{3t)hhS+{KivcfPBYHOizfOzS2(|`CQJH#PCOY77k^yJ-T-a77H#|0`` zhbGt1nbN_QF;`?bC$jRtfLMh^nuDc6aFQXIO>00WolY?-f;vQJS^ zodYNo_?azz>1zr3szXYyJfP$mYi5$Q6bSJBuN>I}?vnpO4cJp`L#HNbR)t#|)}mBP zbw}$uS*8wpV`-*flI-*lEy*sG=xUre7dd+Z?$n8oeUy0(F5p}NIUhl!zMOw-CePnK z{^k|X_?*3Y`|R=4Ue>AatAXBD1}Z63Y#O8v1=OF@=>-r+``j&cazTo8JihQc(Z#On z^|C=H#RfTIr!obDk!Q~VF<>_wvdlYOIdg=bRIhh9sU+ZFXB73N5)rZO2gvI5eF&CX zMz)8Df_Z$4kV+#rO5?HpfYg5-!Pwp@80$YG7_DCF3pZhO`7@j^-AtvxZ-!& z0H*KoiAigu^GZ;nwm>Z0OfIk+qqb5%FF~Pje~0ADIF;hk!_j&gB*g&3xDz$=ryvV}JQnbu zwN*ksM;NgfZF_Vbj~mQU;ymdfk_nriEK(`_eukffe-q<2vXp=Jb{2P)BROP~Q3|?| zO#G^_IPkpb97!qEpI%~u>feqHD%ghXkjh`t z0WHnm<|M;`oSF`*stTuJbU?uuezL$6m_X#w-_ap%`G6V3d2gs08kH_rSq;_n3?Rd<8PFlju2eiHB z0CoJ6s-whD+FGassGe?|6soGgpDG_ZG2htEPZoJW_|FL^Teo<9XdTEYiZDkFTHo(S zw+CQ_s$dq=2l*%)J*dFX<_`9sT)do8FLar|142QtRa<{BcXziL%48U%ivy+B3sL35 zh6q+NM6gO}o+KRg5HYV7iyU$zPFY?WAQZLct^>J4{QMryRJm0_EMe_9o8hM+%3wXY zcHJneg#Vs2M-j*-SEol*p&Oi^q*)>i^M+M>=KR4axZ@J@z8-4tWf$NftM4@W8$XB* z!Yk~}pM!rSMP**@_xu~eze}2MC^5rV*E%fyzOV{Mo+!axu0SIFcPdelmBH($)2%aHU5$~CQ1nsIk4|0 zNOq$IQTahR#NX$h*NXqzv?Lhe7dvZpB+e3d&blGg^8-xb%Z+nV85dK5I8^(31 zFiUXzMu&*?)8JNLv&V4W?|-CjF(h`!UeTRNsx5Qzw7>uU@vL3K&Dy`!v6LJSM)S;A z{f{Dd-kYkf`EtwN;a7*Jp+CvZoDjsR9yH`nQ4V*^#j3>;c&96sjC3C9_}y2E5wrIJ zmluC-gw9^K3F?SRS1Ye&N$?oF=Z>j;?VWQq@gItM3?h^mPB4%{go8{+46arjKvu~! z9D2PRUCE?tM3q$`*h@DuB;D`b*k}y+(O7`a@K3BCL2YVt*R`;i+I^)_`BZdG_IoC? z-S#oJJ1BJLwXAZYEwD`UbHDFEH2H~z(tv-*z+e}xipq3g1y^1OL;&=p7eAmrL2ZsA zGoF~`yMR0wEvn6>bcO2~8&2?PG1ZzwafEQ7N=c0yq!Gp2G%a%eW3o+Uk|~jIr%S=; zr3qRTxtK|rm2C`z};u=v7yIl29~(Ox&8C7B7E* z;!!(m4=>gZOk0ro$h6DD*A{gB;YY~0I@=v zl&~e6pYw7dwTBwOHtywoUN7P_7<7>~Q+?5q{T zI3;wONdsZCgy$4MxS+;IzLpAH`Z>2L+91)CIu(&Nm!g3bU>}2qO}%#2Gybb>SDnuI z-(Wx^U#e%dX;Ic>PKnbKwdbzK!JApMAhpVHeI9dzwB-t}j!hJyDHA#Q0Q#)hmNXO36 z23(bH!nsbz=uXi}1=<&Z1V{8*7&{ekr)=*I79UUP%rBA8qx+OfL1d$df)KmFVbzzd z-A-hwi9e~z701l#8dV@|6Z+@rRO6_}7Kmcf(I%=~T9B=u{ zovzO3)q=E<1NlyX10kw(iBSk(OCOQ*lAUpW)3>^N$Q?kxa zrtAOKNoS`I9+>#xdcMZ}ccoinF#huQexGc^lodBrlt4ndW&-H}YWYRGcQk-pSPx8R zIrdfxXdo1Z6hmvLE3=x~6f(v@z;bQOTH|q-14qSQ70|FPi1B|&+mEES%o`+OMzc_diY%FCmlhchQol2gnDE5C~; z#PPUvCapcYl}-e)&|nAo8Oh4ibJ8Mpj%K1MRp+EOrwJb6+`~|trZne&OImdpYVvl! z7yfxD2{j;XS^9q_ZdqdA0n``1jfq3yJ;42fHiA(@vnCS{z$)8BC>x=;=vXpL`l}dM z64L`tk4yZB4U;qjW9L{5j8pnx9GHHIeK!~0j?|6yW;mAD3CHO0o-gp!$wcnWMmu{b z&I`1)OO^wb(N$3poaz7|n840=Ot?R|^k$_(n!+c|VO@XxeF7}QvNBFen3l{dQY?(w zq&h?xZ|Ul}8jXK(i4AapL4!J_zXByaTD+gkwdVt%dKg__FK9j5OL0AxlK=nZvj>vk2f*t*%C(N(hv!d1KwYD()2;2BD~bmo3>2_ssEs-J`N=P5<+sk^nRb~oz&qhw5Si8rQF{OngIIA^SkyV>E`9* zF~-7~cmoBKh0pRE_@Ko>N#v7)tClH|K>Qng7PpDcv!v7^1Euq zd@*jl^NmqEOWFMOmR?sv0-YT`e%#yDEtP*^9YA47vH!ZWY^aV0y~5`^_2B;i(-{I9ak56O3iIS3ta}zH4(~%RmIcUagOapsL-jFx!`QTxlrS zs2|7TNTn|<%L|2npyM$GueLnZs#8WO zBf(ISsuN0T0_Y7Tu39ZmraW%}%3=1E;nvP$t@Ot1SXG>ZBE)VMa~H^hj1&q&yN>bN zW5CTE`Q;V|vWi#)Oj|tz%i!y(+A=E15+{%}R{yV5%)|7qh++sVl{~O3{EvS&0JI^D zY_-CW9+;um9r11MR(?Sf6O=2l11bi5{shNo88m_W*cU1D(xVfk><7;fo9{OKF^xwda9_$nLea=1J@N zdP_lUOaE2Ei6E2|=@BCgAe+RT{XHpDNmr-L@y@TcC`#^a$0Spj76unrIDK|Rw@bH_|WNk3%s?}$s*U`>$5GBOIJLO()N zn7|cuK}+BH2{~n-Vf=p`fVcI;F{HwRxHHDvSvhejtUZC?AsJfdh_=P~vx4)}E?>=0 z7gGd*ZO9JfK~7EQL!^jAfG;J;yHuO;@(`u1mvjCKcD*ts7df3Mg$RXK;{MF%3tYDs z#xTs&ukw@qKDm&_VV=5bqcRZ7A38=b5#$Op9vChC3Mb`tO!$A47T-Hdu3Z^o8th#q zZAz}K?9TaLlWTXcPs#ci{O{V+1W-I6_%aKsR->H0^@qypNBqmAGJOBqk|E2?)({q? zWn3HG)q2>tJ8lVsQS;@140g&{1f1s-r!!6fmsdv)$*=K0Cj!RFoLIiV-=sQdD&r%X zCi7>!UrD1gmQH`Ki9?zheeql1XA2nCJb@qU8gsfvhIjTY!n;dvyVaD(TEC{z&ArlW zLXMTsIW5)1m@Rb(7F=_L8flG4OQ*%;n%BHxtNlJPeqX@XL73SOtEC zZP!&d#CVLRaxvj+=m%6-LDl;qsSHFKy;4b)PPbTi4WV#eD+{<{dX{ipi520WB_*i= zYi(oX)(|5HT^EayTSE{0hhyZbo*22mrqea3cwvm(8lsrJP8yF{vJS$FZOabeCX&H1 zfmzo%j~suo=xSFcGbb9EqCwkoDgs*V(6J*)ouZLCMFYg=8Z1`i<+O#QC1{DBFYfYLSrm{8hB#BZ@-6k!VajJZq6r}O> zPFQ2$rc$0wb$+7W36GJIRM?TzHM}CHreq}nk%E77up#S|a9nQ^pTZ|Q$ZL*^0_nDq zMb*XSIjya*1$Z+A2*j7=9 zNKl4b0%2ZpHadYiWAdeAMPU2=Fwxy*yTE@P!Y?{ggD5B-@@b97{7cMtl)${eSP7U3 zsu_(+OhgU+tDSU+4)c_t?sg?QqQWSUog^b*&^Ul=Qw5kY>6=+%#oN>$|vf26rja(N~*;XP2r9f7&FGu^#6X37QAh{Vp3vk9pdPiI|jLQ z24Kq>T+xq%B^zw3x*6PTSUHeXk8qT0HV!7FB_nkNtkwhSobPHwb20fx`H%7)5C<1% znk;BrvjJU6NSA?9o%PqSaBsUvgYzDkW`zReO+lv7&2ak8vc3TaepdyqK zrxjb}KbwshhYt-{S+{}>AQ7)@U2P+5A8b{);((SAMEhVg*wAY>pylAj(?NeF26Rxg zbyHm_kB}Z?0{2GQXoQL$FInG%7^sWgZz@>m{wIUF8oVf9v8zgalml7Na!}JXGcKrR z!)m7Mok2$p2FP0omh}F!IZgFOisx}Mg7@@s?Z|so_q~6V&nqEOry%3R6_uiAS+$L> z9zwcnGT0%Jw&YZS;fIE=RPujQd`-3BzXs1>P+)2@WY04rgT4RaX`Kx=O|z@BM~^P5 z3B|#Nr1Ou8M;EMQfmpz!FB94Q+fgo4Yed{{zLxBPdu zdZ;S*k8*@6rxeHKG459%Jac-;_sg9^~_j^P}Q_yMh~zIg>r}q-JmN8aqBR|-9;c5Au@E{P;6cqGm%sP7Q$=B23TVrNTEz;SM=kO zeJv`wDrnvOjCrO#nmi{Aw3#fu2POFT-{-w6{dCk#Fb6W}t5tvWcP|9q=q%JnY4 z|J}LSpS-<0Ycct@H^)%6_XN*)*}r8+;8}aW7bjAuBHlges{q@^)fHQD+Gqh3*-zj> zmtE8pVi>;1<6+}{c03lRpkOtz@+LAj0r*M+KI_73Uim@F)+C)e89YK6T_l!^9qQrC z8AL9JI>mo1u8DXLzCg9P;RxT3-_WrZ&it`ttVl8*%F`e(kDFQYE*Y)h4Xh)h!|XhN ztWbQrQ)(naT-w;Y^r+H!+mZD>$x5i#crRc>eq}4z9&-D#) z5LGtU0$kQHA3&d9!l%s!O-k&<%2)aZ-Pym^e_`J!Ec=Xj@ok&)YEpR~n30z-r@Lt!F3u@(&4(Rg&Tp&j2y%Hw|< ziB8OWq#iv1Zd+P6Px*SSZ9AZ!!@wlq=1W|u8{uqjyxS_M!-`;cP68-l*aQL@wsDwn z!DVm73CQk+X+zPID?L7?A&1qB;^6zzmWsqSE63Mm3K1Y=6Zx%gB)omR+llI$eOoQx zh-z2WbbGdA#T)u@ThUcEAI0yVwFQ5`Y(`}CZMA&7g@gRZXPD3D8GzkJWb}R2Jg?ev zC4Vo-*MhGum@QZSjy(7T&cxf^`b2Nr>U2umP+mH3!_U}bh?sr+=Eb|}lDW@&*X?Is zl)JXUmuvHO*h2TJep5gDEB|_5+vHQ>ymGI?cy4*o=)QIDy(q8gmLnuMcDsMg z$fv?7>R!F;-8-k}(Z}v8-J5?P=F(kn^-Ph-&3lw|te|_B6HX!b>Rs>t^!9n=U3vA$ zySxU{=WnYeUU6RcZ}gXd|Mv*2e`8|Wd4KOMg^b>|<+s&R1`xh&%e&>vvu5M$$+q?W z^+>CqGupI*)%F#A1#iaWqkA<{;y0{0`{Cuw>H-{|_APr2p4nDQx_y6HUA$!1Y-=C# zua6eQTM*w?%gFbf4byv6UyQ%FAcPj8>AzkX)RO;ug$UzNCAZ>t;pxgda;wjBb$BHi(Z zUhoq1xKP>A(+AoL($4wq&%nn`1Nl;V?>jf-p!gS@Ur9zhif`s(aIW#0}r z$*>y!cDXnlrd!qwD9@?Nzej=5Lg90qNhSCN2O>rV$p?di;F$%vQA$RS-YZ7e zLNK&a(`}uN6t-*x(Pj#N=|K(BgWU{hnFQxE%6<68AthU0US_nCp{;cC>jY}HWss(; zO;UiO({|fDN2pLf`sJ5jetG!n)x)Px2b=8bDy!?k;}IDdMt_Tb(?}r&&Ta`U2;JuE zB%N$Nt^{q^lot8l3Ed`z3Nd`PW$;GA8Xf7K(fUBb+pEd%zsYDmrSJ})ylVNo4ZC7* zM0L#pWO3WT&+OZY=oUl^qNy{8t}d8T)O`qqNk-rRL!?j&p7JD}{(nM%UtqFAKLAO* BRfqrp diff --git a/operator_ui/TAG b/operator_ui/TAG index 57ed352173..bd6882b0f5 100644 --- a/operator_ui/TAG +++ b/operator_ui/TAG @@ -1 +1 @@ -v0.8.0-7e6a14f +v0.8.0-094d250 From 96f332c1a4fe442ed852df289bfc4c0d2a8a9120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20Kar=C5=BEinauskas?= Date: Thu, 27 Jun 2024 18:43:10 +0300 Subject: [PATCH 20/61] Simplify capability configuration contract interface check (#13707) --- contracts/src/v0.8/keystone/CapabilitiesRegistry.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol index 56df507867..6b150dc5d7 100644 --- a/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol @@ -1010,10 +1010,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { /// beforeCapabilityConfigSet if ( capability.configurationContract.code.length == 0 || - !IERC165(capability.configurationContract).supportsInterface( - ICapabilityConfiguration.getCapabilityConfiguration.selector ^ - ICapabilityConfiguration.beforeCapabilityConfigSet.selector - ) + !IERC165(capability.configurationContract).supportsInterface(type(ICapabilityConfiguration).interfaceId) ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); } s_capabilities[hashedCapabilityId] = capability; From 7a3ba8ec4ab70002d10a10dde2d885fc37cded7c Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 27 Jun 2024 17:28:00 +0100 Subject: [PATCH 21/61] [KS-347] Start tracking registerTrigger goroutine (#13688) * [KS-347] Start tracking registerTrigger goroutine * Check for channel closed * Check for channel closed --------- Co-authored-by: Bolek <1416262+bolekk@users.noreply.github.com> --- core/services/workflows/engine.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 362fb7fb09..2692b53f5e 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -355,9 +355,25 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig }} } + e.wg.Add(1) go func() { - for event := range eventsCh { - e.triggerEvents <- event + defer e.wg.Done() + + for { + select { + case <-e.stopCh: + return + case event, isOpen := <-eventsCh: + if !isOpen { + return + } + + select { + case <-e.stopCh: + return + case e.triggerEvents <- event: + } + } } }() From a0b85e4c58d355ad5daa2e8cc2d1200992120560 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 28 Jun 2024 10:55:36 +0200 Subject: [PATCH 22/61] [TT-1190] support multiple configuration names (#13649) * support multiple configuration names * TT-1090: adding code to investigate issue with incorrect config being used * TT-1090: adding code to investigate issue with incorrect config being used * TT-1090: adding toml test config for remaining chains for VRF v2 Plus * support unnamed configuration * use chain-specific config in VRF tests --------- Co-authored-by: Ilja Pavlovs --- integration-tests/README.md | 2 +- integration-tests/benchmark/keeper_test.go | 6 +- .../chaos/automation_chaos_test.go | 2 +- integration-tests/chaos/ocr2vrf_chaos_test.go | 2 +- integration-tests/chaos/ocr_chaos_test.go | 2 +- .../docker/cmd/internal/commands.go | 2 +- integration-tests/experiments/gas_test.go | 2 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- .../automationv2_1/automationv2_1_test.go | 2 +- .../load/functions/functions_test.go | 14 +- .../load/functions/gateway_test.go | 4 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- integration-tests/load/ocr/ocr_test.go | 4 +- integration-tests/load/vrfv2/vrfv2_test.go | 4 +- .../load/vrfv2plus/vrfv2plus_test.go | 4 +- .../load/zcluster/cluster_entrypoint_test.go | 2 +- .../migration/upgrade_version_test.go | 2 +- .../reorg/automation_reorg_test.go | 4 +- integration-tests/smoke/automation_test.go | 22 +- integration-tests/smoke/cron_test.go | 4 +- integration-tests/smoke/flux_test.go | 2 +- integration-tests/smoke/forwarder_ocr_test.go | 2 +- .../smoke/forwarders_ocr2_test.go | 2 +- integration-tests/smoke/keeper_test.go | 26 +- integration-tests/smoke/log_poller_test.go | 4 +- integration-tests/smoke/ocr2_test.go | 2 +- integration-tests/smoke/ocr2vrf_test.go | 6 +- integration-tests/smoke/ocr_test.go | 2 +- .../smoke/reorg_above_finality_test.go | 2 +- integration-tests/smoke/runlog_test.go | 2 +- integration-tests/smoke/vrf_test.go | 2 +- integration-tests/smoke/vrfv2_test.go | 12 +- integration-tests/smoke/vrfv2plus_test.go | 19 +- integration-tests/soak/forwarder_ocr_test.go | 4 +- integration-tests/soak/ocr_test.go | 16 +- integration-tests/testconfig/testconfig.go | 53 +- .../testconfig/testconfig_test.go | 2 +- .../testconfig/testconfig_utils.go | 19 + .../testconfig/vrfv2plus/vrfv2plus.toml | 655 +++++++++++++++++- integration-tests/testsetups/ocr.go | 2 +- integration-tests/types/testconfigs.go | 2 +- 43 files changed, 803 insertions(+), 129 deletions(-) diff --git a/integration-tests/README.md b/integration-tests/README.md index d34b4426fd..fcfefe97a7 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -127,4 +127,4 @@ Run soak/ocr_test.go with RPC network chaos by bringing down network to RPC node ```bash make test_soak_ocr_rpc_down_half_cl_nodes -``` \ No newline at end of file +``` diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index 8c1d5bdac3..7cee5d18a8 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -102,7 +102,7 @@ func TestAutomationBenchmark(t *testing.T) { testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err, "Error getting test type") - config, err := tc.GetConfig(testType, tc.Keeper) + config, err := tc.GetConfig([]string{testType}, tc.Keeper) require.NoError(t, err, "Error getting test config") testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, &config) @@ -308,7 +308,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.KeeperBenc TTL: time.Hour * 720, // 30 days, NamespacePrefix: fmt.Sprintf( "automation-%s-%s-%s", - strings.ToLower(keeperTestConfig.GetConfigurationName()), + strings.ToLower(strings.Join(keeperTestConfig.GetConfigurationNames(), "_")), strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), strings.ReplaceAll(strings.ToLower(*keeperTestConfig.GetKeeperConfig().Common.RegistryToTest), "_", "-"), ), @@ -318,7 +318,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.KeeperBenc dbResources := performanceDbResources chainlinkResources := performanceChainlinkResources - if strings.ToLower(keeperTestConfig.GetConfigurationName()) == "soak" { + if strings.Contains(strings.ToLower(strings.Join(keeperTestConfig.GetConfigurationNames(), ",")), "soak") { chainlinkResources = soakChainlinkResources dbResources = soakDbResources } diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index a6267138d2..d091522c2c 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -134,7 +134,7 @@ func TestAutomationChaos(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - config, err := tc.GetConfig("Chaos", tc.Automation) + config, err := tc.GetConfig([]string{"Chaos"}, tc.Automation) if err != nil { t.Fatal(err) } diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go index 95b8373dc2..2d1bb5b10e 100644 --- a/integration-tests/chaos/ocr2vrf_chaos_test.go +++ b/integration-tests/chaos/ocr2vrf_chaos_test.go @@ -32,7 +32,7 @@ import ( func TestOCR2VRFChaos(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - testConfig, err := tc.GetConfig("Chaos", tc.OCR2VRF) + testConfig, err := tc.GetConfig([]string{"Chaos"}, tc.OCR2VRF) if err != nil { t.Fatal(err) } diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 3b7eeac888..54a02cf64f 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -54,7 +54,7 @@ var ( func TestOCRChaos(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Chaos", tc.OCR) + config, err := tc.GetConfig([]string{"Chaos"}, tc.OCR) require.NoError(t, err, "Error getting config") var overrideFn = func(_ interface{}, target interface{}) { diff --git a/integration-tests/docker/cmd/internal/commands.go b/integration-tests/docker/cmd/internal/commands.go index e05e5d89fa..9939765f7f 100644 --- a/integration-tests/docker/cmd/internal/commands.go +++ b/integration-tests/docker/cmd/internal/commands.go @@ -28,7 +28,7 @@ var StartNodesCmd = &cobra.Command{ log.Logger = logging.GetLogger(nil, "CORE_DOCKER_ENV_LOG_LEVEL") log.Info().Msg("Starting docker test env with Chainlink nodes..") - config, err := testconfig.GetConfig("Smoke", testconfig.OCR2) + config, err := testconfig.GetConfig([]string{"Smoke"}, testconfig.OCR2) if err != nil { return err } diff --git a/integration-tests/experiments/gas_test.go b/integration-tests/experiments/gas_test.go index 88bfbcf192..4d1f459711 100644 --- a/integration-tests/experiments/gas_test.go +++ b/integration-tests/experiments/gas_test.go @@ -18,7 +18,7 @@ import ( func TestGasExperiment(t *testing.T) { l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Soak", tc.OCR) + config, err := tc.GetConfig([]string{"Soak"}, tc.OCR) require.NoError(t, err, "Error getting config") network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] diff --git a/integration-tests/go.mod b/integration-tests/go.mod index f33080c3f8..5e575a5483 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -29,7 +29,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 - github.com/smartcontractkit/chainlink-testing-framework v1.31.5 + github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 780bab37c7..d21adca4c1 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1525,8 +1525,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.31.5 h1:PemXseNS74zz1Oitm1MOCeJyQSIYCFck/QsnjM1y06c= -github.com/smartcontractkit/chainlink-testing-framework v1.31.5/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= +github.com/smartcontractkit/chainlink-testing-framework v1.31.7 h1:Vy4ah8VAfj+Y7vVmhjvwyAO6wG+Fp2vzdkSJwJPMQO4= +github.com/smartcontractkit/chainlink-testing-framework v1.31.7/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= 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-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index c1b6a6d4a8..196e8d230f 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -153,7 +153,7 @@ func TestLogTrigger(t *testing.T) { ctx := tests.Context(t) l := logging.GetTestLogger(t) - loadedTestConfig, err := tc.GetConfig("Load", tc.Automation) + loadedTestConfig, err := tc.GetConfig([]string{"Load"}, tc.Automation) if err != nil { t.Fatal(err) } diff --git a/integration-tests/load/functions/functions_test.go b/integration-tests/load/functions/functions_test.go index 49102bcaa6..374b3df705 100644 --- a/integration-tests/load/functions/functions_test.go +++ b/integration-tests/load/functions/functions_test.go @@ -11,7 +11,7 @@ import ( ) func TestFunctionsLoad(t *testing.T) { - generalConfig, err := tc.GetConfig(tc.NoKey, tc.Functions) + generalConfig, err := tc.GetConfig([]string{""}, tc.Functions) require.NoError(t, err, "failed to get config") ft, err := SetupLocalLoadTestEnv(&generalConfig, &generalConfig) @@ -25,7 +25,7 @@ func TestFunctionsLoad(t *testing.T) { MonitorLoadStats(t, ft, labels, &generalConfig) t.Run("mumbai functions soak test http", func(t *testing.T) { - config, err := tc.GetConfig("Soak", tc.Functions) + config, err := tc.GetConfig([]string{"Soak"}, tc.Functions) require.NoError(t, err, "failed to get config") cfg := config.Functions cfgl := config.Logging.Loki @@ -59,7 +59,7 @@ func TestFunctionsLoad(t *testing.T) { }) t.Run("mumbai functions stress test http", func(t *testing.T) { - config, err := tc.GetConfig("Stress", tc.Functions) + config, err := tc.GetConfig([]string{"Stress"}, tc.Functions) require.NoError(t, err, "failed to get config") cfg := config.Functions cfgl := config.Logging.Loki @@ -93,7 +93,7 @@ func TestFunctionsLoad(t *testing.T) { }) t.Run("mumbai functions soak test only secrets", func(t *testing.T) { - config, err := tc.GetConfig("SecretsSoak", tc.Functions) + config, err := tc.GetConfig([]string{"SecretsSoak"}, tc.Functions) require.NoError(t, err, "failed to get config") cfg := config.Functions cfgl := config.Logging.Loki @@ -127,7 +127,7 @@ func TestFunctionsLoad(t *testing.T) { }) t.Run("mumbai functions stress test only secrets", func(t *testing.T) { - config, err := tc.GetConfig("SecretsStress", tc.Functions) + config, err := tc.GetConfig([]string{"SecretsStress"}, tc.Functions) require.NoError(t, err, "failed to get config") cfg := config.Functions cfgl := config.Logging.Loki @@ -161,7 +161,7 @@ func TestFunctionsLoad(t *testing.T) { }) t.Run("mumbai functions soak test real", func(t *testing.T) { - config, err := tc.GetConfig("RealSoak", tc.Functions) + config, err := tc.GetConfig([]string{"RealSoak"}, tc.Functions) require.NoError(t, err, "failed to get config") cfg := config.Functions cfgl := config.Logging.Loki @@ -195,7 +195,7 @@ func TestFunctionsLoad(t *testing.T) { }) t.Run("mumbai functions stress test real", func(t *testing.T) { - config, err := tc.GetConfig("RealStress", tc.Functions) + config, err := tc.GetConfig([]string{"RealStress"}, tc.Functions) require.NoError(t, err, "failed to get config") cfg := config.Functions cfgl := config.Logging.Loki diff --git a/integration-tests/load/functions/gateway_test.go b/integration-tests/load/functions/gateway_test.go index c2d5bd7c2c..dd1092a595 100644 --- a/integration-tests/load/functions/gateway_test.go +++ b/integration-tests/load/functions/gateway_test.go @@ -11,7 +11,7 @@ import ( ) func TestGatewayLoad(t *testing.T) { - listConfig, err := tc.GetConfig("GatewayList", tc.Functions) + listConfig, err := tc.GetConfig([]string{"GatewayList"}, tc.Functions) require.NoError(t, err) cfgl := listConfig.Logging.Loki @@ -42,7 +42,7 @@ func TestGatewayLoad(t *testing.T) { LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), } - setConfig, err := tc.GetConfig("GatewaySet", tc.Functions) + setConfig, err := tc.GetConfig([]string{"GatewaySet"}, tc.Functions) require.NoError(t, err) secretsSetCfg := &wasp.Config{ diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index fca1936781..8a00b043eb 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.1.7-0.20240625145034-72dab520f468 - github.com/smartcontractkit/chainlink-testing-framework v1.31.5 + github.com/smartcontractkit/chainlink-testing-framework v1.31.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-20240419185742-fd3cab206b2c diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 4eabc24cdd..085cae907d 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1515,8 +1515,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.31.5 h1:PemXseNS74zz1Oitm1MOCeJyQSIYCFck/QsnjM1y06c= -github.com/smartcontractkit/chainlink-testing-framework v1.31.5/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= +github.com/smartcontractkit/chainlink-testing-framework v1.31.7 h1:Vy4ah8VAfj+Y7vVmhjvwyAO6wG+Fp2vzdkSJwJPMQO4= +github.com/smartcontractkit/chainlink-testing-framework v1.31.7/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= 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-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/load/ocr/ocr_test.go b/integration-tests/load/ocr/ocr_test.go index 15f52acbff..db90f67b3c 100644 --- a/integration-tests/load/ocr/ocr_test.go +++ b/integration-tests/load/ocr/ocr_test.go @@ -25,7 +25,7 @@ var ( func TestOCRLoad(t *testing.T) { l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Load", tc.OCR) + config, err := tc.GetConfig([]string{"Load"}, tc.OCR) require.NoError(t, err) evmNetwork, msClient, bootstrapNode, workerNodes, err := k8s.ConnectRemote() @@ -61,7 +61,7 @@ func TestOCRLoad(t *testing.T) { func TestOCRVolume(t *testing.T) { l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Volume", tc.OCR) + config, err := tc.GetConfig([]string{"Volume"}, tc.OCR) require.NoError(t, err) evmNetwork, msClient, bootstrapNode, workerNodes, err := k8s.ConnectRemote() diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 5f7e184a48..0a014ccc44 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -46,7 +46,7 @@ func TestVRFV2Performance(t *testing.T) { l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) - testConfig, err := tc.GetConfig(testType, tc.VRFv2) + testConfig, err := tc.GetChainAndTestTypeSpecificConfig(testType, tc.VRFv2) require.NoError(t, err) cfgl := testConfig.Logging.Loki @@ -188,7 +188,7 @@ func TestVRFV2BHSPerformance(t *testing.T) { testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) - testConfig, err := tc.GetConfig(testType, tc.VRFv2) + testConfig, err := tc.GetChainAndTestTypeSpecificConfig(testType, tc.VRFv2) require.NoError(t, err) vrfv2Config := testConfig.VRFv2 testReporter := &testreporters.VRFV2TestReporter{} diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 3ff9a12996..3835dbfb61 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -45,7 +45,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) - testConfig, err := tc.GetConfig(testType, tc.VRFv2Plus) + testConfig, err := tc.GetChainAndTestTypeSpecificConfig(testType, tc.VRFv2Plus) require.NoError(t, err) cfgl := testConfig.Logging.Loki @@ -188,7 +188,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) - testConfig, err := tc.GetConfig(testType, tc.VRFv2Plus) + testConfig, err := tc.GetChainAndTestTypeSpecificConfig(testType, tc.VRFv2Plus) require.NoError(t, err) vrfv2PlusConfig := testConfig.VRFv2Plus testReporter := &testreporters.VRFV2PlusTestReporter{} diff --git a/integration-tests/load/zcluster/cluster_entrypoint_test.go b/integration-tests/load/zcluster/cluster_entrypoint_test.go index 35b3ee422c..aace97b082 100644 --- a/integration-tests/load/zcluster/cluster_entrypoint_test.go +++ b/integration-tests/load/zcluster/cluster_entrypoint_test.go @@ -10,7 +10,7 @@ import ( ) func TestClusterEntrypoint(t *testing.T) { - config, err := tc.GetConfig("Load", tc.OCR) + config, err := tc.GetConfig([]string{"Load"}, tc.OCR) require.NoError(t, err) cfgBase64, err := config.AsBase64() require.NoError(t, err) diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index 4c7b275e29..a17f00e179 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -17,7 +17,7 @@ func TestVersionUpgrade(t *testing.T) { l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Migration", tc.Node) + config, err := tc.GetConfig([]string{"Migration"}, tc.Node) require.NoError(t, err, "Error getting config") err = config.ChainlinkUpgradeImage.Validate() diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 958923327a..5a18bb17c9 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -84,7 +84,7 @@ var ( * Upkeeps are expected to be performed during the reorg. */ func TestAutomationReorg(t *testing.T) { - c, err := tc.GetConfig("Reorg", tc.Automation) + c, err := tc.GetConfig([]string{"Reorg"}, tc.Automation) require.NoError(t, err, "Error getting config") findIntValue := func(text string, substring string) (int, error) { @@ -126,7 +126,7 @@ func TestAutomationReorg(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - config, err := tc.GetConfig("Reorg", tc.Automation) + config, err := tc.GetConfig([]string{"Reorg"}, tc.Automation) if err != nil { t.Fatal(err) } diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 46abccae56..20240351c5 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -120,7 +120,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { t.Parallel() l := logging.GetTestLogger(t) - cfg, err := tc.GetConfig("Smoke", tc.Automation) + cfg, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") if nodeUpgrade { @@ -271,7 +271,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( @@ -453,7 +453,7 @@ func TestAutomationAddFunds(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( t, registryVersion, automationDefaultRegistryConfig(config), false, false, &config, @@ -530,7 +530,7 @@ func TestAutomationPauseUnPause(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( @@ -629,7 +629,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( @@ -723,7 +723,7 @@ func TestAutomationPauseRegistry(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( @@ -801,7 +801,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( @@ -907,7 +907,7 @@ func TestAutomationPerformSimulation(t *testing.T) { registryVersion := rv t.Run(name, func(t *testing.T) { t.Parallel() - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( @@ -979,7 +979,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( t, registryVersion, automationDefaultRegistryConfig(config), false, false, &config, @@ -1133,7 +1133,7 @@ func TestUpdateCheckData(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) require.NoError(t, err, "Failed to get config") a := setupAutomationTestDocker( @@ -1213,7 +1213,7 @@ func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Automation) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Automation) if err != nil { t.Fatal(err) } diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 6f864b2e49..98c1fe0caf 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -21,7 +21,7 @@ func TestCronBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Cron) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Cron) if err != nil { t.Fatal(err) } @@ -76,7 +76,7 @@ func TestCronJobReplacement(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Cron) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Cron) if err != nil { t.Fatal(err) } diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 05b75da223..d8773690b2 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -27,7 +27,7 @@ func TestFluxBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Flux) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Flux) require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 0377553191..a249775dc6 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -24,7 +24,7 @@ func TestForwarderOCRBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.ForwarderOcr) + config, err := tc.GetConfig([]string{"Smoke"}, tc.ForwarderOcr) require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index 3970a0b43b..863b36e4ed 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -25,7 +25,7 @@ func TestForwarderOCR2Basic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.ForwarderOcr2) + config, err := tc.GetConfig([]string{"Smoke"}, tc.ForwarderOcr2) require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 21e1aa6e08..4ff1c90bd1 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -89,7 +89,7 @@ func TestKeeperBasicSmoke(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -170,7 +170,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -314,7 +314,7 @@ func TestKeeperSimulation(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -393,7 +393,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -530,7 +530,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -626,7 +626,7 @@ func TestKeeperAddFunds(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -701,7 +701,7 @@ func TestKeeperRemove(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -786,7 +786,7 @@ func TestKeeperPauseRegistry(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -853,7 +853,7 @@ func TestKeeperPauseRegistry(t *testing.T) { func TestKeeperMigrateRegistry(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Error getting config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -956,7 +956,7 @@ func TestKeeperNodeDown(t *testing.T) { t.Run(fmt.Sprintf("registry_1_%d", registryVersion), func(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -1066,7 +1066,7 @@ type nodeAndJob struct { func TestKeeperPauseUnPauseUpkeep(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -1158,7 +1158,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { func TestKeeperUpdateCheckData(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) @@ -1264,7 +1264,7 @@ func TestKeeperJobReplacement(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) registryVersion := ethereum.RegistryVersion_1_3 - config, err := tc.GetConfig("Smoke", tc.Keeper) + config, err := tc.GetConfig([]string{"Smoke"}, tc.Keeper) require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index 05be29a90b..d02daec211 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -91,7 +91,7 @@ func TestLogPollerReplayFinalityTag(t *testing.T) { // HELPER FUNCTIONS func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.ChainlinkNodeLogScannerSettings) { - testConfig, err := tc.GetConfig(t.Name(), tc.LogPoller) + testConfig, err := tc.GetConfig([]string{t.Name()}, tc.LogPoller) require.NoError(t, err, "Error getting config") overrideEphemeralAddressesCount(&testConfig) @@ -174,7 +174,7 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli } func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { - testConfig, err := tc.GetConfig(t.Name(), tc.LogPoller) + testConfig, err := tc.GetConfig([]string{t.Name()}, tc.LogPoller) require.NoError(t, err, "Error getting config") overrideEphemeralAddressesCount(&testConfig) diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 09a9a22249..56a95c50bd 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -139,7 +139,7 @@ func TestOCRv2JobReplacement(t *testing.T) { } func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, firstRoundResult int) (*test_env.CLClusterTestEnv, []contracts.OffchainAggregatorV2, *seth.Client) { - config, err := tc.GetConfig("Smoke", tc.OCR2) + config, err := tc.GetConfig([]string{"Smoke"}, tc.OCR2) if err != nil { t.Fatal(err) } diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go index 5b263dc144..bf81e22b40 100644 --- a/integration-tests/smoke/ocr2vrf_test.go +++ b/integration-tests/smoke/ocr2vrf_test.go @@ -34,7 +34,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) { // remember to add TOML testConfig for Chainlink node before trying to run this test in future t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) - testConfig, err := testconfig.GetConfig("Smoke", testconfig.OCR2VRF) + testConfig, err := testconfig.GetConfig([]string{"Smoke"}, testconfig.OCR2VRF) require.NoError(t, err, "Error getting config") testEnvironment, testNetwork := setupOCR2VRFEnvironment(t) @@ -95,7 +95,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { t.Parallel() t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) - testConfig, err := testconfig.GetConfig("Smoke", testconfig.OCR2VRF) + testConfig, err := testconfig.GetConfig([]string{"Smoke"}, testconfig.OCR2VRF) require.NoError(t, err, "Error getting config") testEnvironment, testNetwork := setupOCR2VRFEnvironment(t) @@ -153,7 +153,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { func setupOCR2VRFEnvironment(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) { if ocr2vrfSmokeConfig == nil { - c, err := testconfig.GetConfig("Smoke", testconfig.OCR2VRF) + c, err := testconfig.GetConfig([]string{"Smoke"}, testconfig.OCR2VRF) require.NoError(t, err, "Error getting config") ocr2vrfSmokeConfig = &c } diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index d989517278..67f8c44f8a 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -80,7 +80,7 @@ func TestOCRJobReplacement(t *testing.T) { } func prepareORCv1SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult int64) (*test_env.CLClusterTestEnv, []contracts.OffchainAggregator, *seth.Client) { - config, err := tc.GetConfig("Smoke", tc.OCR) + config, err := tc.GetConfig([]string{"Smoke"}, tc.OCR) if err != nil { t.Fatal(err) } diff --git a/integration-tests/smoke/reorg_above_finality_test.go b/integration-tests/smoke/reorg_above_finality_test.go index 829aa66fdc..e7b9e4a218 100644 --- a/integration-tests/smoke/reorg_above_finality_test.go +++ b/integration-tests/smoke/reorg_above_finality_test.go @@ -19,7 +19,7 @@ func TestReorgAboveFinality_FinalityTagDisabled(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig(t.Name(), tc.LogPoller) + config, err := tc.GetConfig([]string{t.Name()}, tc.LogPoller) require.NoError(t, err, "Error getting config") privateNetworkConf, err := actions.EthereumNetworkConfigFromConfig(l, &config) diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 862ac911b3..515d9dea33 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -28,7 +28,7 @@ func TestRunLogBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.RunLog) + config, err := tc.GetConfig([]string{"Smoke"}, tc.RunLog) require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 0f706f1576..04e760796d 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -186,7 +186,7 @@ func TestVRFJobReplacement(t *testing.T) { } func prepareVRFtestEnv(t *testing.T, l zerolog.Logger) (*test_env.CLClusterTestEnv, *vrfv1.Contracts, *seth.Client) { - config, err := tc.GetConfig("Smoke", tc.VRF) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRF) require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 70fcb4bcf7..0cf04051e7 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -52,7 +52,7 @@ func TestVRFv2Basic(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") vrfv2Config := config.VRFv2 chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -569,7 +569,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) if err != nil { t.Fatal(err) } @@ -677,7 +677,7 @@ func TestVRFOwner(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID vrfv2Config := config.VRFv2 @@ -813,7 +813,7 @@ func TestVRFV2WithBHS(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") vrfv2Config := config.VRFv2 chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -1031,7 +1031,7 @@ func TestVRFV2NodeReorg(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") vrfv2Config := config.VRFv2 network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] @@ -1210,7 +1210,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2) require.NoError(t, err, "Error getting config") vrfv2Config := config.VRFv2 network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index b713cdf940..106b4f3c1c 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -49,8 +49,9 @@ func TestVRFv2Plus(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") + vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -746,7 +747,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -851,7 +852,7 @@ func TestVRFv2PlusMigration(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -1245,7 +1246,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -1474,7 +1475,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -1631,7 +1632,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -1800,7 +1801,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID @@ -1894,7 +1895,7 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] @@ -2071,7 +2072,7 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { ) l := logging.GetTestLogger(t) - config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + config, err := tc.GetChainAndTestTypeSpecificConfig("Smoke", tc.VRFv2Plus) require.NoError(t, err, "Error getting config") vrfv2PlusConfig := config.VRFv2Plus network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] diff --git a/integration-tests/soak/forwarder_ocr_test.go b/integration-tests/soak/forwarder_ocr_test.go index fa9752a9a9..dd7eb10217 100644 --- a/integration-tests/soak/forwarder_ocr_test.go +++ b/integration-tests/soak/forwarder_ocr_test.go @@ -15,7 +15,7 @@ import ( func TestForwarderOCRv1Soak(t *testing.T) { //nolint:revive t.Fatalf("This test is disabled because the implementation is broken") - config, err := tc.GetConfig("Soak", tc.ForwarderOcr) + config, err := tc.GetConfig([]string{"Soak"}, tc.ForwarderOcr) require.NoError(t, err, "Error getting config") executeForwarderOCRSoakTest(t, &config) @@ -24,7 +24,7 @@ func TestForwarderOCRv1Soak(t *testing.T) { func TestForwarderOCRv2Soak(t *testing.T) { //nolint:revive t.Fatalf("This test is disabled because the implementation is broken") - config, err := tc.GetConfig("Soak", tc.ForwarderOcr2) + config, err := tc.GetConfig([]string{"Soak"}, tc.ForwarderOcr2) require.NoError(t, err, "Error getting config") executeForwarderOCRSoakTest(t, &config) diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go index ab6051ee94..1f437e565e 100644 --- a/integration-tests/soak/ocr_test.go +++ b/integration-tests/soak/ocr_test.go @@ -25,7 +25,7 @@ import ( ) func TestOCRv1Soak(t *testing.T) { - config, err := tc.GetConfig("Soak", tc.OCR) + config, err := tc.GetConfig([]string{"Soak"}, tc.OCR) require.NoError(t, err, "Error getting config") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) require.NoError(t, err, "Error creating OCR soak test") @@ -33,7 +33,7 @@ func TestOCRv1Soak(t *testing.T) { } func TestOCRv2Soak(t *testing.T) { - config, err := tc.GetConfig("Soak", tc.OCR2) + config, err := tc.GetConfig([]string{"Soak"}, tc.OCR2) require.NoError(t, err, "Error getting config") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) @@ -42,7 +42,7 @@ func TestOCRv2Soak(t *testing.T) { } func TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled(t *testing.T) { - config, err := tc.GetConfig(t.Name(), tc.OCR) + config, err := tc.GetConfig([]string{t.Name()}, tc.OCR) require.NoError(t, err, "Error getting config") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) require.NoError(t, err, "Error creating OCR soak test") @@ -50,7 +50,7 @@ func TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled(t *testing.T) { } func TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled(t *testing.T) { - config, err := tc.GetConfig(t.Name(), tc.OCR) + config, err := tc.GetConfig([]string{t.Name()}, tc.OCR) require.NoError(t, err, "Error getting config") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) require.NoError(t, err, "Error creating OCR soak test") @@ -58,7 +58,7 @@ func TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled(t *testing.T) { } func TestOCRSoak_GasSpike(t *testing.T) { - config, err := tc.GetConfig(t.Name(), tc.OCR) + config, err := tc.GetConfig([]string{t.Name()}, tc.OCR) require.NoError(t, err, "Error getting config") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) require.NoError(t, err, "Error creating OCR soak test") @@ -67,7 +67,7 @@ func TestOCRSoak_GasSpike(t *testing.T) { // TestOCRSoak_ChangeBlockGasLimit changes next block gas limit and sets it to percentage of last gasUsed in previous block creating congestion func TestOCRSoak_ChangeBlockGasLimit(t *testing.T) { - config, err := tc.GetConfig(t.Name(), tc.OCR) + config, err := tc.GetConfig([]string{t.Name()}, tc.OCR) require.NoError(t, err, "Error getting config") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) require.NoError(t, err, "Error creating OCR soak test") @@ -76,7 +76,7 @@ func TestOCRSoak_ChangeBlockGasLimit(t *testing.T) { // TestOCRSoak_RPCDownForAllCLNodes simulates a network chaos by bringing down network to RPC node for all Chainlink Nodes func TestOCRSoak_RPCDownForAllCLNodes(t *testing.T) { - config, err := tc.GetConfig(t.Name(), tc.OCR) + config, err := tc.GetConfig([]string{t.Name()}, tc.OCR) require.NoError(t, err, "Error getting config") require.True(t, config.Network.IsSimulatedGethSelected(), "This test requires simulated geth") @@ -108,7 +108,7 @@ func TestOCRSoak_RPCDownForAllCLNodes(t *testing.T) { // TestOCRSoak_RPCDownForAllCLNodes simulates a network chaos by bringing down network to RPC node for 50% of Chainlink Nodes func TestOCRSoak_RPCDownForHalfCLNodes(t *testing.T) { - config, err := tc.GetConfig(t.Name(), tc.OCR) + config, err := tc.GetConfig([]string{t.Name()}, tc.OCR) require.NoError(t, err, "Error getting config") require.True(t, config.Network.IsSimulatedGethSelected(), "This test requires simulated geth") diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 939645306b..95cb368a2a 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -84,7 +84,7 @@ type TestConfig struct { VRFv2 *vrfv2_config.Config `toml:"VRFv2"` VRFv2Plus *vrfv2plus_config.Config `toml:"VRFv2Plus"` - ConfigurationName string `toml:"-"` + ConfigurationNames []string `toml:"-"` } var embeddedConfigs embed.FS @@ -196,8 +196,8 @@ func (c TestConfig) GetOCRConfig() *ocr_config.Config { return c.OCR } -func (c TestConfig) GetConfigurationName() string { - return c.ConfigurationName +func (c TestConfig) GetConfigurationNames() []string { + return c.ConfigurationNames } func (c TestConfig) GetSethConfig() *seth.Config { @@ -271,15 +271,23 @@ func GetConfigurationNameFromEnv() (string, error) { const ( Base64OverrideEnvVarName = k8s_config.EnvBase64ConfigOverride - NoKey = "NO_KEY" ) -func GetConfig(configurationName string, product Product) (TestConfig, error) { +func GetConfig(configurationNames []string, product Product) (TestConfig, error) { logger := logging.GetTestLogger(nil) - configurationName = strings.ReplaceAll(configurationName, "/", "_") - configurationName = strings.ReplaceAll(configurationName, " ", "_") - configurationName = cases.Title(language.English, cases.NoLower).String(configurationName) + for idx, configurationName := range configurationNames { + configurationNames[idx] = strings.ReplaceAll(configurationName, "/", "_") + configurationNames[idx] = strings.ReplaceAll(configurationName, " ", "_") + configurationNames[idx] = cases.Title(language.English, cases.NoLower).String(configurationName) + } + + // add unnamed (default) configuration as the first one to be read + configurationNamesCopy := make([]string, len(configurationNames)) + copy(configurationNamesCopy, configurationNames) + + configurationNames = append([]string{""}, configurationNamesCopy...) + fileNames := []string{ "default.toml", fmt.Sprintf("%s.toml", product), @@ -287,8 +295,9 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { } testConfig := TestConfig{} - testConfig.ConfigurationName = configurationName - logger.Debug().Msgf("Will apply configuration named '%s' if it is found in any of the configs", configurationName) + testConfig.ConfigurationNames = configurationNames + + logger.Debug().Msgf("Will apply configurations named '%s' if they are found in any of the configs", strings.Join(configurationNames, ",")) // read embedded configs is build tag "embed" is set // this makes our life much easier when using a binary @@ -304,9 +313,11 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { return TestConfig{}, errors.Wrapf(err, "error reading embedded config") } - err = ctf_config.BytesToAnyTomlStruct(logger, fileName, configurationName, &testConfig, file) - if err != nil { - return TestConfig{}, errors.Wrapf(err, "error unmarshalling embedded config") + for _, configurationName := range configurationNames { + err = ctf_config.BytesToAnyTomlStruct(logger, fileName, configurationName, &testConfig, file) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error unmarshalling embedded config %s", embeddedFiles) + } } } } else { @@ -328,9 +339,11 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) } - err = ctf_config.BytesToAnyTomlStruct(logger, fileName, configurationName, &testConfig, content) - if err != nil { - return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) + for _, configurationName := range configurationNames { + err = ctf_config.BytesToAnyTomlStruct(logger, fileName, configurationName, &testConfig, content) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) + } } } } @@ -344,9 +357,11 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { return TestConfig{}, err } - err = ctf_config.BytesToAnyTomlStruct(logger, Base64OverrideEnvVarName, configurationName, &testConfig, decoded) - if err != nil { - return TestConfig{}, errors.Wrapf(err, "error unmarshaling base64 config") + for _, configurationName := range configurationNames { + err = ctf_config.BytesToAnyTomlStruct(logger, Base64OverrideEnvVarName, configurationName, &testConfig, decoded) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error unmarshaling base64 config") + } } } else { logger.Debug().Msg("Base64 config override from environment variable not found") diff --git a/integration-tests/testconfig/testconfig_test.go b/integration-tests/testconfig/testconfig_test.go index fd5230dac2..91d2524fcf 100644 --- a/integration-tests/testconfig/testconfig_test.go +++ b/integration-tests/testconfig/testconfig_test.go @@ -76,7 +76,7 @@ func TestBase64ConfigRead(t *testing.T) { testConfigEncoded := base64.StdEncoding.EncodeToString(configMarshalled) os.Setenv(Base64OverrideEnvVarName, testConfigEncoded) - readConfig, err := GetConfig("test", Automation) + readConfig, err := GetConfig([]string{"test"}, Automation) require.NoError(t, err, "Error reading config") require.NotNil(t, readConfig.Automation, "Automation config read from base64 is nil") diff --git a/integration-tests/testconfig/testconfig_utils.go b/integration-tests/testconfig/testconfig_utils.go index d4290689bc..6529771f49 100644 --- a/integration-tests/testconfig/testconfig_utils.go +++ b/integration-tests/testconfig/testconfig_utils.go @@ -68,3 +68,22 @@ selected_networks=` return fmt.Errorf(finalErrStr) } + +func GetChainAndTestTypeSpecificConfig(testType string, product Product) (TestConfig, error) { + config, err := GetConfig([]string{testType}, product) + if err != nil { + return TestConfig{}, fmt.Errorf("error getting config: %w", err) + } + config, err = GetConfig( + []string{ + testType, + config.GetNetworkConfig().SelectedNetworks[0], + fmt.Sprintf("%s-%s", config.GetNetworkConfig().SelectedNetworks[0], testType), + }, + product, + ) + if err != nil { + return TestConfig{}, fmt.Errorf("error getting config: %w", err) + } + return config, err +} diff --git a/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml index 717a62e997..1d2af76084 100644 --- a/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml +++ b/integration-tests/testconfig/vrfv2plus/vrfv2plus.toml @@ -143,14 +143,6 @@ bhs_test_duration = "10s" bhs_test_rate_limit_unit_duration = "3s" bhs_test_rps = 1 -[Smoke.VRFv2.Performance] -test_duration = "10s" -rate_limit_unit_duration = "3s" -rps = 1 -bhs_test_duration = "10s" -bhs_test_rate_limit_unit_duration = "3s" -bhs_test_rps = 1 - #SOAK TEST CONFIG [Soak.Common] chainlink_node_funding = 0.1 @@ -211,3 +203,650 @@ bhs_test_duration = "1m" bhs_test_rate_limit_unit_duration = "3s" bhs_test_rps = 1 +### POLYGON AMOY Config + +[POLYGON_AMOY.VRFv2Plus.General] +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 3 + +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" +callback_gas_limit = 1000000 + +# NEW ENV CONFIG +# CL Node config +cl_node_max_gas_price_gwei = 200 +number_of_sending_keys_to_create = 0 + +# Coordinator config +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "19823132181656390000" +staleness_seconds = 172_800 +gas_after_payment_calculation = 48_500 +fulfillment_flat_fee_native_ppm = 0 +fulfillment_flat_fee_link_discount_ppm = 0 +native_premium_percentage = 84 +link_premium_percentage = 70 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 99_500 +coordinator_gas_overhead_link = 121_500 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage = 84 +coordinator_link_premium_percentage = 70 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 3.0 +vrf_job_batch_fulfillment_enabled = true +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "2s" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block = "latest" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "2s" +bhs_job_run_timeout = "30s" +# NEW ENV CONFIG END + +[POLYGON_AMOY.VRFv2Plus.ExistingEnv] +coordinator_address = "0x7541EbaE23f32B4A1A2e7a8Cbf9da9582767A9B4" +consumer_address = "" +sub_id = "" +key_hash = "0xd360445bacd26df47086ccf255c4f932d297ed8d5c7334b51eed32f61c541601" +#key_hash = "0x2328cbee29e32d0b6662d6df82ff0fea7be300bd310561c92f515c9ee19464f1" +#key_hash = "0x25f4e2d0509f42ec77db5380f3433a89fe623fa75f65d5b398d5f498327be4dd" +create_fund_subs_and_add_consumers = true +link_address = "0x0Fd9e8d3aF1aaee056EB9e802c3A762a667b1904" +node_sending_key_funding_min = 10 +node_sending_keys = [ + "0xD96013C241f1741C35a135321969f92Aae02A12F", + "0x0580E61a5523F5CAAC4968E4f8FE63b59596BdD7", + "0xd15FcEa6a6AA17085930Fbd5647A9F7fD2Ff58b8", + "0xB7277cBb6E7028AE65235b8ee9201AcBb14B11d4", + "0x6D36a1dC1eEd25C75961E989c4d01Cd4453bE465", + "0xd299Cd7C0073b71e620bf8A3bfD50F75c0b49af8", + "0x48BE7BAED0b65776D85DF971fA901c637cFC5e87", + # BHS + "0x638372de870eF0F8E675A3f67F18D5bd4A2fd804", + "0xF9eF03816411D037202d5ed4457dC1613e3bd729", + "0xCD66973f8fbaE787211EC20228c6bd90D83562A8", + "0x242ea1F4Bb72EF643B2D8EF22e18a89f00742F40", + "0xaA09B4F9B5710b239fdbf1D0f535dd7f86F91219", + "0xe6b72B647B8B45C5562F7a5259E187889C747d3b", + "0x2c1185C4d3B0B4a577d4079Ee193A4e293164D9d" +] + +#SMOKE TEST CONFIG +[POLYGON_AMOY-Smoke.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 5 +subscription_refunding_amount_native = 1 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "15m" + +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 5 + + +[POLYGON_AMOY-Smoke.VRFv2Plus.Performance] +test_duration = "2s" +rate_limit_unit_duration = "15s" +rps = 1 + + +#SOAK TEST CONFIG +[POLYGON_AMOY-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 200 + +[POLYGON_AMOY-Soak.VRFv2Plus.Performance] +test_duration = "5h" +rate_limit_unit_duration = "3s" +rps = 1 + +# LOAD TEST CONFIG +[POLYGON_AMOY-Load.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 300 +subscription_funding_amount_native = 300 + +[POLYGON_AMOY-Load.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + + +# STRESS TEST CONFIG +[POLYGON_AMOY-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5.0 +subscription_funding_amount_native = 0.1 + +[POLYGON_AMOY-Stress.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + +### ARBITRUM SEPOLIA Config + +[ARBITRUM_SEPOLIA.VRFv2Plus.General] +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 0 +subscription_billing_type = "LINK_AND_NATIVE" + +cl_node_max_gas_price_gwei = 50 +number_of_sending_keys_to_create = 0 + +# Coordinator config +callback_gas_limit = 1000000 +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "5352799651145251" +staleness_seconds = 172_800 +gas_after_payment_calculation = 56000 +fulfillment_flat_fee_native_ppm=0 +fulfillment_flat_fee_link_discount_ppm=0 +native_premium_percentage=60 +link_premium_percentage=50 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 104_500 +coordinator_gas_overhead_link = 126_500 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage=60 +coordinator_link_premium_percentage=50 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 3.0 +vrf_job_batch_fulfillment_enabled = true +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "300ms" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block="pending" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "300ms" +bhs_job_run_timeout = "30s" +# NEW ENV CONFIG END + +[ARBITRUM_SEPOLIA.VRFv2Plus.ExistingEnv] +coordinator_address = "0xF7ba1Cf141F9729abC43c146dc2bf86EbcfD8603" +consumer_address = "" +sub_id = "" +key_hash = "0xe13aa26fe94bfcd2ae055911f4d3bf1aed54ca6cf77af34e17f918802fd69ba1" +create_fund_subs_and_add_consumers = true +link_address = "0xb1D4538B4571d411F07960EF2838Ce337FE1E80E" +node_sending_key_funding_min = 20 +node_sending_keys = [ + "0xbE21ae371FcA1aC2d8A152e707D21e68d7d99252", + "0xb13e9BA0aE94FD3b89B13b092e6d41614c805134", + "0x27aa703e585Ee165B7c977EAA652eCFa13b08294", + "0x9324643ACD2ec5b0813488E5EdAb64C3758ae4Ee", + "0x7CBA8c8e86f23f23363051650Fe5AE4DE78c3652", + "0x9A0143a4BAB55A826331A8ef82462557633aA016", + "0xD4259633F8e87949F683433a17e1fFcCE27865AC", + "0x5e47B71d6F95f68cd5538907ec6A9635b1Fe30Fa", + "0xa850a1a257FDF439c8f854ce3b89dd5b6F411827", + "0x7c82D56087c10aF2c3970f9a9Be7786B2850ce91", + "0x9545CB59956347d3debf27f5029754bBE1d398FA", + "0xEb8C69ac19709f27A97FB4A561f51AD2F9b34c5B", + # BHS + "0xf0e8cF7Fbd28Fc4D412B76B744CDA269df671F8e", + "0x317A02A658d12E5Bb4A6270171E7385928dD2d53", + "0x480f1dbcEc118Bd91e4dbb7e45bFa4A73180d21f", + "0x500a2662FaF981EC4669f791349D37Cbf1bE7d85", + "0x2ad350374B904c10B47c64ECdBD9e70BB0833Be2", + "0x0b946F0bF4e63C12b5157137f1c130f0788bC1b1", + # BHF + "0x571BBF4a5b07fc3F47Bd3B65CE2FE73739f86623" +] + +#SMOKE TEST CONFIG +[ARBITRUM_SEPOLIA-Smoke.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 20 +subscription_refunding_amount_native = 10 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "100s" + +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 5 + +[ARBITRUM_SEPOLIA-Smoke.VRFv2Plus.Performance] +test_duration = "1s" +rate_limit_unit_duration = "10s" +rps = 1 + + +#SOAK TEST CONFIG +[ARBITRUM_SEPOLIA-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 4 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 300 +subscription_funding_amount_native = 100 + +[ARBITRUM_SEPOLIA-Soak.VRFv2Plus.Performance] +test_duration = "1h" +rate_limit_unit_duration = "10s" +rps = 1 + +# LOAD TEST CONFIG +[ARBITRUM_SEPOLIA-Load.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 100 +subscription_funding_amount_native = 60 + +[ARBITRUM_SEPOLIA-Load.VRFv2Plus.Performance] +test_duration = "30m" +rate_limit_unit_duration = "3s" +rps = 1 + + +# STRESS TEST CONFIG +[ARBITRUM_SEPOLIA-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5.0 +subscription_funding_amount_native = 0.1 + +[ARBITRUM_SEPOLIA-Stress.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + + +### AVALANCHE FUJI Config +[AVALANCHE_FUJI.VRFv2Plus.General] +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 0 + +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" +callback_gas_limit = 1000000 + +# NEW ENV CONFIG +# CL Node config +cl_node_max_gas_price_gwei = 300 +number_of_sending_keys_to_create = 0 + +# Coordinator config +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "378709808510249900" +staleness_seconds = 172_800 +gas_after_payment_calculation = 56_000 +fulfillment_flat_fee_native_ppm = 0 +fulfillment_flat_fee_link_discount_ppm = 0 +native_premium_percentage = 60 +link_premium_percentage = 50 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 107_000 +coordinator_gas_overhead_link = 129_000 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage = 60 +coordinator_link_premium_percentage = 50 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 3.0 +vrf_job_batch_fulfillment_enabled = true +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "2s" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block = "pending" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "2s" +bhs_job_run_timeout = "30s" +# NEW ENV CONFIG END + +[AVALANCHE_FUJI.VRFv2Plus.ExistingEnv] +coordinator_address = "0xE122bf3Badd6545bDec5D4627a6DAd16352A1b36" +consumer_address = "" +sub_id = "" +key_hash = "0x5b03254a80ea3eb72139ff0423cb88be42612780c3dd25f1d95a5ba7708a4be1" +create_fund_subs_and_add_consumers = true +link_address = "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846" +node_sending_key_funding_min = 50 +node_sending_keys = [ + "0x3D7Da5D6A23CA2240CE576C8638C1798a023920a", + # BHS + "0x72c8565279430F5179b0090d51ab8BB53Da323B5" +] + +#SMOKE TEST CONFIG +[AVALANCHE_FUJI-Smoke.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 20 +subscription_funding_amount_native = 20 +subscription_refunding_amount_link = 20 +subscription_refunding_amount_native = 20 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "10m" + +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 5 + +[AVALANCHE_FUJI-Smoke.VRFv2Plus.Performance] +test_duration = "2s" +rate_limit_unit_duration = "10s" +rps = 1 + + +#SOAK TEST CONFIG +[AVALANCHE_FUJI-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 400 +subscription_funding_amount_native = 200 + +[AVALANCHE_FUJI-Soak.VRFv2Plus.Performance] +test_duration = "5h" +rate_limit_unit_duration = "3s" +rps = 1 + +# LOAD TEST CONFIG +[AVALANCHE_FUJI-Load.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 300 +subscription_funding_amount_native = 300 + +[AVALANCHE_FUJI-Load.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + + +# STRESS TEST CONFIG +[AVALANCHE_FUJI-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5.0 +subscription_funding_amount_native = 0.1 + +[AVALANCHE_FUJI-Stress.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + +### ETH SEPOLIA Config +[SEPOLIA.VRFv2Plus.General] +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 3 + +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" +callback_gas_limit = 1000000 + +# NEW ENV CONFIG +# CL Node config +cl_node_max_gas_price_gwei = 100 +number_of_sending_keys_to_create = 0 + +# Coordinator config +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "5354747932930759" +staleness_seconds = 172_800 +gas_after_payment_calculation = 38_900 +fulfillment_flat_fee_native_ppm = 0 +fulfillment_flat_fee_link_discount_ppm = 0 +native_premium_percentage = 24 +link_premium_percentage = 20 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 90_000 +coordinator_gas_overhead_link = 112_000 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage = 24 +coordinator_link_premium_percentage = 20 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 1.15 +vrf_job_batch_fulfillment_enabled = false +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "5s" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block = "latest" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "30s" +bhs_job_run_timeout = "1m0s" +# NEW ENV CONFIG END + +[SEPOLIA.VRFv2Plus.ExistingEnv] +coordinator_address = "0x2F3b892710523Ee9A85c3155a42089fFe99Ca31e" +consumer_address = "" +sub_id = "" +key_hash = "0xf5b4a359df0598eef89872ea2170f2afa844dbf74b417e6d44d4bda9420aceb2" +create_fund_subs_and_add_consumers = true +link_address = "0x779877A7B0D9E8603169DdbD7836e478b4624789" +node_sending_key_funding_min = 50 +node_sending_keys = [ + "0x0c0DC7f33A1256f0247c5ea75861d385fa5FED31", + # BHS + "0xEd8A4b792d16484f6c9B4df1e721e8280925Db80", +] + +#SMOKE TEST CONFIG +[SEPOLIA-Smoke.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5 +subscription_funding_amount_native = 1 +subscription_refunding_amount_link = 5 +subscription_refunding_amount_native = 1 +number_of_words = 1 +random_words_fulfilled_event_timeout = "1m30s" +wait_for_256_blocks_timeout = "70m" + +wrapper_consumer_funding_amount_native_token = 1.0 +wrapper_consumer_funding_amount_link = 5 + +[SEPOLIA-Smoke.VRFv2Plus.Performance] +test_duration = "2s" +rate_limit_unit_duration = "3s" +rps = 1 + +#SOAK TEST CONFIG +[SEPOLIA-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 500 +subscription_funding_amount_native = 200 + +[SEPOLIA-Soak.VRFv2Plus.Performance] +test_duration = "2h" +rate_limit_unit_duration = "3s" +rps = 1 + +# LOAD TEST CONFIG +[SEPOLIA-Load.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5.0 +subscription_funding_amount_native = 30 + +[SEPOLIA-Load.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + +# STRESS TEST CONFIG +[SEPOLIA-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5.0 +subscription_funding_amount_native = 0.1 + +[SEPOLIA-Stress.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + +### BSC SEPOLIA Config +[BSC_TESTNET.VRFv2Plus.General] +use_existing_env = true +#todo - need to have separate minimum_confirmations config for Coordinator, CL Node and Consumer request +minimum_confirmations = 3 + +# Consumer Request config +subscription_billing_type = "LINK_AND_NATIVE" +callback_gas_limit = 1000000 + +# NEW ENV CONFIG +# CL Node config +cl_node_max_gas_price_gwei = 50 +number_of_sending_keys_to_create = 0 + +# Coordinator config +max_gas_limit_coordinator_config = 2500000 +fallback_wei_per_unit_link = "30531029880396850" +staleness_seconds = 172_800 +gas_after_payment_calculation = 48_500 +fulfillment_flat_fee_native_ppm = 0 +fulfillment_flat_fee_link_discount_ppm = 0 +native_premium_percentage = 60 +link_premium_percentage = 50 + +# Wrapper config +wrapped_gas_overhead = 13_400 +coordinator_gas_overhead_native = 99_500 +coordinator_gas_overhead_link = 121_500 +coordinator_gas_overhead_per_word = 435 +coordinator_native_premium_percentage = 60 +coordinator_link_premium_percentage = 50 +wrapper_max_number_of_words = 10 + +# VRF Job config +vrf_job_forwarding_allowed = false +vrf_job_estimate_gas_multiplier = 1.1 +vrf_job_batch_fulfillment_enabled = true +vrf_job_batch_fulfillment_gas_multiplier = 1.1 +vrf_job_poll_period = "3s" +vrf_job_request_timeout = "2h0m0s" +vrf_job_simulation_block = "latest" + +# BHS Job config +bhs_job_wait_blocks = 30 +bhs_job_lookback_blocks = 200 +bhs_job_poll_period = "2s" +bhs_job_run_timeout = "30s" +# NEW ENV CONFIG END + +[BSC_TESTNET.VRFv2Plus.ExistingEnv] +coordinator_address = "0x84A477F6ebF33501eE3ACA86fEcB980b1fC99AC2" +consumer_address = "" +sub_id = "" +key_hash = "0x4d43763d3eff849a89cf578a42787baa32132d7a80032125710e95b3972cd214" +create_fund_subs_and_add_consumers = true +link_address = "0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06" +node_sending_key_funding_min = 150 +node_sending_keys = [ + "0x4EE2Cc6D50E8acb6BaEf673B03559525a6c92fB8", + # BHS + "0xAFB44568f7DAc218EA6e1C71c366692ED4758A07" +] + +#SMOKE TEST CONFIG +[BSC_TESTNET-Smoke.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 10 +subscription_funding_amount_native = 10 + +[BSC_TESTNET-Smoke.VRFv2Plus.Performance] +test_duration = "15s" +rate_limit_unit_duration = "3s" +rps = 1 + + +#SOAK TEST CONFIG +[BSC_TESTNET-Soak.VRFv2Plus.General] +randomness_request_count_per_request = 1 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 0 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 400 +subscription_funding_amount_native = 200 + +[BSC_TESTNET-Soak.VRFv2Plus.Performance] +test_duration = "5h" +rate_limit_unit_duration = "3s" +rps = 1 + +# LOAD TEST CONFIG +[BSC_TESTNET-Load.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 300 +subscription_funding_amount_native = 300 + +[BSC_TESTNET-Load.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 + + +# STRESS TEST CONFIG +[BSC_TESTNET-Stress.VRFv2Plus.General] +randomness_request_count_per_request = 3 # amount of randomness requests to make per one TX request +randomness_request_count_per_request_deviation = 2 #NOTE - deviation should be less than randomness_request_count_per_request setting +number_of_sub_to_create = 1 +subscription_funding_amount_link = 5.0 +subscription_funding_amount_native = 0.1 + +[BSC_TESTNET-Stress.VRFv2Plus.Performance] +test_duration = "2m" +rate_limit_unit_duration = "3s" +rps = 1 diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 749ca3beac..45c334bf69 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -372,7 +372,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { // Run starts the OCR soak test func (o *OCRSoakTest) Run() { - config, err := tc.GetConfig("soak", tc.OCR) + config, err := tc.GetConfig([]string{"soak"}, tc.OCR) require.NoError(o.t, err, "Error getting config") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) diff --git a/integration-tests/types/testconfigs.go b/integration-tests/types/testconfigs.go index 58eb1a7c8c..ee8a614bae 100644 --- a/integration-tests/types/testconfigs.go +++ b/integration-tests/types/testconfigs.go @@ -35,7 +35,7 @@ type KeeperBenchmarkTestConfig interface { ctf_config.GlobalTestConfig tc.CommonTestConfig tc.KeeperTestConfig - ctf_config.NamedConfiguration + ctf_config.NamedConfigurations testreporters.GrafanaURLProvider } From 6a57f900bb8c2894b5e5f511601f1c4da5665de5 Mon Sep 17 00:00:00 2001 From: Cedric Date: Fri, 28 Jun 2024 11:19:04 +0100 Subject: [PATCH 23/61] Bump common; update mapstructure to incorporate perf improvements (#13717) --- core/capabilities/streams/trigger_test.go | 4 ++-- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- go.mod | 6 +++++- go.sum | 10 ++++------ 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, 20 insertions(+), 18 deletions(-) diff --git a/core/capabilities/streams/trigger_test.go b/core/capabilities/streams/trigger_test.go index 8f9450d2c9..6d8c9a27c1 100644 --- a/core/capabilities/streams/trigger_test.go +++ b/core/capabilities/streams/trigger_test.go @@ -191,12 +191,12 @@ func newTriggerEvent(t *testing.T, reportList []datastreams.FeedReport, triggerE Payload: val, } - eventVal, err := values.Wrap(triggerEvent) + eventVal, err := values.WrapMap(triggerEvent) require.NoError(t, err) marshaled, err := pb.MarshalCapabilityResponse( capabilities.CapabilityResponse{ - Value: eventVal.(*values.Map), + Value: eventVal, }) require.NoError(t, err) msg := &remotetypes.MessageBody{ diff --git a/core/scripts/go.mod b/core/scripts/go.mod index f0edb3503c..3c9c1dd179 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index e2002fcf8b..b80f1e26c8 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1212,8 +1212,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.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/go.mod b/go.mod index 0086ef3ec0..bc64ddace8 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 @@ -346,6 +346,10 @@ replace ( // until merged upstream: https://github.com/hashicorp/go-plugin/pull/257 github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 + // until nolag updates merged upstream + github.com/mitchellh/mapstructure => github.com/nolag/mapstructure v1.5.2-0.20240625151721-90ea83a3f479 + // 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 + ) diff --git a/go.sum b/go.sum index 7ab9fe024e..0df004af98 100644 --- a/go.sum +++ b/go.sum @@ -965,10 +965,6 @@ github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJ github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -1001,6 +997,8 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 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/nolag/mapstructure v1.5.2-0.20240625151721-90ea83a3f479 h1:1jCGDLFXDOHF2sdeTJYKrIuSLGMpQZpgXXHNGXR5Ouk= +github.com/nolag/mapstructure v1.5.2-0.20240625151721-90ea83a3f479/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1171,8 +1169,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.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 5e575a5483..ff6be98785 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -28,7 +28,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index d21adca4c1..9e81378cb5 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1513,8 +1513,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.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 8a00b043eb..28b22d4302 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.1.7-0.20240625145034-72dab520f468 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 085cae907d..ea1ff559c2 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1503,8 +1503,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.1.7-0.20240625145034-72dab520f468 h1:rhsUMdSrCerrUzzsOWaHkcb+qlB7knEAXYv/P29YUn8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240625145034-72dab520f468/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From 336e4191a227b1e344c43267f63e985fba5f0d01 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Fri, 28 Jun 2024 08:04:36 -0600 Subject: [PATCH 24/61] bump: solana with logging fix (#13710) --- 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 3c9c1dd179..3adf218399 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -277,7 +277,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index b80f1e26c8..d15cf62a75 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1220,8 +1220,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= diff --git a/go.mod b/go.mod index bc64ddace8..5f2a2c175d 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/go.sum b/go.sum index 0df004af98..da0951445f 100644 --- a/go.sum +++ b/go.sum @@ -1177,8 +1177,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index ff6be98785..96c004d492 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -381,7 +381,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 9e81378cb5..d76b199515 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1521,8 +1521,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-testing-framework v1.31.7 h1:Vy4ah8VAfj+Y7vVmhjvwyAO6wG+Fp2vzdkSJwJPMQO4= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 28b22d4302..9437ca3c98 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -367,7 +367,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index ea1ff559c2..3ad51a7ec0 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1511,8 +1511,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9 h1:YudTCEe/2xWdfPY/ESSiPFW4MVsrAoi2MWPwRUJ6QAA= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240625135745-60e0e43656f9/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-testing-framework v1.31.7 h1:Vy4ah8VAfj+Y7vVmhjvwyAO6wG+Fp2vzdkSJwJPMQO4= From 8ba250416b5b603f0c8c9ebb56e37b0ed305af0e Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 28 Jun 2024 16:59:20 +0200 Subject: [PATCH 25/61] Fix log poller test early exit (#13719) * WIP#1 - doesn't hang on error * WIP#3 - better early exit * use concurrent executor in log poller tests --- .../universal/log_poller/helpers.go | 199 ++++++------------ 1 file changed, 68 insertions(+), 131 deletions(-) diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 7bedef393d..ee4060f7ab 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -13,8 +13,6 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -28,9 +26,11 @@ import ( "github.com/smartcontractkit/wasp" "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/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -204,11 +204,6 @@ func randomWait(minMilliseconds, maxMilliseconds int) { time.Sleep(time.Duration(randomMilliseconds) * time.Millisecond) } -type LogEmitterChannel struct { - logsEmitted int - err error -} - // getIntSlice returns a slice of ints of the provided length func getIntSlice(length int) []int { result := make([]int, length) @@ -229,95 +224,6 @@ func getStringSlice(length int) []string { return result } -// emitEvents emits events from the provided log emitter concurrently according to the provided config -func emitEvents(ctx context.Context, l zerolog.Logger, client *seth.Client, logEmitter *contracts.LogEmitter, cfg *lp_config.Config, wg *sync.WaitGroup, results chan LogEmitterChannel) { - address := (*logEmitter).Address().String() - defer wg.Done() - - var executionGroup sync.WaitGroup - - // Atomic counter is used to keep track of the number of logs emitted - var atomicCounter = atomic.Int32{} - - for i := 0; i < *cfg.LoopedConfig.ExecutionCount; i++ { - executionGroup.Add(1) - } - - var emitAllEvents = func() { - defer executionGroup.Done() - current := atomicCounter.Add(1) - - for _, event := range cfg.General.EventsToEmit { - select { - case <-ctx.Done(): - l.Warn().Str("Emitter address", address).Msg("Context cancelled, not emitting events") - return - default: - l.Debug().Str("Emitter address", address).Str("Event type", event.Name).Str("index", fmt.Sprintf("%d/%d", current, *cfg.LoopedConfig.ExecutionCount)).Msg("Emitting log from emitter") - var err error - switch event.Name { - case "Log1": - _, err = client.Decode((*logEmitter).EmitLogIntsFromKey(getIntSlice(*cfg.General.EventsPerTx), client.AnySyncedKey())) - case "Log2": - _, err = client.Decode((*logEmitter).EmitLogIntsIndexedFromKey(getIntSlice(*cfg.General.EventsPerTx), client.AnySyncedKey())) - case "Log3": - _, err = client.Decode((*logEmitter).EmitLogStringsFromKey(getStringSlice(*cfg.General.EventsPerTx), client.AnySyncedKey())) - case "Log4": - _, err = client.Decode((*logEmitter).EmitLogIntMultiIndexedFromKey(1, 1, *cfg.General.EventsPerTx, client.AnySyncedKey())) - default: - err = fmt.Errorf("unknown event name: %s", event.Name) - } - - if err != nil { - results <- LogEmitterChannel{ - err: err, - } - return - } - randomWait(*cfg.LoopedConfig.MinEmitWaitTimeMs, *cfg.LoopedConfig.MaxEmitWaitTimeMs) - } - - if (current)%10 == 0 { - l.Info().Str("Emitter address", address).Str("Index", fmt.Sprintf("%d/%d", current, *cfg.LoopedConfig.ExecutionCount)).Msgf("Emitted all %d events", len(cfg.General.EventsToEmit)) - } - } - } - - clientNumber := int(*client.Cfg.EphemeralAddrs) - emissionsPerClient := *cfg.LoopedConfig.ExecutionCount / clientNumber - extraEmissions := *cfg.LoopedConfig.ExecutionCount % clientNumber - - l.Debug().Str("Emitter address", address). - Int("Total logs to emit", *cfg.LoopedConfig.ExecutionCount*len(cfg.General.EventsToEmit)*(*cfg.General.EventsPerTx)). - Int("Total clients", clientNumber). - Int("Emissions per client", emissionsPerClient). - Int("Extra emissions", extraEmissions). - Msg("Starting to emit events") - - for i := 0; i < clientNumber; i++ { - go func(key int) { - numTasks := emissionsPerClient - if key < extraEmissions { - numTasks++ - } - - for idx := 0; idx < numTasks; idx++ { - emitAllEvents() - } - }(i) - } - - executionGroup.Wait() - - localCounter := int(atomicCounter.Load()) * *cfg.General.EventsPerTx * len(cfg.General.EventsToEmit) - l.Info().Str("Emitter address", address).Int("Total logs emitted", localCounter).Msg("Finished emitting events") - - results <- LogEmitterChannel{ - logsEmitted: localCounter, - err: nil, - } -} - // LogPollerHasFinalisedEndBlock returns true if all CL nodes have finalised processing the provided end block func LogPollerHasFinalisedEndBlock(endBlock int64, chainID *big.Int, l zerolog.Logger, coreLogger core_logger.SugaredLogger, nodes *test_env.ClCluster) (bool, error) { wg := &sync.WaitGroup{} @@ -699,7 +605,7 @@ func GetMissingLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmit if int64(len(allLogsInEVMNode)) != expectedTotalLogsEmitted { l.Warn(). Str("Actual/Expected", fmt.Sprintf("%d/%d", expectedTotalLogsEmitted, len(allLogsInEVMNode))). - Msg("Some of the test logs were not found in EVM node. This is a bug in the test") + Msg("Actual number of logs found on EVM nodes differs from expected ones. Most probably this is a bug in the test") } return missingLogs, nil @@ -854,58 +760,89 @@ func runWaspGenerator(t *testing.T, cfg *lp_config.Config, logEmitters []*contra return counter.value, nil } +type logEmissionTask struct { + emitter *contracts.LogEmitter + eventsToEmit []abi.Event + eventsPerTx int +} + +type emittedLogsData struct { + count int +} + +func (d emittedLogsData) GetResult() emittedLogsData { + return d +} + // runLoopedGenerator runs the looped generator and returns the total number of logs emitted func runLoopedGenerator(t *testing.T, cfg *lp_config.Config, client *seth.Client, logEmitters []*contracts.LogEmitter) (int, error) { l := logging.GetTestLogger(t) - // Start emitting events in parallel, each contract is emitting events in a separate goroutine - // We will stop as soon as we encounter an error - wg := &sync.WaitGroup{} - emitterCh := make(chan LogEmitterChannel, len(logEmitters)) + tasks := make([]logEmissionTask, 0) + for i := 0; i < *cfg.LoopedConfig.ExecutionCount; i++ { + for _, logEmitter := range logEmitters { + tasks = append(tasks, logEmissionTask{ + emitter: logEmitter, + eventsToEmit: cfg.General.EventsToEmit, + eventsPerTx: *cfg.General.EventsPerTx, + }) + } + } - ctx, cancelFn := context.WithCancel(context.Background()) - defer cancelFn() + l.Info().Int("Total tasks", len(tasks)).Msg("Starting to emit events") - for i := 0; i < len(logEmitters); i++ { - wg.Add(1) - go func(idx int) { - emitEvents(ctx, l, client, logEmitters[idx], cfg, wg, emitterCh) - }(i) - } + var atomicCounter = atomic.Int32{} - var emitErr error - total := 0 + var emitAllEventsFn = func(resultCh chan emittedLogsData, errorCh chan error, _ int, task logEmissionTask) { + current := atomicCounter.Add(1) - aggrChan := make(chan int, len(logEmitters)) + address := (*task.emitter).Address().String() - go func() { - for { - select { - case <-ctx.Done(): + for _, event := range cfg.General.EventsToEmit { + l.Debug().Str("Emitter address", address).Str("Event type", event.Name).Str("index", fmt.Sprintf("%d/%d", current, *cfg.LoopedConfig.ExecutionCount)).Msg("Emitting log from emitter") + var err error + switch event.Name { + case "Log1": + _, err = client.Decode((*task.emitter).EmitLogIntsFromKey(getIntSlice(*cfg.General.EventsPerTx), client.AnySyncedKey())) + case "Log2": + _, err = client.Decode((*task.emitter).EmitLogIntsIndexedFromKey(getIntSlice(*cfg.General.EventsPerTx), client.AnySyncedKey())) + case "Log3": + _, err = client.Decode((*task.emitter).EmitLogStringsFromKey(getStringSlice(*cfg.General.EventsPerTx), client.AnySyncedKey())) + case "Log4": + _, err = client.Decode((*task.emitter).EmitLogIntMultiIndexedFromKey(1, 1, *cfg.General.EventsPerTx, client.AnySyncedKey())) + default: + err = fmt.Errorf("unknown event name: %s", event.Name) + } + + if err != nil { + errorCh <- err return - case emitter := <-emitterCh: - if emitter.err != nil { - emitErr = emitter.err - cancelFn() - return - } - aggrChan <- emitter.logsEmitted + } + randomWait(*cfg.LoopedConfig.MinEmitWaitTimeMs, *cfg.LoopedConfig.MaxEmitWaitTimeMs) + + if (current)%10 == 0 { + l.Info().Str("Emitter address", address).Str("Index", fmt.Sprintf("%d/%d", current, *cfg.LoopedConfig.ExecutionCount)).Msgf("Emitted all %d events", len(cfg.General.EventsToEmit)) } } - }() - wg.Wait() - close(emitterCh) + resultCh <- emittedLogsData{ + *cfg.General.EventsPerTx * len(cfg.General.EventsToEmit), + } + } + + executor := ctf_concurrency.NewConcurrentExecutor[emittedLogsData, emittedLogsData, logEmissionTask](l) + r, err := executor.Execute(int(*client.Cfg.EphemeralAddrs), tasks, emitAllEventsFn) - if emitErr != nil { - return 0, emitErr + if err != nil { + return 0, err } - for i := 0; i < len(logEmitters); i++ { - total += <-aggrChan + var total int + for _, result := range r { + total += result.count } - return int(total), nil + return total, nil } // GetExpectedLogCount returns the expected number of logs to be emitted based on the provided config From e91b82cf621386081ebd2cf6e6fc37b6d757672f Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 28 Jun 2024 17:12:52 +0200 Subject: [PATCH 26/61] [TT-1167] try updated grafana shortener (#13706) * support multiple configuration names * TT-1090: adding code to investigate issue with incorrect config being used * TT-1090: adding code to investigate issue with incorrect config being used * TT-1090: adding toml test config for remaining chains for VRF v2 Plus * support unnamed configuration * try updated grafana shortener * use new summary printer in correct job * use fixed version of print summary action * another test of shortener * remove debug --------- Co-authored-by: Ilja Pavlovs --- .github/workflows/integration-tests.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 04d97e1838..82eca4294a 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -387,7 +387,7 @@ jobs: - name: Print failed test summary if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@a8afe9cb511125685ce02bb8694298ca89685028 # v2.3.23 eth-smoke-tests-matrix-log-poller: if: ${{ !(contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') || github.event_name == 'workflow_dispatch') || inputs.distinct_run_name != '' }} @@ -500,6 +500,11 @@ jobs: path: .covdata retention-days: 1 + - name: Print failed test summary + if: always() + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@a8afe9cb511125685ce02bb8694298ca89685028 # v2.3.23 + + eth-smoke-tests-matrix: if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }} environment: integration @@ -658,15 +663,18 @@ jobs: -v $PWD/../../integration-tests/smoke/traces:/tracing \ --user "$(id -u):$(id -g)" \ -p 4317:4317 otel/opentelemetry-collector:0.88.0 --config=/etc/otel-collector.yaml + - name: Locate Docker Volume id: locate-volume if: false run: | echo "VOLUME_PATH=$(docker volume inspect --format '{{ .Mountpoint }}' otel-traces)" >> $GITHUB_OUTPUT + - name: Show Otel-Collector Logs if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' run: | docker logs otel-collector + - name: Setup GAP for Grafana uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 id: setup-gap @@ -677,6 +685,7 @@ jobs: api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} # other inputs duplicate-authorization-header: "true" + - name: Prepare Base64 TOML override uses: ./.github/actions/setup-create-base64-config with: @@ -695,6 +704,7 @@ jobs: 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' @@ -743,23 +753,27 @@ jobs: QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: "" should_tidy: "false" + - name: Show Otel-Collector Logs if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' run: | docker logs otel-collector + - name: Permissions on traces if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' run: | ls -l ./integration-tests/smoke/traces + - name: Upload Trace Data if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: trace-data path: ./integration-tests/smoke/traces/trace-data.json + - name: Print failed test summary if: always() - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@a8afe9cb511125685ce02bb8694298ca89685028 # v2.3.23 with: test_directory: ./integration-tests/smoke/ @@ -845,7 +859,6 @@ jobs: # Run the setup if the matrix finishes but this time save the cache if we have a cache hit miss # this will also only run if both of the matrix jobs pass eth-smoke-go-mod-cache: - environment: integration needs: [eth-smoke-tests] runs-on: ubuntu-latest From 39e44428435f9b87d4c5f28a91c935de009eaed0 Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Fri, 28 Jun 2024 09:33:53 -0700 Subject: [PATCH 27/61] [KS-354] Load/integration test for streams consensus aggregator (#13705) --- core/capabilities/streams/codec.go | 6 +- .../streams/consensus_agg_test.go | 123 ++++++++++++++++++ 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, 139 insertions(+), 14 deletions(-) create mode 100644 core/capabilities/streams/consensus_agg_test.go diff --git a/core/capabilities/streams/codec.go b/core/capabilities/streams/codec.go index 21784cdcf4..af574f98fa 100644 --- a/core/capabilities/streams/codec.go +++ b/core/capabilities/streams/codec.go @@ -23,8 +23,7 @@ func (c *codec) UnwrapValid(wrapped values.Value, allowedSigners [][]byte, minRe for _, signer := range allowedSigners { signersMap[common.BytesToAddress(signer)] = struct{}{} } - dest := []datastreams.FeedReport{} - err := wrapped.UnwrapTo(&dest) + dest, err := datastreams.UnwrapFeedReportList(wrapped) if err != nil { return nil, fmt.Errorf("failed to unwrap: %v", err) } @@ -44,6 +43,9 @@ func (c *codec) UnwrapValid(wrapped values.Value, allowedSigners [][]byte, minRe continue } validated[signerAddr] = struct{}{} + if len(validated) >= minRequiredSignatures { + break // early exit + } } if len(validated) < minRequiredSignatures { return nil, fmt.Errorf("not enough valid signatures %d, needed %d", len(validated), minRequiredSignatures) diff --git a/core/capabilities/streams/consensus_agg_test.go b/core/capabilities/streams/consensus_agg_test.go new file mode 100644 index 0000000000..506ad26f86 --- /dev/null +++ b/core/capabilities/streams/consensus_agg_test.go @@ -0,0 +1,123 @@ +package streams_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + + "github.com/smartcontractkit/libocr/commontypes" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/datafeeds" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/streams" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// Integration/load test that combines Data Feeds Consensus Aggregator and Streams Codec. +// For more meaningful measurements, increase the values of parameters P and T. +func TestStreamsConsensusAggregator(t *testing.T) { + Nt := 10 // trigger DON nodes + Ft := 3 // trigger DON faulty nodes + Nw := 10 // workflow DON nodes + Fw := 3 // workflow DON faulty nodes + P := 40 // feeds + T := 2 // test iterations + + triggerNodes := newNodes(t, Nt) + feeds := newFeedsWithSignedReports(t, triggerNodes, Nt, P, 1) + allowedSigners := make([][]byte, Nt) + for i := 0; i < Nt; i++ { + allowedSigners[i] = triggerNodes[i].bundle.PublicKey() // bad name - see comment on evmKeyring.PublicKey + } + + config := newAggConfig(t, feeds) + lggr := logger.TestLogger(t) + codec := streams.NewCodec(lggr) + agg, err := datafeeds.NewDataFeedsAggregator(*config, codec, lggr) + require.NoError(t, err) + + // init round - empty previous Outcome, empty observations + outcome, err := agg.Aggregate(nil, map[commontypes.OracleID][]values.Value{}, Fw) + require.NoError(t, err) + require.False(t, outcome.ShouldReport) + + // validate metadata + newState := &datafeeds.DataFeedsOutcomeMetadata{} + err = proto.Unmarshal(outcome.Metadata, newState) + require.NoError(t, err) + require.Equal(t, P, len(newState.FeedInfo)) + + // run test aggregations + startTs := time.Now().UnixMilli() + processingTime := int64(0) + for c := 0; c < T; c++ { + obs := newObservations(t, Nw, feeds, Ft+1, allowedSigners) + processingStart := time.Now().UnixMilli() + outcome, err = agg.Aggregate(outcome, obs, Fw) + processingTime += time.Now().UnixMilli() - processingStart + require.NoError(t, err) + } + totalTime := time.Now().UnixMilli() - startTs + lggr.Infow("elapsed", "totalMs", totalTime, "processingMs", processingTime) +} + +func newAggConfig(t *testing.T, feeds []feed) *values.Map { + feedMap := map[string]any{} + for _, feed := range feeds { + feedMap[feed.feedIDStr] = map[string]any{ + "deviation": "0.1", + "heartbeat": 1, + "remappedID": feed.feedIDStr, + } + } + unwrappedConfig := map[string]any{ + "feeds": feedMap, + "allowedPartialStaleness": "0.2", + } + config, err := values.NewMap(unwrappedConfig) + require.NoError(t, err) + return config +} + +func newObservations(t *testing.T, nNodes int, feeds []feed, minRequiredSignatures int, allowedSigners [][]byte) map[commontypes.OracleID][]values.Value { + observations := map[commontypes.OracleID][]values.Value{} + for i := 0; i < nNodes; i++ { + reportList := []datastreams.FeedReport{} + for j := 0; j < len(feeds); j++ { + reportIdx := 0 + signedStreamsReport := datastreams.FeedReport{ + FeedID: feeds[j].feedIDStr, + FullReport: feeds[j].reports[reportIdx].rawReport, + ReportContext: feeds[j].reports[reportIdx].reportCtx, + Signatures: feeds[j].reports[reportIdx].signatures, + } + reportList = append(reportList, signedStreamsReport) + } + + payloadVal, err := values.Wrap(reportList) + require.NoError(t, err) + + meta := datastreams.SignersMetadata{ + Signers: allowedSigners, + MinRequiredSignatures: minRequiredSignatures, + } + metaVal, err := values.Wrap(meta) + require.NoError(t, err) + + triggerEvent := capabilities.TriggerEvent{ + TriggerType: triggerID, + ID: "unused", + Timestamp: "1234", + Metadata: metaVal, + Payload: payloadVal, + } + wrappedEvent, err := values.Wrap(triggerEvent) + require.NoError(t, err) + observations[commontypes.OracleID(i)] = []values.Value{wrappedEvent} + } + return observations +} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 3adf218399..4bbd546766 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index d15cf62a75..21d3207fdd 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1212,8 +1212,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.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/go.mod b/go.mod index 5f2a2c175d..02624a20c6 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 diff --git a/go.sum b/go.sum index da0951445f..dbcf086fdc 100644 --- a/go.sum +++ b/go.sum @@ -1169,8 +1169,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.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 96c004d492..123811ebe2 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -28,7 +28,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index d76b199515..b31b5487eb 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1513,8 +1513,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.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 9437ca3c98..800f514722 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.1.7-0.20240627134843-36665f8f9f40 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 3ad51a7ec0..d284b8484b 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1503,8 +1503,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.1.7-0.20240627134843-36665f8f9f40 h1:ewTiUC5thYTuoLCW67VwQzM7DXnz4XQU4GOk4IRYM/o= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627134843-36665f8f9f40/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From f33cd1915c03bef9bfe110481eb13094c36ce454 Mon Sep 17 00:00:00 2001 From: Nick Corin Date: Fri, 28 Jun 2024 19:23:07 +0200 Subject: [PATCH 28/61] [BCI-3438] Add the chainwriter to the EVM relayer impl (#13718) * evm: Add chain writer constructor onto the evm relayer impl * changeset: Add changeset --- .changeset/five-apes-fold.md | 5 +++++ core/services/relay/evm/evm.go | 9 +++++++++ core/services/relay/evm/write_target.go | 9 +++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 .changeset/five-apes-fold.md diff --git a/.changeset/five-apes-fold.md b/.changeset/five-apes-fold.md new file mode 100644 index 0000000000..b9f33cbfa1 --- /dev/null +++ b/.changeset/five-apes-fold.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Added a chain writer constructor onto the evm relayer. diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index bda99d3cb1..0a6dea6588 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -626,6 +626,15 @@ func newOnChainContractTransmitter(ctx context.Context, lggr logger.Logger, rarg ) } +func (r *Relayer) NewChainWriter(_ context.Context, config []byte) (commontypes.ChainWriter, error) { + var cfg types.ChainWriterConfig + if err := json.Unmarshal(config, &cfg); err != nil { + return nil, fmt.Errorf("failed to unmarshall chain writer config err: %s", err) + } + + return NewChainWriterService(r.lggr, r.chain.Client(), r.chain.TxManager(), r.chain.GasEstimator(), cfg) +} + func (r *Relayer) NewContractReader(chainReaderConfig []byte) (commontypes.ContractReader, error) { ctx := context.Background() cfg := &types.ChainReaderConfig{} diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index 46f4f83b05..dc1a363533 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -69,9 +69,14 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain }, }, } - chainWriterConfig.MaxGasPrice = chain.Config().EVM().GasEstimator().PriceMax() - cw, err := NewChainWriterService(lggr.Named("ChainWriter"), chain.Client(), chain.TxManager(), chain.GasEstimator(), chainWriterConfig) + + encodedWriterConfig, err := json.Marshal(chainWriterConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal chainwriter config: %w", err) + } + + cw, err := relayer.NewChainWriter(ctx, encodedWriterConfig) if err != nil { return nil, err } From 3b4a7e45aef216fec56565f0ff51218d983ff24c Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 28 Jun 2024 14:03:59 -0400 Subject: [PATCH 29/61] Adding foundations to root (#13559) * renamed: CODEOWNERS -> .github/CODEOWNERS * adding foundations to root * fixing root path --- CODEOWNERS => .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename CODEOWNERS => .github/CODEOWNERS (99%) diff --git a/CODEOWNERS b/.github/CODEOWNERS similarity index 99% rename from CODEOWNERS rename to .github/CODEOWNERS index 5b80a90b27..fbaeeef27f 100644 --- a/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,8 +2,8 @@ # 1. Per Github docs: "Order is important; the last matching pattern takes the most precedence." # Please define less specific codeowner paths before more specific codeowner paths in order for the more specific rule to have priority -# Core -/core @smartcontractkit/foundations +# Root +* @smartcontractkit/foundations # Chains /common @smartcontractkit/bix-framework From 363e8290bb5ea2f7bf07528ba19cc64dca8e87a8 Mon Sep 17 00:00:00 2001 From: amit-momin <108959691+amit-momin@users.noreply.github.com> Date: Fri, 28 Jun 2024 13:30:17 -0500 Subject: [PATCH 30/61] Update L1 gas price calculations for Optimism Ecotone and Fjord upgrades (#13661) * Updated L1 gas price calculations for Optimism Ecotone and Fjord upgrades * Added changeset * Fixed linting * Removed panics from L1 oracle initialization * Fixed linting * Updated comments * Fixed upgrade check batch result parsing * Fixed linting errors --- .changeset/sharp-rabbits-tie.md | 5 + .../chains/evm/gas/arbitrum_estimator_test.go | 40 +- core/chains/evm/gas/models.go | 16 +- core/chains/evm/gas/models_test.go | 3 +- .../evm/gas/rollups/arbitrum_l1_oracle.go | 8 +- core/chains/evm/gas/rollups/l1_oracle.go | 16 +- core/chains/evm/gas/rollups/l1_oracle_abi.go | 8 +- core/chains/evm/gas/rollups/l1_oracle_test.go | 87 ++-- .../evm/gas/rollups/mocks/da_price_reader.go | 59 --- core/chains/evm/gas/rollups/op_l1_oracle.go | 441 ++++++++++++------ .../evm/gas/rollups/op_l1_oracle_test.go | 306 ++++++++---- .../evm/gas/rollups/zkSync_l1_oracle.go | 2 +- core/chains/evm/txmgr/txmgr_test.go | 15 +- core/chains/legacyevm/evm_txm.go | 4 +- .../promreporter/prom_reporter_test.go | 3 +- 15 files changed, 629 insertions(+), 384 deletions(-) create mode 100644 .changeset/sharp-rabbits-tie.md delete mode 100644 core/chains/evm/gas/rollups/mocks/da_price_reader.go diff --git a/.changeset/sharp-rabbits-tie.md b/.changeset/sharp-rabbits-tie.md new file mode 100644 index 0000000000..9daed9f405 --- /dev/null +++ b/.changeset/sharp-rabbits-tie.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Updated L1 gas price calculations for Optimism Ecotone and Fjord upgrades #internal diff --git a/core/chains/evm/gas/arbitrum_estimator_test.go b/core/chains/evm/gas/arbitrum_estimator_test.go index 289025fcda..cbc6d5d37f 100644 --- a/core/chains/evm/gas/arbitrum_estimator_test.go +++ b/core/chains/evm/gas/arbitrum_estimator_test.go @@ -55,10 +55,11 @@ func TestArbitrumEstimator(t *testing.T) { t.Run("calling GetLegacyGas on unstarted estimator returns error", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) - _, _, err := o.GetLegacyGas(tests.Context(t), calldata, gasLimit, maxGasPrice) + _, _, err = o.GetLegacyGas(tests.Context(t), calldata, gasLimit, maxGasPrice) assert.EqualError(t, err, "estimator is not started") }) @@ -68,7 +69,8 @@ func TestArbitrumEstimator(t *testing.T) { zeros.Write(common.BigToHash(big.NewInt(123455)).Bytes()) t.Run("calling GetLegacyGas on started estimator returns estimates", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) @@ -93,7 +95,8 @@ func TestArbitrumEstimator(t *testing.T) { t.Run("gas price is lower than user specified max gas price", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) @@ -119,7 +122,8 @@ func TestArbitrumEstimator(t *testing.T) { t.Run("gas price is lower than global max gas price", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) @@ -144,16 +148,18 @@ func TestArbitrumEstimator(t *testing.T) { t.Run("calling BumpLegacyGas on unstarted arbitrum estimator returns error", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) - _, _, err := o.BumpLegacyGas(tests.Context(t), assets.NewWeiI(42), gasLimit, assets.NewWeiI(10), nil) + _, _, err = o.BumpLegacyGas(tests.Context(t), assets.NewWeiI(42), gasLimit, assets.NewWeiI(10), nil) assert.EqualError(t, err, "estimator is not started") }) t.Run("calling GetLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) @@ -168,35 +174,38 @@ func TestArbitrumEstimator(t *testing.T) { servicetest.RunHealthy(t, o) - _, _, err := o.GetLegacyGas(tests.Context(t), calldata, gasLimit, maxGasPrice) + _, _, err = o.GetLegacyGas(tests.Context(t), calldata, gasLimit, maxGasPrice) assert.EqualError(t, err, "failed to estimate gas; gas price not set") }) t.Run("calling GetDynamicFee always returns error", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) - _, err := o.GetDynamicFee(tests.Context(t), maxGasPrice) + _, err = o.GetDynamicFee(tests.Context(t), maxGasPrice) assert.EqualError(t, err, "dynamic fees are not implemented for this estimator") }) t.Run("calling BumpDynamicFee always returns error", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) fee := gas.DynamicFee{ FeeCap: assets.NewWeiI(42), TipCap: assets.NewWeiI(5), } - _, err := o.BumpDynamicFee(tests.Context(t), fee, maxGasPrice, nil) + _, err = o.BumpDynamicFee(tests.Context(t), fee, maxGasPrice, nil) assert.EqualError(t, err, "dynamic fees are not implemented for this estimator") }) t.Run("limit computes", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) @@ -232,7 +241,8 @@ func TestArbitrumEstimator(t *testing.T) { t.Run("limit exceeds max", func(t *testing.T) { feeEstimatorClient := mocks.NewFeeEstimatorClient(t) - l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + l1Oracle, err := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + require.NoError(t, err) feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 320834caba..8c1d19280a 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -52,7 +52,7 @@ type feeEstimatorClient interface { } // NewEstimator returns the estimator for a given config -func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, geCfg evmconfig.GasEstimator) EvmFeeEstimator { +func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, geCfg evmconfig.GasEstimator) (EvmFeeEstimator, error) { bh := geCfg.BlockHistory() s := geCfg.Mode() lggr.Infow(fmt.Sprintf("Initializing EVM gas estimator in mode: %s", s), @@ -79,13 +79,21 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, // create l1Oracle only if it is supported for the chain var l1Oracle rollups.L1Oracle if rollups.IsRollupWithL1Support(cfg.ChainType()) { - l1Oracle = rollups.NewL1GasOracle(lggr, ethClient, cfg.ChainType()) + var err error + l1Oracle, err = rollups.NewL1GasOracle(lggr, ethClient, cfg.ChainType()) + if err != nil { + return nil, fmt.Errorf("failed to initialize L1 oracle: %w", err) + } } var newEstimator func(logger.Logger) EvmEstimator switch s { case "Arbitrum": + arbOracle, err := rollups.NewArbitrumL1GasOracle(lggr, ethClient) + if err != nil { + return nil, fmt.Errorf("failed to initialize Arbitrum L1 oracle: %w", err) + } newEstimator = func(l logger.Logger) EvmEstimator { - return NewArbitrumEstimator(lggr, geCfg, ethClient, rollups.NewArbitrumL1GasOracle(lggr, ethClient)) + return NewArbitrumEstimator(lggr, geCfg, ethClient, arbOracle) } case "BlockHistory": newEstimator = func(l logger.Logger) EvmEstimator { @@ -105,7 +113,7 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, return NewFixedPriceEstimator(geCfg, ethClient, bh, lggr, l1Oracle) } } - return NewEvmFeeEstimator(lggr, newEstimator, df, geCfg) + return NewEvmFeeEstimator(lggr, newEstimator, df, geCfg), nil } // DynamicFee encompasses both FeeCap and TipCap for EIP1559 transactions diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index 059d0ed3d0..92ea901596 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -65,7 +65,8 @@ func TestWrappedEvmEstimator(t *testing.T) { assert.Nil(t, l1Oracle) // expect l1Oracle - oracle := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock) + oracle, err := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock) + require.NoError(t, err) // cast oracle to L1Oracle interface estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) diff --git a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go index 9e15cfe4c9..eb8dae3de2 100644 --- a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go +++ b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go @@ -71,7 +71,7 @@ const ( ArbGasInfo_getPricesInArbGas = "02199f34" ) -func NewArbitrumL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) *arbitrumL1Oracle { +func NewArbitrumL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) (*arbitrumL1Oracle, error) { var l1GasPriceAddress, gasPriceMethod, l1GasCostAddress, gasCostMethod string var l1GasPriceMethodAbi, l1GasCostMethodAbi abi.ABI var gasPriceErr, gasCostErr error @@ -84,10 +84,10 @@ func NewArbitrumL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) *arbit l1GasCostMethodAbi, gasCostErr = abi.JSON(strings.NewReader(GasEstimateL1ComponentAbiString)) if gasPriceErr != nil { - panic("Failed to parse L1 gas price method ABI for chain: arbitrum") + return nil, fmt.Errorf("failed to parse L1 gas price method ABI for chain: arbitrum: %w", gasPriceErr) } if gasCostErr != nil { - panic("Failed to parse L1 gas cost method ABI for chain: arbitrum") + return nil, fmt.Errorf("failed to parse L1 gas cost method ABI for chain: arbitrum: %w", gasCostErr) } return &arbitrumL1Oracle{ @@ -106,7 +106,7 @@ func NewArbitrumL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) *arbit chInitialised: make(chan struct{}), chStop: make(chan struct{}), chDone: make(chan struct{}), - } + }, nil } func (o *arbitrumL1Oracle) Name() string { diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index 97cc673154..234ddd9fdc 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -52,20 +52,24 @@ func IsRollupWithL1Support(chainType chaintype.ChainType) bool { return slices.Contains(supportedChainTypes, chainType) } -func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) L1Oracle { +func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) (L1Oracle, error) { if !IsRollupWithL1Support(chainType) { - return nil + return nil, nil } var l1Oracle L1Oracle + var err error switch chainType { case chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll: - l1Oracle = NewOpStackL1GasOracle(lggr, ethClient, chainType) + l1Oracle, err = NewOpStackL1GasOracle(lggr, ethClient, chainType) case chaintype.ChainArbitrum: - l1Oracle = NewArbitrumL1GasOracle(lggr, ethClient) + l1Oracle, err = NewArbitrumL1GasOracle(lggr, ethClient) case chaintype.ChainZkSync: l1Oracle = NewZkSyncL1GasOracle(lggr, ethClient) default: - panic(fmt.Sprintf("Received unspported chaintype %s", chainType)) + return nil, fmt.Errorf("received unsupported chaintype %s", chainType) } - return l1Oracle + if err != nil { + return nil, fmt.Errorf("failed to initialize L1 oracle for chaintype %s: %w", chainType, err) + } + return l1Oracle, nil } diff --git a/core/chains/evm/gas/rollups/l1_oracle_abi.go b/core/chains/evm/gas/rollups/l1_oracle_abi.go index dc18e43c98..fa5d9c8539 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_abi.go +++ b/core/chains/evm/gas/rollups/l1_oracle_abi.go @@ -12,6 +12,10 @@ const GasEstimateL1ComponentAbiString = `[{"inputs":[{"internalType":"address"," const L1BaseFeeAbiString = `[{"inputs":[],"name":"l1BaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` const GetL1FeeAbiString = `[{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"getL1Fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` -// ABIs for OP Stack Ecotone GasPriceOracle methods needed to calculated encoded gas price +// ABIs for OP Stack GasPriceOracle methods needed to calculated encoded gas price const OPIsEcotoneAbiString = `[{"inputs":[],"name":"isEcotone","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]` -const OPGetL1GasUsedAbiString = `[{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"getL1GasUsed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` +const OPIsFjordAbiString = `[{"inputs":[],"name":"isFjord","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]` +const OPBaseFeeScalarAbiString = `[{"inputs":[],"name":"baseFeeScalar","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]` +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"}]` diff --git a/core/chains/evm/gas/rollups/l1_oracle_test.go b/core/chains/evm/gas/rollups/l1_oracle_test.go index 800a3558d1..7a28523d39 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/l1_oracle_test.go @@ -2,7 +2,6 @@ package rollups import ( "encoding/hex" - "errors" "math/big" "strings" "testing" @@ -31,7 +30,9 @@ func TestL1Oracle(t *testing.T) { t.Run("Unsupported ChainType returns nil", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - assert.Nil(t, NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainCelo)) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainCelo) + require.NoError(t, err) + assert.Nil(t, oracle) }) } @@ -41,9 +42,10 @@ func TestL1Oracle_GasPrice(t *testing.T) { t.Run("Calling GasPrice on unstarted L1Oracle returns error", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) + require.NoError(t, err) - _, err := oracle.GasPrice(tests.Context(t)) + _, err = oracle.GasPrice(tests.Context(t)) assert.EqualError(t, err, "L1GasOracle is not started; cannot estimate gas") }) @@ -63,7 +65,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) + require.NoError(t, err) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) @@ -78,19 +81,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - isEcotoneAbiString, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) - require.NoError(t, err) - - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { - callMsg := args.Get(1).(ethereum.CallMsg) - blockNumber := args.Get(2).(*big.Int) - var payload []byte - payload, err = isEcotoneAbiString.Pack("isEcotone") - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - assert.Nil(t, blockNumber) - }).Return(nil, errors.New("not ecotone")).Once() + ethClient := setupUpgradeCheck(t, KromaGasOracleAddress, false, false) // Ecotone, Fjord disabled ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) @@ -102,7 +93,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma, KromaGasOracleAddress) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma) + require.NoError(t, err) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) @@ -117,19 +109,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - isEcotoneAbiString, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) - require.NoError(t, err) - - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { - callMsg := args.Get(1).(ethereum.CallMsg) - blockNumber := args.Get(2).(*big.Int) - var payload []byte - payload, err = isEcotoneAbiString.Pack("isEcotone") - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - assert.Nil(t, blockNumber) - }).Return(nil, errors.New("not ecotone")).Once() + ethClient := setupUpgradeCheck(t, OPGasOracleAddress, false, false) // Ecotone, Fjord disabled ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) @@ -141,7 +121,8 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, OPGasOracleAddress) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) + require.NoError(t, err) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) @@ -155,19 +136,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - isEcotoneAbiString, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) - require.NoError(t, err) - - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { - callMsg := args.Get(1).(ethereum.CallMsg) - blockNumber := args.Get(2).(*big.Int) - var payload []byte - payload, err = isEcotoneAbiString.Pack("isEcotone") - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - assert.Nil(t, blockNumber) - }).Return(nil, errors.New("not ecotone")).Once() + ethClient := setupUpgradeCheck(t, ScrollGasOracleAddress, false, false) // Ecotone, Fjord disabled ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) @@ -179,9 +148,9 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) - require.NoError(t, oracle.Start(tests.Context(t))) - t.Cleanup(func() { assert.NoError(t, oracle.Close()) }) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) + require.NoError(t, err) + servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) require.NoError(t, err) @@ -216,9 +185,9 @@ func TestL1Oracle_GasPrice(t *testing.T) { assert.Nil(t, blockNumber) }).Return(common.BigToHash(gasPerPubByteL2).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync) - require.NoError(t, oracle.Start(tests.Context(t))) - t.Cleanup(func() { assert.NoError(t, oracle.Close()) }) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync) + require.NoError(t, err) + servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(tests.Context(t)) require.NoError(t, err) @@ -260,7 +229,8 @@ func TestL1Oracle_GetGasCost(t *testing.T) { require.Equal(t, blockNum, blockNumber) }).Return(result, nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum) + require.NoError(t, err) gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) require.NoError(t, err) @@ -272,9 +242,10 @@ func TestL1Oracle_GetGasCost(t *testing.T) { tx := types.NewTx(&types.LegacyTx{}) ethClient := mocks.NewL1OracleClient(t) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma) + require.NoError(t, err) - _, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) + _, err = oracle.GetGasCost(tests.Context(t), tx, blockNum) require.Error(t, err, "L1 gas cost not supported for this chain: kroma") }) @@ -306,7 +277,8 @@ func TestL1Oracle_GetGasCost(t *testing.T) { require.Equal(t, blockNum, blockNumber) }).Return(common.BigToHash(l1GasCost).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock) + require.NoError(t, err) gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) require.NoError(t, err) @@ -341,7 +313,8 @@ func TestL1Oracle_GetGasCost(t *testing.T) { require.Equal(t, blockNum, blockNumber) }).Return(common.BigToHash(l1GasCost).Bytes(), nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll) + require.NoError(t, err) gasCost, err := oracle.GetGasCost(tests.Context(t), tx, blockNum) require.NoError(t, err) diff --git a/core/chains/evm/gas/rollups/mocks/da_price_reader.go b/core/chains/evm/gas/rollups/mocks/da_price_reader.go deleted file mode 100644 index 4157eb1494..0000000000 --- a/core/chains/evm/gas/rollups/mocks/da_price_reader.go +++ /dev/null @@ -1,59 +0,0 @@ -// Code generated by mockery v2.42.2. DO NOT EDIT. - -package mocks - -import ( - context "context" - big "math/big" - - mock "github.com/stretchr/testify/mock" -) - -// DAPriceReader is an autogenerated mock type for the daPriceReader type -type DAPriceReader struct { - mock.Mock -} - -// GetDAGasPrice provides a mock function with given fields: ctx -func (_m *DAPriceReader) GetDAGasPrice(ctx context.Context) (*big.Int, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for GetDAGasPrice") - } - - 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 -} - -// NewDAPriceReader creates a new instance of DAPriceReader. 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 NewDAPriceReader(t interface { - mock.TestingT - Cleanup(func()) -}) *DAPriceReader { - mock := &DAPriceReader{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index 1977d139f9..ade7604a44 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -27,64 +27,76 @@ import ( ) // Reads L2-specific precompiles and caches the l1GasPrice set by the L2. -type OptimismL1Oracle struct { +type optimismL1Oracle struct { services.StateMachine client l1OracleClient pollPeriod time.Duration logger logger.SugaredLogger chainType chaintype.ChainType - l1OracleAddress string - gasPriceMethod string - l1GasPriceMethodAbi abi.ABI - l1GasPriceMu sync.RWMutex - l1GasPrice priceEntry - - gasCostMethod string - l1GasCostMethodAbi abi.ABI + l1OracleAddress string + l1GasPriceMu sync.RWMutex + l1GasPrice priceEntry + isEcotone bool + isFjord bool + upgradeCheckTs time.Time chInitialised chan struct{} chStop services.StopChan chDone chan struct{} - isEcotoneMethodAbi abi.ABI - - l1BaseFeeCalldata []byte - isEcotoneCalldata []byte - getL1GasUsedCalldata []byte - getL1FeeCalldata []byte - - isEcotone bool - isEcotoneCheckTs int64 + getL1FeeMethodAbi abi.ABI + l1BaseFeeCalldata []byte + baseFeeScalarCalldata []byte + blobBaseFeeCalldata []byte + blobBaseFeeScalarCalldata []byte + decimalsCalldata []byte + isEcotoneCalldata []byte + isEcotoneMethodAbi abi.ABI + isFjordCalldata []byte + isFjordMethodAbi abi.ABI } const ( - // OPStackGasOracle_isEcotone fetches if the OP Stack GasPriceOracle contract has upgraded to Ecotone - OPStackGasOracle_isEcotone = "isEcotone" - // OPStackGasOracle_getL1GasUsed fetches the l1 gas used for given tx bytes - OPStackGasOracle_getL1GasUsed = "getL1GasUsed" - // OPStackGasOracle_isEcotonePollingPeriod is the interval to poll if chain has upgraded to Ecotone - // Set to poll every 4 hours - OPStackGasOracle_isEcotonePollingPeriod = 14400 - // OPStackGasOracleAddress is the address of the precompiled contract that exists on OP stack chain. - // OPStackGasOracle_l1BaseFee fetches the l1 base fee set in the OP Stack GasPriceOracle contract - // OPStackGasOracle_l1BaseFee is a hex encoded call to: - // `function l1BaseFee() external view returns (uint256);` - OPStackGasOracle_l1BaseFee = "l1BaseFee" - // OPStackGasOracle_getL1Fee fetches the l1 fee for given tx bytes - // OPStackGasOracle_getL1Fee is a hex encoded call to: + // upgradePollingPeriod is the interval to poll if chain has been upgraded + upgradePollingPeriod = 4 * time.Hour + // isEcotone fetches if the OP Stack GasPriceOracle contract has upgraded to Ecotone + isEcotoneMethod = "isEcotone" + // isFjord fetches if the OP Stack GasPriceOracle contract has upgraded to Fjord + isFjordMethod = "isFjord" + // getL1Fee fetches the l1 fee for given tx bytes + // getL1Fee is a hex encoded call to: // `function getL1Fee(bytes) external view returns (uint256);` - OPStackGasOracle_getL1Fee = "getL1Fee" - // This is the case for Optimism and Base. + getL1FeeMethod = "getL1Fee" + // l1BaseFee fetches the l1 base fee set in the OP Stack GasPriceOracle contract + // l1BaseFee is a hex encoded call to: + // `function l1BaseFee() external view returns (uint256);` + l1BaseFeeMethod = "l1BaseFee" + // baseFeeScalar fetches the l1 base fee scalar for gas price calculation + // baseFeeScalar is a hex encoded call to: + // `function baseFeeScalar() public view returns (uint32);` + baseFeeScalarMethod = "baseFeeScalar" + // blobBaseFee fetches the l1 blob base fee for gas price calculation + // blobBaseFee is a hex encoded call to: + // `function blobBaseFee() public view returns (uint256);` + blobBaseFeeMethod = "blobBaseFee" + // blobBaseFeeScalar fetches the l1 blob base fee scalar for gas price calculation + // blobBaseFeeScalar is a hex encoded call to: + // `function blobBaseFeeScalar() public view returns (uint32);` + blobBaseFeeScalarMethod = "blobBaseFeeScalar" + // decimals fetches the number of decimals used in the scalar for gas price calculation + // 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. OPGasOracleAddress = "0x420000000000000000000000000000000000000F" - // GasOracleAddress is the address of the precompiled contract that exists on Kroma chain. - // This is the case for Kroma. + // KromaGasOracleAddress is the address of the precompiled contract that exists on Kroma. KromaGasOracleAddress = "0x4200000000000000000000000000000000000005" - // ScrollGasOracleAddress is the address of the precompiled contract that exists on Scroll chain. + // ScrollGasOracleAddress is the address of the precompiled contract that exists on Scroll. ScrollGasOracleAddress = "0x5300000000000000000000000000000000000002" ) -func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) *OptimismL1Oracle { +func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) (*optimismL1Oracle, error) { var precompileAddress string switch chainType { case chaintype.ChainOptimismBedrock: @@ -94,106 +106,128 @@ func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy case chaintype.ChainScroll: precompileAddress = ScrollGasOracleAddress default: - panic(fmt.Sprintf("Received unspported chaintype %s", chainType)) + return nil, fmt.Errorf("received unsupported chaintype %s", chainType) } return newOpStackL1GasOracle(lggr, ethClient, chainType, precompileAddress) } -func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, precompileAddress string) *OptimismL1Oracle { - var l1OracleAddress, gasPriceMethod, gasCostMethod string - var l1GasPriceMethodAbi, l1GasCostMethodAbi abi.ABI - var gasPriceErr, gasCostErr error - - l1OracleAddress = precompileAddress - gasPriceMethod = OPStackGasOracle_l1BaseFee - l1GasPriceMethodAbi, gasPriceErr = abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - gasCostMethod = OPStackGasOracle_getL1Fee - l1GasCostMethodAbi, gasCostErr = abi.JSON(strings.NewReader(GetL1FeeAbiString)) - - if gasPriceErr != nil { - panic(fmt.Sprintf("Failed to parse L1 gas price method ABI for chain: %s", chainType)) - } - if gasCostErr != nil { - panic(fmt.Sprintf("Failed to parse L1 gas cost method ABI for chain: %s", chainType)) +func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, precompileAddress string) (*optimismL1Oracle, error) { + getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse L1 gas cost method ABI for chain: %s", chainType) } // encode calldata for each method; these calldata will remain the same for each call, we can encode them just once + // Encode calldata for l1BaseFee method l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_l1BaseFee, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", l1BaseFeeMethod, chainType, err) } - l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(OPStackGasOracle_l1BaseFee) + l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(l1BaseFeeMethod) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_l1BaseFee, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", l1BaseFeeMethod, chainType, err) } + // Encode calldata for isEcotone method isEcotoneMethodAbi, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_isEcotone, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", isEcotoneMethod, chainType, err) } - isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(OPStackGasOracle_isEcotone) + isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(isEcotoneMethod) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_isEcotone, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", isEcotoneMethod, chainType, err) } - getL1GasUsedMethodAbi, err := abi.JSON(strings.NewReader(OPGetL1GasUsedAbiString)) + // Encode calldata for isFjord method + isFjordMethodAbi, err := abi.JSON(strings.NewReader(OPIsFjordAbiString)) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_getL1GasUsed, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", isFjordMethod, chainType, err) } - getL1GasUsedCalldata, err := getL1GasUsedMethodAbi.Pack(OPStackGasOracle_getL1GasUsed, []byte{0x1}) + isFjordCalldata, err := isFjordMethodAbi.Pack(isFjordMethod) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_getL1GasUsed, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", isFjordMethod, chainType, err) } - getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) + // Encode calldata for baseFeeScalar method + baseFeeScalarMethodAbi, err := abi.JSON(strings.NewReader(OPBaseFeeScalarAbiString)) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_getL1Fee, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", baseFeeScalarMethod, chainType, err) } - getL1FeeCalldata, err := getL1FeeMethodAbi.Pack(OPStackGasOracle_getL1Fee, []byte{0x1}) + baseFeeScalarCalldata, err := baseFeeScalarMethodAbi.Pack(baseFeeScalarMethod) if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_getL1Fee, chainType, err)) + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", baseFeeScalarMethod, chainType, err) } - return &OptimismL1Oracle{ + // Encode calldata for blobBaseFee method + blobBaseFeeMethodAbi, err := abi.JSON(strings.NewReader(OPBlobBaseFeeAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", blobBaseFeeMethod, chainType, err) + } + blobBaseFeeCalldata, err := blobBaseFeeMethodAbi.Pack(blobBaseFeeMethod) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", blobBaseFeeMethod, chainType, err) + } + + // Encode calldata for blobBaseFeeScalar method + blobBaseFeeScalarMethodAbi, err := abi.JSON(strings.NewReader(OPBlobBaseFeeScalarAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", blobBaseFeeScalarMethod, chainType, err) + } + blobBaseFeeScalarCalldata, err := blobBaseFeeScalarMethodAbi.Pack(blobBaseFeeScalarMethod) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", blobBaseFeeScalarMethod, chainType, err) + } + + // Encode calldata for decimals method + decimalsMethodAbi, err := abi.JSON(strings.NewReader(OPDecimalsAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", decimalsMethod, chainType, err) + } + decimalsCalldata, err := decimalsMethodAbi.Pack(decimalsMethod) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", decimalsMethod, chainType, err) + } + + return &optimismL1Oracle{ client: ethClient, pollPeriod: PollPeriod, - logger: logger.Sugared(logger.Named(lggr, "L1GasOracle(optimismBedrock)")), + logger: logger.Sugared(logger.Named(lggr, fmt.Sprintf("L1GasOracle(%s)", chainType))), chainType: chainType, - l1OracleAddress: l1OracleAddress, - gasPriceMethod: gasPriceMethod, - l1GasPriceMethodAbi: l1GasPriceMethodAbi, - gasCostMethod: gasCostMethod, - l1GasCostMethodAbi: l1GasCostMethodAbi, + l1OracleAddress: precompileAddress, + isEcotone: false, + isFjord: false, + upgradeCheckTs: time.Time{}, chInitialised: make(chan struct{}), chStop: make(chan struct{}), chDone: make(chan struct{}), - isEcotoneMethodAbi: isEcotoneMethodAbi, - - l1BaseFeeCalldata: l1BaseFeeCalldata, - isEcotoneCalldata: isEcotoneCalldata, - getL1GasUsedCalldata: getL1GasUsedCalldata, - getL1FeeCalldata: getL1FeeCalldata, - - isEcotone: false, - isEcotoneCheckTs: 0, - } + getL1FeeMethodAbi: getL1FeeMethodAbi, + l1BaseFeeCalldata: l1BaseFeeCalldata, + baseFeeScalarCalldata: baseFeeScalarCalldata, + blobBaseFeeCalldata: blobBaseFeeCalldata, + blobBaseFeeScalarCalldata: blobBaseFeeScalarCalldata, + decimalsCalldata: decimalsCalldata, + isEcotoneCalldata: isEcotoneCalldata, + isEcotoneMethodAbi: isEcotoneMethodAbi, + isFjordCalldata: isFjordCalldata, + isFjordMethodAbi: isFjordMethodAbi, + }, nil } -func (o *OptimismL1Oracle) Name() string { +func (o *optimismL1Oracle) Name() string { return o.logger.Name() } -func (o *OptimismL1Oracle) Start(ctx context.Context) error { +func (o *optimismL1Oracle) Start(ctx context.Context) error { return o.StartOnce(o.Name(), func() error { go o.run() <-o.chInitialised return nil }) } -func (o *OptimismL1Oracle) Close() error { +func (o *optimismL1Oracle) Close() error { return o.StopOnce(o.Name(), func() error { close(o.chStop) <-o.chDone @@ -201,11 +235,11 @@ func (o *OptimismL1Oracle) Close() error { }) } -func (o *OptimismL1Oracle) HealthReport() map[string]error { +func (o *optimismL1Oracle) HealthReport() map[string]error { return map[string]error{o.Name(): o.Healthy()} } -func (o *OptimismL1Oracle) run() { +func (o *optimismL1Oracle) run() { defer close(o.chDone) t := o.refresh() @@ -220,7 +254,7 @@ func (o *OptimismL1Oracle) run() { } } } -func (o *OptimismL1Oracle) refresh() (t *time.Timer) { +func (o *optimismL1Oracle) refresh() (t *time.Timer) { t, err := o.refreshWithError() if err != nil { o.SvcErrBuffer.Append(err) @@ -228,7 +262,7 @@ func (o *OptimismL1Oracle) refresh() (t *time.Timer) { return } -func (o *OptimismL1Oracle) refreshWithError() (t *time.Timer, err error) { +func (o *optimismL1Oracle) refreshWithError() (t *time.Timer, err error) { t = time.NewTimer(utils.WithJitter(o.pollPeriod)) ctx, cancel := o.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout()) @@ -245,7 +279,7 @@ func (o *OptimismL1Oracle) refreshWithError() (t *time.Timer, err error) { return } -func (o *OptimismL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, err error) { +func (o *optimismL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, err error) { var timestamp time.Time ok := o.IfStarted(func() { o.l1GasPriceMu.RLock() @@ -269,7 +303,7 @@ func (o *OptimismL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, // Gets the L1 gas cost for the provided transaction at the specified block num // If block num is not provided, the value on the latest block num is used -func (o *OptimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { +func (o *optimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { ctx, cancel := context.WithTimeout(ctx, client.QueryTimeout) defer cancel() var callData, b []byte @@ -282,7 +316,7 @@ func (o *OptimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transac if encodedtx, err = tx.MarshalBinary(); err != nil { return nil, fmt.Errorf("failed to marshal tx for gas cost estimation: %w", err) } - if callData, err = o.l1GasCostMethodAbi.Pack(o.gasCostMethod, encodedtx); err != nil { + if callData, err = o.getL1FeeMethodAbi.Pack(getL1FeeMethod, encodedtx); err != nil { return nil, fmt.Errorf("failed to pack calldata for %s L1 gas cost estimation method: %w", o.chainType, err) } @@ -308,54 +342,89 @@ func (o *OptimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transac return assets.NewWei(l1GasCost), nil } -func (o *OptimismL1Oracle) GetDAGasPrice(ctx context.Context) (*big.Int, error) { - isEcotone, err := o.checkIsEcotone(ctx) +func (o *optimismL1Oracle) GetDAGasPrice(ctx context.Context) (*big.Int, error) { + err := o.checkForUpgrade(ctx) if err != nil { return nil, err } - - o.logger.Infof("Chain isEcotone result: %t", isEcotone) - - if isEcotone { - return o.getEcotoneGasPrice(ctx) + if o.isFjord || o.isEcotone { + return o.getEcotoneFjordGasPrice(ctx) } return o.getV1GasPrice(ctx) } -func (o *OptimismL1Oracle) checkIsEcotone(ctx context.Context) (bool, error) { - // if chain is already Ecotone, NOOP - if o.isEcotone { - return true, nil +// Checks oracle flags for Ecotone and Fjord upgrades +func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { + // if chain is already Fjord (the latest upgrade), NOOP + // need to continue to check if not on latest upgrade + if o.isFjord { + return nil } // if time since last check has not exceeded polling period, NOOP - if time.Now().Unix()-o.isEcotoneCheckTs < OPStackGasOracle_isEcotonePollingPeriod { - return false, nil + if time.Since(o.upgradeCheckTs) < upgradePollingPeriod { + return nil } - o.isEcotoneCheckTs = time.Now().Unix() - - l1OracleAddress := common.HexToAddress(o.l1OracleAddress) - // confirmed with OP team that isEcotone() is the canonical way to check if the chain has upgraded - b, err := o.client.CallContract(ctx, ethereum.CallMsg{ - To: &l1OracleAddress, - Data: o.isEcotoneCalldata, - }, nil) - - // if the chain has not upgraded to Ecotone, the isEcotone call will revert, this would be expected - if err != nil { - o.logger.Infof("isEcotone() call failed, this can happen if chain has not upgraded: %v", err) - return false, nil + o.upgradeCheckTs = time.Now() + rpcBatchCalls := []rpc.BatchElem{ + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.isFjordCalldata), + }, + "latest", + }, + Result: new(string), + }, + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.isEcotoneCalldata), + }, + "latest", + }, + Result: new(string), + }, } - - res, err := o.isEcotoneMethodAbi.Unpack(OPStackGasOracle_isEcotone, b) + err := o.client.BatchCallContext(ctx, rpcBatchCalls) if err != nil { - return false, fmt.Errorf("failed to unpack isEcotone() return data: %w", err) + return fmt.Errorf("check upgrade batch call failed: %w", err) + } + // These calls are expected to revert if chain has not upgraded. Ignore non-nil Error field. + if rpcBatchCalls[0].Error == nil { + result := *(rpcBatchCalls[0].Result.(*string)) + if b, decodeErr := hexutil.Decode(result); decodeErr == nil { + if res, unpackErr := o.isFjordMethodAbi.Unpack(isFjordMethod, b); unpackErr == nil { + o.isFjord = res[0].(bool) + } else { + o.logger.Errorw("failed to unpack results", "method", isFjordMethod, "hex", result, "error", unpackErr) + } + } else { + o.logger.Errorw("failed to decode bytes", "method", isFjordMethod, "hex", result, "error", decodeErr) + } + } + if rpcBatchCalls[1].Error == nil { + result := *(rpcBatchCalls[1].Result.(*string)) + if b, decodeErr := hexutil.Decode(result); decodeErr == nil { + if res, unpackErr := o.isEcotoneMethodAbi.Unpack(isEcotoneMethod, b); unpackErr == nil { + o.isEcotone = res[0].(bool) + } else { + o.logger.Errorw("failed to unpack results", "method", isEcotoneMethod, "hex", result, "error", unpackErr) + } + } else { + o.logger.Errorw("failed to decode bytes", "method", isEcotoneMethod, "hex", result, "error", decodeErr) + } } - o.isEcotone = res[0].(bool) - return o.isEcotone, nil + return nil } -func (o *OptimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) { +func (o *optimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) { l1OracleAddress := common.HexToAddress(o.l1OracleAddress) b, err := o.client.CallContract(ctx, ethereum.CallMsg{ To: &l1OracleAddress, @@ -371,7 +440,9 @@ func (o *OptimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) return new(big.Int).SetBytes(b), nil } -func (o *OptimismL1Oracle) getEcotoneGasPrice(ctx context.Context) (*big.Int, error) { +// 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) { rpcBatchCalls := []rpc.BatchElem{ { Method: "eth_call", @@ -379,7 +450,43 @@ func (o *OptimismL1Oracle) getEcotoneGasPrice(ctx context.Context) (*big.Int, er map[string]interface{}{ "from": common.Address{}, "to": o.l1OracleAddress, - "data": hexutil.Bytes(o.getL1GasUsedCalldata), + "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.baseFeeScalarCalldata), + }, + "latest", + }, + Result: new(string), + }, + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.blobBaseFeeCalldata), + }, + "latest", + }, + Result: new(string), + }, + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.blobBaseFeeScalarCalldata), }, "latest", }, @@ -391,7 +498,7 @@ func (o *OptimismL1Oracle) getEcotoneGasPrice(ctx context.Context) (*big.Int, er map[string]interface{}{ "from": common.Address{}, "to": o.l1OracleAddress, - "data": hexutil.Bytes(o.getL1FeeCalldata), + "data": hexutil.Bytes(o.decimalsCalldata), }, "latest", }, @@ -401,31 +508,75 @@ func (o *OptimismL1Oracle) getEcotoneGasPrice(ctx context.Context) (*big.Int, er err := o.client.BatchCallContext(ctx, rpcBatchCalls) if err != nil { - return nil, fmt.Errorf("getEcotoneGasPrice batch call failed: %w", err) + 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", OPStackGasOracle_getL1GasUsed, err) + 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", OPStackGasOracle_getL1Fee, err) + return nil, fmt.Errorf("%s call failed in a batch: %w", baseFeeScalarMethod, err) + } + if rpcBatchCalls[2].Error != nil { + return nil, fmt.Errorf("%s call failed in a batch: %w", blobBaseFeeMethod, err) + } + if rpcBatchCalls[3].Error != nil { + return nil, fmt.Errorf("%s call failed in a batch: %w", blobBaseFeeScalarMethod, err) + } + if rpcBatchCalls[4].Error != nil { + return nil, fmt.Errorf("%s call failed in a batch: %w", decimalsMethod, err) } - l1GasUsedResult := *(rpcBatchCalls[0].Result.(*string)) - l1FeeResult := *(rpcBatchCalls[1].Result.(*string)) + // Extract values from responses + l1BaseFeeResult := *(rpcBatchCalls[0].Result.(*string)) + baseFeeScalarResult := *(rpcBatchCalls[1].Result.(*string)) + blobBaseFeeResult := *(rpcBatchCalls[2].Result.(*string)) + blobBaseFeeScalarResult := *(rpcBatchCalls[3].Result.(*string)) + decimalsResult := *(rpcBatchCalls[4].Result.(*string)) - l1GasUsedBytes, err := hexutil.Decode(l1GasUsedResult) + // 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) + } + baseFeeScalarBytes, err := hexutil.Decode(baseFeeScalarResult) if err != nil { - return nil, fmt.Errorf("failed to decode %s rpc result: %w", OPStackGasOracle_getL1GasUsed, err) + return nil, fmt.Errorf("failed to decode %s rpc result: %w", baseFeeScalarMethod, err) } - l1FeeBytes, err := hexutil.Decode(l1FeeResult) + blobBaseFeeBytes, err := hexutil.Decode(blobBaseFeeResult) if err != nil { - return nil, fmt.Errorf("failed to decode %s rpc result: %w", OPStackGasOracle_getL1Fee, err) + return nil, fmt.Errorf("failed to decode %s rpc result: %w", blobBaseFeeMethod, err) } + blobBaseFeeScalarBytes, err := hexutil.Decode(blobBaseFeeScalarResult) + if err != nil { + return nil, fmt.Errorf("failed to decode %s rpc result: %w", blobBaseFeeScalarMethod, err) + } + decimalsBytes, err := hexutil.Decode(decimalsResult) + if err != nil { + return nil, fmt.Errorf("failed to decode %s rpc result: %w", decimalsMethod, err) + } + + // Convert bytes to big int for calculations + l1BaseFee := new(big.Int).SetBytes(l1BaseFeeBytes) + baseFeeScalar := new(big.Int).SetBytes(baseFeeScalarBytes) + blobBaseFee := new(big.Int).SetBytes(blobBaseFeeBytes) + blobBaseFeeScalar := new(big.Int).SetBytes(blobBaseFeeScalarBytes) + decimals := new(big.Int).SetBytes(decimalsBytes) + + o.logger.Debugw("gas price parameters", "l1BaseFee", l1BaseFee, "baseFeeScalar", baseFeeScalar, "blobBaseFee", blobBaseFee, "blobBaseFeeScalar", blobBaseFeeScalar, "decimals", decimals) + + // Scaled gas price = baseFee * 16 * baseFeeScalar + blobBaseFee * blobBaseFeeScalar + scaledBaseFee := new(big.Int).Mul(l1BaseFee, baseFeeScalar) + scaledBaseFee = new(big.Int).Mul(scaledBaseFee, big.NewInt(16)) + scaledBlobBaseFee := new(big.Int).Mul(blobBaseFee, blobBaseFeeScalar) + scaledGasPrice := new(big.Int).Add(scaledBaseFee, scaledBlobBaseFee) - l1GasUsed := new(big.Int).SetBytes(l1GasUsedBytes) - l1Fee := new(big.Int).SetBytes(l1FeeBytes) + // Gas price = scaled gas price / (16 * 10 ^ decimals) + // This formula is extracted from the gas cost methods in the precompile contract + // Note: The Fjord calculation in the contract uses estimated size instead of gas used which is why we have to scale down by (16 * 10 ^ decimals) as well + // Ecotone: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/GasPriceOracle.sol#L192 + // Fjord: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/GasPriceOracle.sol#L229-L230 + scale := new(big.Int).Exp(big.NewInt(10), decimals, nil) + scale = new(big.Int).Mul(scale, big.NewInt(16)) - // for the same tx byte, l1Fee / l1GasUsed will give the l1 gas price - // note this price is per l1 gas, not l1 data byte - return new(big.Int).Div(l1Fee, l1GasUsed), nil + return new(big.Int).Div(scaledGasPrice, scale), nil } 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 86fdbe0a62..f5f009f1ea 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle_test.go @@ -22,26 +22,28 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" ) -func TestDAPriceReader_ReadV1GasPrice(t *testing.T) { +func TestOPL1Oracle_ReadV1GasPrice(t *testing.T) { t.Parallel() testCases := []struct { name string isEcotoneError bool - returnBadData bool + isFjordError bool }{ { - name: "calling isEcotone returns false, fetches l1BaseFee", + name: "calling isEcotone and isFjord returns false, fetches l1BaseFee", isEcotoneError: false, + isFjordError: false, }, { - name: "calling isEcotone when chain has not made Ecotone upgrade, fetches l1BaseFee", - isEcotoneError: true, + name: "calling isEcotone returns false and IsFjord errors when chain has not made Fjord upgrade, fetches l1BaseFee", + isEcotoneError: false, + isFjordError: true, }, { - name: "calling isEcotone returns bad data, returns error", - isEcotoneError: false, - returnBadData: true, + name: "calling isEcotone and isFjord when chain has not made Ecotone upgrade, fetches l1BaseFee", + isEcotoneError: true, + isFjordError: true, }, } @@ -52,117 +54,252 @@ func TestDAPriceReader_ReadV1GasPrice(t *testing.T) { l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(OPStackGasOracle_l1BaseFee) + l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(l1BaseFeeMethod) require.NoError(t, err) + // IsFjord calldata + isFjordMethodAbi, err := abi.JSON(strings.NewReader(OPIsFjordAbiString)) + require.NoError(t, err) + isFjordCalldata, err := isFjordMethodAbi.Pack(isFjordMethod) + require.NoError(t, err) + + // IsEcotone calldata isEcotoneMethodAbi, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) require.NoError(t, err) - isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(OPStackGasOracle_isEcotone) + isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(isEcotoneMethod) require.NoError(t, err) ethClient := mocks.NewL1OracleClient(t) - call := ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + 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(isFjordCalldata), rpcElements[0].Args[0].(map[string]interface{})["data"]) + require.Equal(t, hexutil.Bytes(isEcotoneCalldata), rpcElements[1].Args[0].(map[string]interface{})["data"]) + isUpgraded := "0x0000000000000000000000000000000000000000000000000000000000000000" + if tc.isFjordError { + rpcElements[0].Error = fmt.Errorf("test error") + } else { + rpcElements[0].Result = &isUpgraded + } + if tc.isEcotoneError { + rpcElements[1].Error = fmt.Errorf("test error") + } else { + rpcElements[1].Result = &isUpgraded + } + }).Return(nil).Once() + + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - require.Equal(t, isEcotoneCalldata, callMsg.Data) + require.Equal(t, l1BaseFeeCalldata, callMsg.Data) require.Equal(t, oracleAddress, callMsg.To.String()) assert.Nil(t, blockNumber) - }) - - if tc.returnBadData { - call.Return([]byte{0x2, 0x2}, nil).Once() - } else if tc.isEcotoneError { - call.Return(nil, fmt.Errorf("test error")).Once() - } else { - call.Return(isEcotoneMethodAbi.Methods["isEcotone"].Outputs.Pack(false)).Once() - } - - if !tc.returnBadData { - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { - callMsg := args.Get(1).(ethereum.CallMsg) - blockNumber := args.Get(2).(*big.Int) - require.Equal(t, l1BaseFeeCalldata, callMsg.Data) - require.Equal(t, oracleAddress, callMsg.To.String()) - assert.Nil(t, blockNumber) - }).Return(common.BigToHash(l1BaseFee).Bytes(), nil).Once() - } - - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + }).Return(common.BigToHash(l1BaseFee).Bytes(), nil).Once() + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + require.NoError(t, err) gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) - if tc.returnBadData { - assert.Error(t, err) - } else { - require.NoError(t, err) - assert.Equal(t, l1BaseFee, gasPrice) - } + require.NoError(t, err) + assert.Equal(t, l1BaseFee, gasPrice) }) } } -func setupIsEcotone(t *testing.T, oracleAddress string) *mocks.L1OracleClient { +func setupUpgradeCheck(t *testing.T, oracleAddress string, isFjord, isEcotone bool) *mocks.L1OracleClient { + trueHex := "0x0000000000000000000000000000000000000000000000000000000000000001" + falseHex := "0x0000000000000000000000000000000000000000000000000000000000000000" + boolToHexMap := map[bool]*string{ + true: &trueHex, + false: &falseHex, + } + // IsFjord calldata + isFjordMethodAbi, err := abi.JSON(strings.NewReader(OPIsFjordAbiString)) + require.NoError(t, err) + isFjordCalldata, err := isFjordMethodAbi.Pack(isFjordMethod) + require.NoError(t, err) + + // IsEcotone calldata isEcotoneMethodAbi, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) require.NoError(t, err) - isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(OPStackGasOracle_isEcotone) + isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(isEcotoneMethod) require.NoError(t, err) ethClient := mocks.NewL1OracleClient(t) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { - callMsg := args.Get(1).(ethereum.CallMsg) - blockNumber := args.Get(2).(*big.Int) - require.Equal(t, isEcotoneCalldata, callMsg.Data) - require.Equal(t, oracleAddress, callMsg.To.String()) - assert.Nil(t, blockNumber) - }).Return(isEcotoneMethodAbi.Methods["isEcotone"].Outputs.Pack(true)).Once() + 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(isFjordCalldata), rpcElements[0].Args[0].(map[string]interface{})["data"]) + require.Equal(t, hexutil.Bytes(isEcotoneCalldata), rpcElements[1].Args[0].(map[string]interface{})["data"]) + + rpcElements[0].Result = boolToHexMap[isFjord] + rpcElements[1].Result = boolToHexMap[isEcotone] + }).Return(nil).Once() return ethClient } -func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { - l1BaseFee := big.NewInt(100) +func mockBatchContractCall(t *testing.T, ethClient *mocks.L1OracleClient, oracleAddress string, baseFeeVal, baseFeeScalarVal, blobBaseFeeVal, blobBaseFeeScalarVal, decimalsVal *big.Int) { + // L1 base fee calldata + l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) + require.NoError(t, err) + l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(l1BaseFeeMethod) + require.NoError(t, err) + + // L1 base fee scalar calldata + l1BaseFeeScalarMethodAbi, err := abi.JSON(strings.NewReader(OPBaseFeeScalarAbiString)) + require.NoError(t, err) + l1BaseFeeScalarCalldata, err := l1BaseFeeScalarMethodAbi.Pack(baseFeeScalarMethod) + require.NoError(t, err) + + // Blob base fee calldata + blobBaseFeeMethodAbi, err := abi.JSON(strings.NewReader(OPBlobBaseFeeAbiString)) + require.NoError(t, err) + blobBaseFeeCalldata, err := blobBaseFeeMethodAbi.Pack(blobBaseFeeMethod) + require.NoError(t, err) + + // Blob base fee scalar calldata + blobBaseFeeScalarMethodAbi, err := abi.JSON(strings.NewReader(OPBlobBaseFeeScalarAbiString)) + require.NoError(t, err) + blobBaseFeeScalarCalldata, err := blobBaseFeeScalarMethodAbi.Pack(blobBaseFeeScalarMethod) + require.NoError(t, err) + + // Decimals calldata + decimalsMethodAbi, err := abi.JSON(strings.NewReader(OPDecimalsAbiString)) + require.NoError(t, err) + decimalsCalldata, err := decimalsMethodAbi.Pack(decimalsMethod) + require.NoError(t, err) + + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { + rpcElements := args.Get(1).([]rpc.BatchElem) + require.Equal(t, 5, 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(l1BaseFeeScalarCalldata), rpcElements[1].Args[0].(map[string]interface{})["data"]) + require.Equal(t, hexutil.Bytes(blobBaseFeeCalldata), rpcElements[2].Args[0].(map[string]interface{})["data"]) + require.Equal(t, hexutil.Bytes(blobBaseFeeScalarCalldata), rpcElements[3].Args[0].(map[string]interface{})["data"]) + require.Equal(t, hexutil.Bytes(decimalsCalldata), rpcElements[4].Args[0].(map[string]interface{})["data"]) + + res1 := common.BigToHash(baseFeeVal).Hex() + res2 := common.BigToHash(baseFeeScalarVal).Hex() + res3 := common.BigToHash(blobBaseFeeVal).Hex() + res4 := common.BigToHash(blobBaseFeeScalarVal).Hex() + res5 := common.BigToHash(decimalsVal).Hex() + rpcElements[0].Result = &res1 + rpcElements[1].Result = &res2 + rpcElements[2].Result = &res3 + rpcElements[3].Result = &res4 + rpcElements[4].Result = &res5 + }).Return(nil).Once() +} + +func TestOPL1Oracle_CalculateEcotoneGasPrice(t *testing.T) { + baseFee := big.NewInt(100000000) + blobBaseFee := big.NewInt(25000000) + baseFeeScalar := big.NewInt(10) + blobBaseFeeScalar := big.NewInt(5) + decimals := big.NewInt(6) oracleAddress := common.HexToAddress("0x1234").String() t.Parallel() t.Run("correctly fetches weighted gas price if chain has upgraded to Ecotone", func(t *testing.T) { - ethClient := setupIsEcotone(t, oracleAddress) - getL1GasUsedMethodAbi, err := abi.JSON(strings.NewReader(OPGetL1GasUsedAbiString)) + ethClient := setupUpgradeCheck(t, oracleAddress, false, true) + mockBatchContractCall(t, ethClient, oracleAddress, baseFee, baseFeeScalar, blobBaseFee, blobBaseFeeScalar, decimals) + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) require.NoError(t, err) - getL1GasUsedCalldata, err := getL1GasUsedMethodAbi.Pack(OPStackGasOracle_getL1GasUsed, []byte{0x1}) + gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) require.NoError(t, err) + scaledGasPrice := big.NewInt(16125000000) // baseFee * scalar * 16 + blobBaseFee * scalar + scale := big.NewInt(16000000) // Scaled by 16 * 10 ^ decimals + expectedGasPrice := new(big.Int).Div(scaledGasPrice, scale) + assert.Equal(t, expectedGasPrice, gasPrice) + }) - getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) + t.Run("fetching Ecotone price but rpc returns bad data", func(t *testing.T) { + ethClient := setupUpgradeCheck(t, oracleAddress, false, true) + 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.ChainOptimismBedrock, oracleAddress) require.NoError(t, err) - getL1FeeCalldata, err := getL1FeeMethodAbi.Pack(OPStackGasOracle_getL1Fee, []byte{0x1}) + _, err = oracle.GetDAGasPrice(tests.Context(t)) + assert.Error(t, err) + }) + + t.Run("fetching Ecotone price but rpc parent call errors", func(t *testing.T) { + ethClient := setupUpgradeCheck(t, oracleAddress, false, true) + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) + assert.Error(t, err) + }) + t.Run("fetching Ecotone price but one of the sub rpc call errors", func(t *testing.T) { + ethClient := setupUpgradeCheck(t, oracleAddress, false, true) 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)) + res := common.BigToHash(baseFee).Hex() + rpcElements[0].Result = &res + rpcElements[1].Error = fmt.Errorf("revert") + }).Return(nil).Once() - 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]) - } + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) + assert.Error(t, err) + }) +} - require.Equal(t, hexutil.Bytes(getL1GasUsedCalldata), rpcElements[0].Args[0].(map[string]interface{})["data"]) - require.Equal(t, hexutil.Bytes(getL1FeeCalldata), rpcElements[1].Args[0].(map[string]interface{})["data"]) +func TestOPL1Oracle_CalculateFjordGasPrice(t *testing.T) { + baseFee := big.NewInt(100000000) + blobBaseFee := big.NewInt(25000000) + baseFeeScalar := big.NewInt(10) + blobBaseFeeScalar := big.NewInt(5) + decimals := big.NewInt(6) + oracleAddress := common.HexToAddress("0x1234").String() - res1 := common.BigToHash(big.NewInt(1)).Hex() - res2 := common.BigToHash(l1BaseFee).Hex() - rpcElements[0].Result = &res1 - rpcElements[1].Result = &res2 - }).Return(nil).Once() + t.Parallel() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + t.Run("correctly fetches gas price if chain has upgraded to Fjord", func(t *testing.T) { + ethClient := setupUpgradeCheck(t, oracleAddress, true, true) + mockBatchContractCall(t, ethClient, oracleAddress, baseFee, baseFeeScalar, blobBaseFee, blobBaseFeeScalar, decimals) + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + require.NoError(t, err) gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) require.NoError(t, err) - assert.Equal(t, l1BaseFee, gasPrice) + scaledGasPrice := big.NewInt(16125000000) // baseFee * scalar * 16 + blobBaseFee * scalar + scale := big.NewInt(16000000) // Scaled by 16 * 10 ^ decimals + expectedGasPrice := new(big.Int).Div(scaledGasPrice, scale) + assert.Equal(t, expectedGasPrice, gasPrice) }) - t.Run("fetching Ecotone price but rpc returns bad data", func(t *testing.T) { - ethClient := setupIsEcotone(t, oracleAddress) + t.Run("fetching Fjord price but rpc returns bad data", func(t *testing.T) { + ethClient := setupUpgradeCheck(t, oracleAddress, true, true) ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { rpcElements := args.Get(1).([]rpc.BatchElem) var badData = "zzz" @@ -170,31 +307,34 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { rpcElements[1].Result = &badData }).Return(nil).Once() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) - _, err := oracle.GetDAGasPrice(tests.Context(t)) + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) }) - t.Run("fetching Ecotone price but rpc parent call errors", func(t *testing.T) { - ethClient := setupIsEcotone(t, oracleAddress) + t.Run("fetching Fjord price but rpc parent call errors", func(t *testing.T) { + ethClient := setupUpgradeCheck(t, oracleAddress, true, true) ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) - _, err := oracle.GetDAGasPrice(tests.Context(t)) + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) }) - t.Run("fetching Ecotone price but one of the sub rpc call errors", func(t *testing.T) { - ethClient := setupIsEcotone(t, oracleAddress) + t.Run("fetching Fjord price but one of the sub rpc call errors", func(t *testing.T) { + ethClient := setupUpgradeCheck(t, oracleAddress, true, true) 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() + res := common.BigToHash(baseFee).Hex() rpcElements[0].Result = &res rpcElements[1].Error = fmt.Errorf("revert") }).Return(nil).Once() - oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) - _, err := oracle.GetDAGasPrice(tests.Context(t)) + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, oracleAddress) + require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) assert.Error(t, err) }) } diff --git a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go index 00ee91b3f8..2517bd5edf 100644 --- a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go +++ b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go @@ -185,7 +185,7 @@ func (o *zkSyncL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, er func (o *zkSyncL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { //Unused method, so not implemented // And its not possible to know gas consumption of a transaction before its executed, since zkSync only posts the state difference - panic("unimplemented") + return nil, fmt.Errorf("unimplemented") } // GetL2GasPrice calls SystemContract.gasPrice() on the zksync system precompile contract. diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 4e187571e5..8427170f1a 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -97,7 +97,8 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore) require.NoError(t, err) @@ -122,7 +123,8 @@ func TestTxm_CreateTransaction(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth()) require.NoError(t, err) @@ -403,7 +405,8 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), etKeyStore) require.NoError(t, err) @@ -494,7 +497,8 @@ func TestTxm_Lifecycle(t *testing.T) { keyChangeCh := make(chan struct{}) unsub := cltest.NewAwaiter() kst.On("SubscribeToKeyChanges", mock.Anything).Return(keyChangeCh, unsub.ItHappened) - estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) + require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst) require.NoError(t, err) @@ -549,7 +553,8 @@ func TestTxm_Reset(t *testing.T) { ethClient.On("PendingNonceAt", mock.Anything, addr).Return(uint64(128), nil).Maybe() ethClient.On("PendingNonceAt", mock.Anything, addr2).Return(uint64(44), nil).Maybe() - estimator := gas.NewEstimator(logger.Test(t), ethClient, cfg.EVM(), cfg.EVM().GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, cfg.EVM(), cfg.EVM().GasEstimator()) + require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), gcfg.Database(), gcfg.Database().Listener(), kst.Eth()) require.NoError(t, err) diff --git a/core/chains/legacyevm/evm_txm.go b/core/chains/legacyevm/evm_txm.go index df1f4248ce..cecfd4ffaf 100644 --- a/core/chains/legacyevm/evm_txm.go +++ b/core/chains/legacyevm/evm_txm.go @@ -43,7 +43,9 @@ func newEvmTxm( // build estimator from factory if opts.GenGasEstimator == nil { - estimator = gas.NewEstimator(lggr, client, cfg, cfg.GasEstimator()) + if estimator, err = gas.NewEstimator(lggr, client, cfg, cfg.GasEstimator()); err != nil { + return nil, nil, fmt.Errorf("failed to initialize estimator: %w", err) + } } else { estimator = opts.GenGasEstimator(chainID) } diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index f17b4aafed..2be3f5bacb 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -36,7 +36,8 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) + 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, From 3f8c00a6f1884f765bbe9e4b70e0dc4fb94a0088 Mon Sep 17 00:00:00 2001 From: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com> Date: Fri, 28 Jun 2024 21:45:26 +0200 Subject: [PATCH 31/61] Feature/bci 2996 local finality violation (#13048) * implement RPCClient changes * simplify interception of RPC's view on chain * Remove redundant changes * remove redundant changes * do not pick RPC as active if it's lagging on finalized block * fix race * minor refactor * Added FinalizedBlockOffset to config * HeadTracker support of FinalizedBlockOffset * fix lint issues * switch logpoller to head tracker * remove redundant changes * fix build * Capture latest chain info on RPC level to avoid race on state transition if we are communicating with RPC with highest finalized block * EnforceRepeatableRead config option * ensure HeadTracked does not miss block if it's committed between initialHead processing and subscription * hot fix flakey test * fix build & changeset * remove outdated test * fix headtracker tests * use polling in head tracker to get latest finalized block * fix relay * regen mocks * use proper context in the LogPoller's latestBlocks * fix flaky test * fixes for changes from develop branch * replace panic with FailNow * report dead node only if it's dead for long enough * fix racy test * rollback foundry change caused by merge with develop * use active node as source of HighestChainInfo to reduce number of transitions to nodeStateFinalizedBlockOutOfSync * optimised loading of latest finalized block * fix merge conflicts * make generate * simplify capturing of app layer observations * ensure logpoller is not affected by FinalityTagBypass * fix comment * reset keystone to develop * reset keystone * reset to develop * ungoimport * move newChainIDSubForwarder into the test * fix typo * Move deathDeclarationDelay to config * Comments adjustments * fix merge issues * regen mocks * fix multinode flaky test * refactor SetTotalDifficultyIfGt to MaxTotalDifficulty * Use softer language in LatestFinalizedBlock comments Co-authored-by: Dimitris Grigoriou * nits * Ensure HistoryDepth is >= FinalizedBlockOffset * regen mocks with newer version --------- Co-authored-by: Dimitris Grigoriou Co-authored-by: Domino Valdano --- .changeset/dull-ants-collect.md | 9 + common/client/ctx.go | 17 + common/client/ctx_test.go | 16 + common/client/mock_node_client_test.go | 51 ++- common/client/mock_node_test.go | 48 ++- .../mock_pool_chain_info_provider_test.go | 70 ++++ common/client/mock_rpc_test.go | 51 ++- common/client/mocks/config.go | 11 +- common/client/multi_node.go | 164 +++++--- common/client/multi_node_test.go | 147 +++++-- common/client/node.go | 47 ++- common/client/node_fsm.go | 54 ++- common/client/node_lifecycle.go | 137 +++---- common/client/node_lifecycle_test.go | 253 ++++++++---- common/client/node_selector_highest_head.go | 3 +- .../client/node_selector_highest_head_test.go | 40 +- .../client/node_selector_total_difficulty.go | 3 +- .../node_selector_total_difficulty_test.go | 42 +- common/client/node_test.go | 10 + common/client/types.go | 50 ++- common/client/types_test.go | 34 ++ common/headtracker/head_listener.go | 6 +- common/headtracker/head_tracker.go | 104 +++-- common/headtracker/mocks/head_tracker.go | 45 ++- common/headtracker/types/config.go | 1 + common/types/head.go | 3 + common/types/mocks/head.go | 30 ++ core/chains/evm/client/chain_client.go | 12 +- core/chains/evm/client/chain_client_test.go | 3 +- core/chains/evm/client/chain_id_sub_test.go | 105 ----- core/chains/evm/client/config_builder.go | 26 +- core/chains/evm/client/config_builder_test.go | 9 +- core/chains/evm/client/evm_client.go | 2 +- core/chains/evm/client/evm_client_test.go | 6 +- core/chains/evm/client/helpers_test.go | 16 +- core/chains/evm/client/mocks/rpc_client.go | 81 ++-- core/chains/evm/client/rpc_client.go | 165 ++++++-- core/chains/evm/client/rpc_client_test.go | 300 ++++++++++++++ core/chains/evm/client/sub_error_wrapper.go | 77 ---- .../evm/client/sub_error_wrapper_test.go | 74 ---- .../{chain_id_sub.go => sub_forwarder.go} | 51 +-- core/chains/evm/client/sub_forwarder_test.go | 190 +++++++++ core/chains/evm/config/chain_scoped.go | 4 + .../evm/config/chain_scoped_node_pool.go | 10 +- core/chains/evm/config/config.go | 3 + core/chains/evm/config/config_test.go | 2 + core/chains/evm/config/toml/config.go | 16 + core/chains/evm/config/toml/defaults.go | 3 + .../evm/config/toml/defaults/fallback.toml | 3 + .../evm/forwarders/forwarder_manager_test.go | 10 +- .../evm/headtracker/head_broadcaster_test.go | 3 +- .../evm/headtracker/head_listener_test.go | 6 +- .../chains/evm/headtracker/head_saver_test.go | 5 + core/chains/evm/headtracker/head_tracker.go | 5 +- .../evm/headtracker/head_tracker_test.go | 368 ++++++++++++++---- .../evm/headtracker/simulated_head_tracker.go | 53 +++ core/chains/evm/logpoller/helper_test.go | 4 +- core/chains/evm/logpoller/log_poller.go | 44 +-- .../evm/logpoller/log_poller_internal_test.go | 117 ++---- core/chains/evm/logpoller/log_poller_test.go | 24 +- core/chains/evm/txmgr/txmgr_test.go | 5 +- core/chains/evm/types/models.go | 19 +- core/chains/evm/types/models_test.go | 20 + core/chains/legacyevm/chain.go | 2 +- core/config/docs/chains-evm.toml | 24 +- core/services/chainlink/config_test.go | 14 +- .../chainlink/testdata/config-full.toml | 3 + .../chainlink/testdata/config-invalid.toml | 1 + .../config-multi-chain-effective.toml | 9 + .../testdata/config-multi-chain.toml | 1 + ...annel_definition_cache_integration_test.go | 10 +- .../v21/logprovider/integration_test.go | 8 +- .../promreporter/prom_reporter_test.go | 4 +- core/services/registrysyncer/syncer_test.go | 7 +- core/services/relay/evm/config_poller_test.go | 4 +- .../chain_reader_interface_tester.go | 4 +- .../relay/evm/functions/config_poller_test.go | 4 +- .../relay/evm/mercury/helpers_test.go | 4 +- .../vrf/v2/listener_v2_log_listener_test.go | 4 +- core/web/resolver/testdata/config-full.toml | 3 + .../config-multi-chain-effective.toml | 9 + .../resolver/testdata/config-multi-chain.toml | 1 + docs/CONFIG.md | 214 ++++++++++ .../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 + 88 files changed, 2654 insertions(+), 978 deletions(-) create mode 100644 .changeset/dull-ants-collect.md create mode 100644 common/client/ctx.go create mode 100644 common/client/ctx_test.go create mode 100644 common/client/mock_pool_chain_info_provider_test.go create mode 100644 common/client/types_test.go delete mode 100644 core/chains/evm/client/chain_id_sub_test.go create mode 100644 core/chains/evm/client/rpc_client_test.go delete mode 100644 core/chains/evm/client/sub_error_wrapper.go delete mode 100644 core/chains/evm/client/sub_error_wrapper_test.go rename core/chains/evm/client/{chain_id_sub.go => sub_forwarder.go} (51%) create mode 100644 core/chains/evm/client/sub_forwarder_test.go create mode 100644 core/chains/evm/headtracker/simulated_head_tracker.go diff --git a/.changeset/dull-ants-collect.md b/.changeset/dull-ants-collect.md new file mode 100644 index 0000000000..78f608e341 --- /dev/null +++ b/.changeset/dull-ants-collect.md @@ -0,0 +1,9 @@ +--- +"chainlink": patch +--- + +Fixed local finality violation caused by an RPC lagging behind on latest finalized block. + +Added `EVM.FinalizedBlockOffset` and `EVM.NodePool.EnforceRepeatableRead` config options. +With `EnforceRepeatableRead = true`, RPC is considered healthy only if its most recent finalized block is larger or equal to the highest finalized block observed by the Node minus `FinalizedBlockOffset`. +#bugfix diff --git a/common/client/ctx.go b/common/client/ctx.go new file mode 100644 index 0000000000..57b2fc8a86 --- /dev/null +++ b/common/client/ctx.go @@ -0,0 +1,17 @@ +package client + +import "context" + +type multiNodeContextKey int + +const ( + contextKeyHeathCheckRequest multiNodeContextKey = iota + 1 +) + +func CtxAddHealthCheckFlag(ctx context.Context) context.Context { + return context.WithValue(ctx, contextKeyHeathCheckRequest, struct{}{}) +} + +func CtxIsHeathCheckRequest(ctx context.Context) bool { + return ctx.Value(contextKeyHeathCheckRequest) != nil +} diff --git a/common/client/ctx_test.go b/common/client/ctx_test.go new file mode 100644 index 0000000000..822b36c3f8 --- /dev/null +++ b/common/client/ctx_test.go @@ -0,0 +1,16 @@ +package client + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" +) + +func TestContext(t *testing.T) { + ctx := tests.Context(t) + assert.False(t, CtxIsHeathCheckRequest(ctx), "expected false for test context") + ctx = CtxAddHealthCheckFlag(ctx) + assert.True(t, CtxIsHeathCheckRequest(ctx), "expected context to contain the healthcheck flag") +} diff --git a/common/client/mock_node_client_test.go b/common/client/mock_node_client_test.go index b9b9470de2..a7c0e4dbdb 100644 --- a/common/client/mock_node_client_test.go +++ b/common/client/mock_node_client_test.go @@ -116,6 +116,34 @@ func (_m *mockNodeClient[CHAIN_ID, HEAD]) DisconnectAll() { _m.Called() } +// GetInterceptedChainInfo provides a mock function with given fields: +func (_m *mockNodeClient[CHAIN_ID, HEAD]) GetInterceptedChainInfo() (ChainInfo, ChainInfo) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetInterceptedChainInfo") + } + + var r0 ChainInfo + var r1 ChainInfo + if rf, ok := ret.Get(0).(func() (ChainInfo, ChainInfo)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() ChainInfo); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(ChainInfo) + } + + if rf, ok := ret.Get(1).(func() ChainInfo); ok { + r1 = rf() + } else { + r1 = ret.Get(1).(ChainInfo) + } + + return r0, r1 +} + // IsSyncing provides a mock function with given fields: ctx func (_m *mockNodeClient[CHAIN_ID, HEAD]) IsSyncing(ctx context.Context) (bool, error) { ret := _m.Called(ctx) @@ -177,32 +205,29 @@ func (_m *mockNodeClient[CHAIN_ID, HEAD]) SetAliveLoopSub(_a0 types.Subscription _m.Called(_a0) } -// Subscribe provides a mock function with given fields: ctx, channel, args -func (_m *mockNodeClient[CHAIN_ID, HEAD]) Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (types.Subscription, error) { - var _ca []interface{} - _ca = append(_ca, ctx, channel) - _ca = append(_ca, args...) - ret := _m.Called(_ca...) +// SubscribeNewHead provides a mock function with given fields: ctx, channel +func (_m *mockNodeClient[CHAIN_ID, HEAD]) SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (types.Subscription, error) { + ret := _m.Called(ctx, channel) if len(ret) == 0 { - panic("no return value specified for Subscribe") + panic("no return value specified for SubscribeNewHead") } var r0 types.Subscription var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) (types.Subscription, error)); ok { - return rf(ctx, channel, args...) + if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) (types.Subscription, error)); ok { + return rf(ctx, channel) } - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) types.Subscription); ok { - r0 = rf(ctx, channel, args...) + if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) types.Subscription); ok { + r0 = rf(ctx, channel) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(types.Subscription) } } - if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD, ...interface{}) error); ok { - r1 = rf(ctx, channel, args...) + if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD) error); ok { + r1 = rf(ctx, channel) } else { r1 = ret.Error(1) } diff --git a/common/client/mock_node_test.go b/common/client/mock_node_test.go index 67ee5a4ba9..5109eb6bb9 100644 --- a/common/client/mock_node_test.go +++ b/common/client/mock_node_test.go @@ -4,11 +4,9 @@ package client import ( context "context" - big "math/big" - - mock "github.com/stretchr/testify/mock" types "github.com/smartcontractkit/chainlink/v2/common/types" + mock "github.com/stretchr/testify/mock" ) // mockNode is an autogenerated mock type for the Node type @@ -52,6 +50,24 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) ConfiguredChainID() CHAIN_ID { return r0 } +// HighestUserObservations provides a mock function with given fields: +func (_m *mockNode[CHAIN_ID, HEAD, RPC]) HighestUserObservations() ChainInfo { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HighestUserObservations") + } + + var r0 ChainInfo + if rf, ok := ret.Get(0).(func() ChainInfo); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(ChainInfo) + } + + return r0 +} + // Name provides a mock function with given fields: func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Name() string { ret := _m.Called() @@ -106,6 +122,11 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) RPC() RPC { return r0 } +// SetPoolChainInfoProvider provides a mock function with given fields: _a0 +func (_m *mockNode[CHAIN_ID, HEAD, RPC]) SetPoolChainInfoProvider(_a0 PoolChainInfoProvider) { + _m.Called(_a0) +} + // Start provides a mock function with given fields: _a0 func (_m *mockNode[CHAIN_ID, HEAD, RPC]) Start(_a0 context.Context) error { ret := _m.Called(_a0) @@ -143,7 +164,7 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) State() nodeState { } // StateAndLatest provides a mock function with given fields: -func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *big.Int) { +func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, ChainInfo) { ret := _m.Called() if len(ret) == 0 { @@ -151,9 +172,8 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *bi } var r0 nodeState - var r1 int64 - var r2 *big.Int - if rf, ok := ret.Get(0).(func() (nodeState, int64, *big.Int)); ok { + var r1 ChainInfo + if rf, ok := ret.Get(0).(func() (nodeState, ChainInfo)); ok { return rf() } if rf, ok := ret.Get(0).(func() nodeState); ok { @@ -162,21 +182,13 @@ func (_m *mockNode[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *bi r0 = ret.Get(0).(nodeState) } - if rf, ok := ret.Get(1).(func() int64); ok { + if rf, ok := ret.Get(1).(func() ChainInfo); ok { r1 = rf() } else { - r1 = ret.Get(1).(int64) - } - - if rf, ok := ret.Get(2).(func() *big.Int); ok { - r2 = rf() - } else { - if ret.Get(2) != nil { - r2 = ret.Get(2).(*big.Int) - } + r1 = ret.Get(1).(ChainInfo) } - return r0, r1, r2 + return r0, r1 } // String provides a mock function with given fields: diff --git a/common/client/mock_pool_chain_info_provider_test.go b/common/client/mock_pool_chain_info_provider_test.go new file mode 100644 index 0000000000..4e4955e738 --- /dev/null +++ b/common/client/mock_pool_chain_info_provider_test.go @@ -0,0 +1,70 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package client + +import mock "github.com/stretchr/testify/mock" + +// mockPoolChainInfoProvider is an autogenerated mock type for the PoolChainInfoProvider type +type mockPoolChainInfoProvider struct { + mock.Mock +} + +// HighestUserObservations provides a mock function with given fields: +func (_m *mockPoolChainInfoProvider) HighestUserObservations() ChainInfo { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HighestUserObservations") + } + + var r0 ChainInfo + if rf, ok := ret.Get(0).(func() ChainInfo); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(ChainInfo) + } + + return r0 +} + +// LatestChainInfo provides a mock function with given fields: +func (_m *mockPoolChainInfoProvider) LatestChainInfo() (int, ChainInfo) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for LatestChainInfo") + } + + var r0 int + var r1 ChainInfo + if rf, ok := ret.Get(0).(func() (int, ChainInfo)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + if rf, ok := ret.Get(1).(func() ChainInfo); ok { + r1 = rf() + } else { + r1 = ret.Get(1).(ChainInfo) + } + + return r0, r1 +} + +// newMockPoolChainInfoProvider creates a new instance of mockPoolChainInfoProvider. 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 newMockPoolChainInfoProvider(t interface { + mock.TestingT + Cleanup(func()) +}) *mockPoolChainInfoProvider { + mock := &mockPoolChainInfoProvider{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/common/client/mock_rpc_test.go b/common/client/mock_rpc_test.go index e3e7c59f2e..81bac04547 100644 --- a/common/client/mock_rpc_test.go +++ b/common/client/mock_rpc_test.go @@ -366,6 +366,34 @@ func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS return r0, r1 } +// GetInterceptedChainInfo provides a mock function with given fields: +func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) GetInterceptedChainInfo() (ChainInfo, ChainInfo) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetInterceptedChainInfo") + } + + var r0 ChainInfo + var r1 ChainInfo + if rf, ok := ret.Get(0).(func() (ChainInfo, ChainInfo)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() ChainInfo); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(ChainInfo) + } + + if rf, ok := ret.Get(1).(func() ChainInfo); ok { + r1 = rf() + } else { + r1 = ret.Get(1).(ChainInfo) + } + + return r0, r1 +} + // IsSyncing provides a mock function with given fields: ctx func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) IsSyncing(ctx context.Context) (bool, error) { ret := _m.Called(ctx) @@ -637,32 +665,29 @@ func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS return r0 } -// Subscribe provides a mock function with given fields: ctx, channel, args -func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (types.Subscription, error) { - var _ca []interface{} - _ca = append(_ca, ctx, channel) - _ca = append(_ca, args...) - ret := _m.Called(_ca...) +// SubscribeNewHead provides a mock function with given fields: ctx, channel +func (_m *mockRPC[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, BATCH_ELEM]) SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (types.Subscription, error) { + ret := _m.Called(ctx, channel) if len(ret) == 0 { - panic("no return value specified for Subscribe") + panic("no return value specified for SubscribeNewHead") } var r0 types.Subscription var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) (types.Subscription, error)); ok { - return rf(ctx, channel, args...) + if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) (types.Subscription, error)); ok { + return rf(ctx, channel) } - if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD, ...interface{}) types.Subscription); ok { - r0 = rf(ctx, channel, args...) + if rf, ok := ret.Get(0).(func(context.Context, chan<- HEAD) types.Subscription); ok { + r0 = rf(ctx, channel) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(types.Subscription) } } - if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD, ...interface{}) error); ok { - r1 = rf(ctx, channel, args...) + if rf, ok := ret.Get(1).(func(context.Context, chan<- HEAD) error); ok { + r1 = rf(ctx, channel) } else { r1 = ret.Error(1) } diff --git a/common/client/mocks/config.go b/common/client/mocks/config.go index 306965a9f5..d1007f39f0 100644 --- a/common/client/mocks/config.go +++ b/common/client/mocks/config.go @@ -3,9 +3,10 @@ package mocks import "time" type ChainConfig struct { - IsFinalityTagEnabled bool - FinalityDepthVal uint32 - NoNewHeadsThresholdVal time.Duration + IsFinalityTagEnabled bool + FinalityDepthVal uint32 + NoNewHeadsThresholdVal time.Duration + FinalizedBlockOffsetVal uint32 } func (t ChainConfig) NodeNoNewHeadsThreshold() time.Duration { @@ -19,3 +20,7 @@ func (t ChainConfig) FinalityDepth() uint32 { func (t ChainConfig) FinalityTagEnabled() bool { return t.IsFinalityTagEnabled } + +func (t ChainConfig) FinalizedBlockOffset() uint32 { + return t.FinalizedBlockOffsetVal +} diff --git a/common/client/multi_node.go b/common/client/multi_node.go index 0fc095c293..c53e5d33b7 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -90,18 +90,19 @@ type multiNode[ BATCH_ELEM any, ] struct { services.StateMachine - nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT] - sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT] - chainID CHAIN_ID - lggr logger.SugaredLogger - selectionMode string - noNewHeadsThreshold time.Duration - nodeSelector NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT] - leaseDuration time.Duration - leaseTicker *time.Ticker - chainFamily string - reportInterval time.Duration - sendTxSoftTimeout time.Duration // defines max waiting time from first response til responses evaluation + nodes []Node[CHAIN_ID, HEAD, RPC_CLIENT] + sendonlys []SendOnlyNode[CHAIN_ID, RPC_CLIENT] + chainID CHAIN_ID + lggr logger.SugaredLogger + selectionMode string + noNewHeadsThreshold time.Duration + nodeSelector NodeSelector[CHAIN_ID, HEAD, RPC_CLIENT] + leaseDuration time.Duration + leaseTicker *time.Ticker + chainFamily string + reportInterval time.Duration + deathDeclarationDelay time.Duration + sendTxSoftTimeout time.Duration // defines max waiting time from first response til responses evaluation activeMu sync.RWMutex activeNode Node[CHAIN_ID, HEAD, RPC_CLIENT] @@ -137,6 +138,7 @@ func NewMultiNode[ chainFamily string, classifySendTxError func(tx TX, err error) SendTxReturnCode, sendTxSoftTimeout time.Duration, + deathDeclarationDelay time.Duration, ) MultiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM] { nodeSelector := newNodeSelector(selectionMode, nodes) // Prometheus' default interval is 15s, set this to under 7.5s to avoid @@ -146,19 +148,20 @@ func NewMultiNode[ sendTxSoftTimeout = QueryTimeout / 2 } c := &multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]{ - nodes: nodes, - sendonlys: sendonlys, - chainID: chainID, - lggr: logger.Sugared(lggr).Named("MultiNode").With("chainID", chainID.String()), - selectionMode: selectionMode, - noNewHeadsThreshold: noNewHeadsThreshold, - nodeSelector: nodeSelector, - chStop: make(services.StopChan), - leaseDuration: leaseDuration, - chainFamily: chainFamily, - classifySendTxError: classifySendTxError, - reportInterval: reportInterval, - sendTxSoftTimeout: sendTxSoftTimeout, + nodes: nodes, + sendonlys: sendonlys, + chainID: chainID, + lggr: logger.Sugared(lggr).Named("MultiNode").With("chainID", chainID.String()), + selectionMode: selectionMode, + noNewHeadsThreshold: noNewHeadsThreshold, + nodeSelector: nodeSelector, + chStop: make(services.StopChan), + leaseDuration: leaseDuration, + chainFamily: chainFamily, + classifySendTxError: classifySendTxError, + reportInterval: reportInterval, + deathDeclarationDelay: deathDeclarationDelay, + sendTxSoftTimeout: sendTxSoftTimeout, } c.lggr.Debugf("The MultiNode is configured to use NodeSelectionMode: %s", selectionMode) @@ -180,14 +183,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP if n.ConfiguredChainID().String() != c.chainID.String() { return ms.CloseBecause(fmt.Errorf("node %s has configured chain ID %s which does not match multinode configured chain ID of %s", n.String(), n.ConfiguredChainID().String(), c.chainID.String())) } - rawNode, ok := n.(*node[CHAIN_ID, HEAD, RPC_CLIENT]) - if ok { - // This is a bit hacky but it allows the node to be aware of - // pool state and prevent certain state transitions that might - // otherwise leave no nodes available. It is better to have one - // node in a degraded state than no nodes at all. - rawNode.nLiveNodes = c.nLiveNodes - } + n.SetPoolChainInfoProvider(c) // node will handle its own redialing and automatic recovery if err := ms.Start(ctx, n); err != nil { return err @@ -253,6 +249,9 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return // another goroutine beat us here } + if c.activeNode != nil { + c.activeNode.UnsubscribeAllExceptAliveLoop() + } c.activeNode = c.nodeSelector.Select() if c.activeNode == nil { @@ -265,22 +264,37 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return c.activeNode, err } -// nLiveNodes returns the number of currently alive nodes, as well as the highest block number and greatest total difficulty. -// totalDifficulty will be 0 if all nodes return nil. -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) nLiveNodes() (nLiveNodes int, blockNumber int64, totalDifficulty *big.Int) { - totalDifficulty = big.NewInt(0) +// LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being marked as out-of-sync. +// Return highest ChainInfo most recently received by the alive nodes. +// E.g. If Node A's the most recent block is 10 and highest 15 and for Node B it's - 12 and 14. This method will return 12. +func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) LatestChainInfo() (int, ChainInfo) { + var nLiveNodes int + ch := ChainInfo{ + TotalDifficulty: big.NewInt(0), + } for _, n := range c.nodes { - if s, num, td := n.StateAndLatest(); s == nodeStateAlive { + if s, nodeChainInfo := n.StateAndLatest(); s == nodeStateAlive { nLiveNodes++ - if num > blockNumber { - blockNumber = num - } - if td != nil && td.Cmp(totalDifficulty) > 0 { - totalDifficulty = td - } + ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) + ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber) + ch.TotalDifficulty = MaxTotalDifficulty(ch.TotalDifficulty, nodeChainInfo.TotalDifficulty) } } - return + return nLiveNodes, ch +} + +// HighestUserObservations - returns highest ChainInfo ever observed by any user of the MultiNode +func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) HighestUserObservations() ChainInfo { + ch := ChainInfo{ + TotalDifficulty: big.NewInt(0), + } + for _, n := range c.nodes { + nodeChainInfo := n.HighestUserObservations() + ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) + ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber) + ch.TotalDifficulty = MaxTotalDifficulty(ch.TotalDifficulty, nodeChainInfo.TotalDifficulty) + } + return ch } func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) checkLease() { @@ -295,10 +309,13 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } c.activeMu.Lock() + defer c.activeMu.Unlock() if bestNode != c.activeNode { + if c.activeNode != nil { + c.activeNode.UnsubscribeAllExceptAliveLoop() + } c.activeNode = bestNode } - c.activeMu.Unlock() } func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) checkLeaseLoop() { @@ -319,7 +336,16 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) runLoop() { defer c.wg.Done() - c.report() + nodeStates := make([]nodeWithState, len(c.nodes)) + for i, n := range c.nodes { + nodeStates[i] = nodeWithState{ + Node: n.String(), + State: n.State().String(), + DeadSince: nil, + } + } + + c.report(nodeStates) monitor := time.NewTicker(utils.WithJitter(c.reportInterval)) defer monitor.Stop() @@ -327,44 +353,54 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP for { select { case <-monitor.C: - c.report() + c.report(nodeStates) case <-c.chStop: return } } } -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) report() { - type nodeWithState struct { - Node string - State string - } +type nodeWithState struct { + Node string + State string + DeadSince *time.Time +} - var total, dead int +func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) report(nodesStateInfo []nodeWithState) { + start := time.Now() + var dead int counts := make(map[nodeState]int) - nodeStates := make([]nodeWithState, len(c.nodes)) for i, n := range c.nodes { state := n.State() - nodeStates[i] = nodeWithState{n.String(), state.String()} - total++ - if state != nodeStateAlive { + counts[state]++ + nodesStateInfo[i].State = state.String() + if state == nodeStateAlive { + nodesStateInfo[i].DeadSince = nil + continue + } + + if nodesStateInfo[i].DeadSince == nil { + nodesStateInfo[i].DeadSince = &start + } + + if start.Sub(*nodesStateInfo[i].DeadSince) >= c.deathDeclarationDelay { dead++ } - counts[state]++ } for _, state := range allNodeStates { count := counts[state] PromMultiNodeRPCNodeStates.WithLabelValues(c.chainFamily, c.chainID.String(), state.String()).Set(float64(count)) } + total := len(c.nodes) live := total - dead - c.lggr.Tracew(fmt.Sprintf("MultiNode state: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) + c.lggr.Tracew(fmt.Sprintf("MultiNode state: %d/%d nodes are alive", live, total), "nodeStates", nodesStateInfo) if total == dead { rerr := fmt.Errorf("no primary nodes available: 0/%d nodes are alive", total) - c.lggr.Criticalw(rerr.Error(), "nodeStates", nodeStates) + c.lggr.Criticalw(rerr.Error(), "nodeStates", nodesStateInfo) c.SvcErrBuffer.Append(rerr) } else if dead > 0 { - c.lggr.Errorw(fmt.Sprintf("At least one primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodeStates) + c.lggr.Errorw(fmt.Sprintf("At least one primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodesStateInfo) } } @@ -779,12 +815,12 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return n.RPC().SimulateTransaction(ctx, tx) } -func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (s types.Subscription, err error) { +func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (s types.Subscription, err error) { n, err := c.selectNode() if err != nil { return s, err } - return n.RPC().Subscribe(ctx, channel, args...) + return n.RPC().SubscribeNewHead(ctx, channel) } func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) TokenBalance(ctx context.Context, account ADDR, tokenAddr ADDR) (b *big.Int, err error) { diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 3076d99b61..ffef0c29d5 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -29,16 +29,17 @@ type testMultiNode struct { } type multiNodeOpts struct { - logger logger.Logger - selectionMode string - leaseDuration time.Duration - noNewHeadsThreshold time.Duration - nodes []Node[types.ID, types.Head[Hashable], multiNodeRPCClient] - sendonlys []SendOnlyNode[types.ID, multiNodeRPCClient] - chainID types.ID - chainFamily string - classifySendTxError func(tx any, err error) SendTxReturnCode - sendTxSoftTimeout time.Duration + logger logger.Logger + selectionMode string + leaseDuration time.Duration + noNewHeadsThreshold time.Duration + nodes []Node[types.ID, types.Head[Hashable], multiNodeRPCClient] + sendonlys []SendOnlyNode[types.ID, multiNodeRPCClient] + chainID types.ID + chainFamily string + classifySendTxError func(tx any, err error) SendTxReturnCode + sendTxSoftTimeout time.Duration + deathDeclarationDelay time.Duration } func newTestMultiNode(t *testing.T, opts multiNodeOpts) testMultiNode { @@ -49,7 +50,7 @@ func newTestMultiNode(t *testing.T, opts multiNodeOpts) testMultiNode { result := NewMultiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient, any](opts.logger, opts.selectionMode, opts.leaseDuration, opts.noNewHeadsThreshold, opts.nodes, opts.sendonlys, - opts.chainID, opts.chainFamily, opts.classifySendTxError, opts.sendTxSoftTimeout) + opts.chainID, opts.chainFamily, opts.classifySendTxError, opts.sendTxSoftTimeout, opts.deathDeclarationDelay) return testMultiNode{ result.(*multiNode[types.ID, *big.Int, Hashable, Hashable, any, Hashable, any, any, types.Receipt[Hashable, Hashable], Hashable, types.Head[Hashable], multiNodeRPCClient, any]), @@ -67,14 +68,21 @@ func newHealthyNode(t *testing.T, chainID types.ID) *mockNode[types.ID, types.He } func newNodeWithState(t *testing.T, chainID types.ID, state nodeState) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] { + node := newDialableNode(t, chainID) + node.On("State").Return(state).Maybe() + return node +} + +func newDialableNode(t *testing.T, chainID types.ID) *mockNode[types.ID, types.Head[Hashable], multiNodeRPCClient] { node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) node.On("ConfiguredChainID").Return(chainID).Once() node.On("Start", mock.Anything).Return(nil).Once() node.On("Close").Return(nil).Once() - node.On("State").Return(state).Maybe() node.On("String").Return(fmt.Sprintf("healthy_node_%d", rand.Int())).Maybe() + node.On("SetPoolChainInfoProvider", mock.Anything).Once() return node } + func TestMultiNode_Dial(t *testing.T) { t.Parallel() @@ -111,6 +119,7 @@ func TestMultiNode_Dial(t *testing.T) { node := newMockNode(t) chainID := types.RandomID() node.On("ConfiguredChainID").Return(chainID).Once() + node.On("SetPoolChainInfoProvider", mock.Anything).Once() expectedError := errors.New("failed to start node") node.On("Start", mock.Anything).Return(expectedError).Once() mn := newTestMultiNode(t, multiNodeOpts{ @@ -128,6 +137,7 @@ func TestMultiNode_Dial(t *testing.T) { node1 := newHealthyNode(t, chainID) node2 := newMockNode(t) node2.On("ConfiguredChainID").Return(chainID).Once() + node2.On("SetPoolChainInfoProvider", mock.Anything).Once() expectedError := errors.New("failed to start node") node2.On("Start", mock.Anything).Return(expectedError).Once() @@ -219,6 +229,7 @@ func TestMultiNode_Report(t *testing.T) { logger: lggr, }) mn.reportInterval = tests.TestInterval + mn.deathDeclarationDelay = tests.TestInterval defer func() { assert.NoError(t, mn.Close()) }() err := mn.Dial(tests.Context(t)) require.NoError(t, err) @@ -236,6 +247,7 @@ func TestMultiNode_Report(t *testing.T) { logger: lggr, }) mn.reportInterval = tests.TestInterval + mn.deathDeclarationDelay = tests.TestInterval defer func() { assert.NoError(t, mn.Close()) }() err := mn.Dial(tests.Context(t)) require.NoError(t, err) @@ -377,6 +389,7 @@ func TestMultiNode_selectNode(t *testing.T) { chainID := types.RandomID() oldBest := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) oldBest.On("String").Return("oldBest").Maybe() + oldBest.On("UnsubscribeAllExceptAliveLoop").Once() newBest := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) newBest.On("String").Return("newBest").Maybe() mn := newTestMultiNode(t, multiNodeOpts{ @@ -417,49 +430,94 @@ func TestMultiNode_selectNode(t *testing.T) { }) } -func TestMultiNode_nLiveNodes(t *testing.T) { +func TestMultiNode_ChainInfo(t *testing.T) { t.Parallel() type nodeParams struct { - BlockNumber int64 - TotalDifficulty *big.Int - State nodeState + LatestChainInfo ChainInfo + HighestUserObservations ChainInfo + State nodeState } testCases := []struct { - Name string - ExpectedNLiveNodes int - ExpectedBlockNumber int64 - ExpectedTotalDifficulty *big.Int - NodeParams []nodeParams + Name string + ExpectedNLiveNodes int + ExpectedLatestChainInfo ChainInfo + ExpectedHighestUserObservations ChainInfo + NodeParams []nodeParams }{ { - Name: "no nodes", - ExpectedTotalDifficulty: big.NewInt(0), + Name: "no nodes", + ExpectedLatestChainInfo: ChainInfo{ + TotalDifficulty: big.NewInt(0), + }, + ExpectedHighestUserObservations: ChainInfo{ + TotalDifficulty: big.NewInt(0), + }, }, { - Name: "Best node is not healthy", - ExpectedTotalDifficulty: big.NewInt(10), - ExpectedBlockNumber: 20, - ExpectedNLiveNodes: 3, + Name: "Best node is not healthy", + ExpectedNLiveNodes: 3, + ExpectedLatestChainInfo: ChainInfo{ + BlockNumber: 20, + FinalizedBlockNumber: 10, + TotalDifficulty: big.NewInt(10), + }, + ExpectedHighestUserObservations: ChainInfo{ + BlockNumber: 1005, + FinalizedBlockNumber: 995, + TotalDifficulty: big.NewInt(2005), + }, NodeParams: []nodeParams{ { - State: nodeStateOutOfSync, - BlockNumber: 1000, - TotalDifficulty: big.NewInt(2000), + State: nodeStateOutOfSync, + LatestChainInfo: ChainInfo{ + BlockNumber: 1000, + FinalizedBlockNumber: 990, + TotalDifficulty: big.NewInt(2000), + }, + HighestUserObservations: ChainInfo{ + BlockNumber: 1005, + FinalizedBlockNumber: 995, + TotalDifficulty: big.NewInt(2005), + }, }, { - State: nodeStateAlive, - BlockNumber: 20, - TotalDifficulty: big.NewInt(9), + State: nodeStateAlive, + LatestChainInfo: ChainInfo{ + BlockNumber: 20, + FinalizedBlockNumber: 10, + TotalDifficulty: big.NewInt(9), + }, + HighestUserObservations: ChainInfo{ + BlockNumber: 25, + FinalizedBlockNumber: 15, + TotalDifficulty: big.NewInt(14), + }, }, { - State: nodeStateAlive, - BlockNumber: 19, - TotalDifficulty: big.NewInt(10), + State: nodeStateAlive, + LatestChainInfo: ChainInfo{ + BlockNumber: 19, + FinalizedBlockNumber: 9, + TotalDifficulty: big.NewInt(10), + }, + HighestUserObservations: ChainInfo{ + BlockNumber: 24, + FinalizedBlockNumber: 14, + TotalDifficulty: big.NewInt(15), + }, }, { - State: nodeStateAlive, - BlockNumber: 11, - TotalDifficulty: nil, + State: nodeStateAlive, + LatestChainInfo: ChainInfo{ + BlockNumber: 11, + FinalizedBlockNumber: 1, + TotalDifficulty: nil, + }, + HighestUserObservations: ChainInfo{ + BlockNumber: 16, + FinalizedBlockNumber: 6, + TotalDifficulty: nil, + }, }, }, }, @@ -475,14 +533,17 @@ func TestMultiNode_nLiveNodes(t *testing.T) { t.Run(tc.Name, func(t *testing.T) { for _, params := range tc.NodeParams { node := newMockNode[types.ID, types.Head[Hashable], multiNodeRPCClient](t) - node.On("StateAndLatest").Return(params.State, params.BlockNumber, params.TotalDifficulty) + node.On("StateAndLatest").Return(params.State, params.LatestChainInfo) + node.On("HighestUserObservations").Return(params.HighestUserObservations) mn.nodes = append(mn.nodes, node) } - nNodes, blockNum, td := mn.nLiveNodes() + nNodes, latestChainInfo := mn.LatestChainInfo() assert.Equal(t, tc.ExpectedNLiveNodes, nNodes) - assert.Equal(t, tc.ExpectedTotalDifficulty, td) - assert.Equal(t, tc.ExpectedBlockNumber, blockNum) + assert.Equal(t, tc.ExpectedLatestChainInfo, latestChainInfo) + + highestChainInfo := mn.HighestUserObservations() + assert.Equal(t, tc.ExpectedHighestUserObservations, highestChainInfo) }) } } diff --git a/common/client/node.go b/common/client/node.go index 869ea89c03..7871c622eb 100644 --- a/common/client/node.go +++ b/common/client/node.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "math/big" "net/url" "sync" "time" @@ -44,12 +43,15 @@ type NodeConfig interface { SyncThreshold() uint32 NodeIsSyncingEnabled() bool FinalizedBlockPollInterval() time.Duration + EnforceRepeatableRead() bool + DeathDeclarationDelay() time.Duration } type ChainConfig interface { NodeNoNewHeadsThreshold() time.Duration FinalityDepth() uint32 FinalityTagEnabled() bool + FinalizedBlockOffset() uint32 } //go:generate mockery --quiet --name Node --structname mockNode --filename "mock_node_test.go" --inpackage --case=underscore @@ -58,15 +60,21 @@ type Node[ HEAD Head, RPC NodeClient[CHAIN_ID, HEAD], ] interface { - // State returns nodeState + // State returns most accurate state of the Node on the moment of call. + // While some of the checks may be performed in the background and State may return cached value, critical, like + // `FinalizedBlockOutOfSync`, must be executed upon every call. State() nodeState - // StateAndLatest returns nodeState with the latest received block number & total difficulty. - StateAndLatest() (nodeState, int64, *big.Int) + // StateAndLatest returns nodeState with the latest ChainInfo observed by Node during current lifecycle. + StateAndLatest() (nodeState, ChainInfo) + // HighestUserObservations - returns highest ChainInfo ever observed by underlying RPC excluding results of health check requests + HighestUserObservations() ChainInfo + SetPoolChainInfoProvider(PoolChainInfoProvider) // Name is a unique identifier for this node. Name() string String() string RPC() RPC SubscribersCount() int32 + // UnsubscribeAllExceptAliveLoop - closes all subscriptions except the aliveLoop subscription UnsubscribeAllExceptAliveLoop() ConfiguredChainID() CHAIN_ID Order() int32 @@ -96,20 +104,12 @@ type node[ stateMu sync.RWMutex // protects state* fields state nodeState - // Each node is tracking the last received head number and total difficulty - stateLatestBlockNumber int64 - stateLatestTotalDifficulty *big.Int - stateLatestFinalizedBlockNumber int64 + + poolInfoProvider PoolChainInfoProvider stopCh services.StopChan // wg waits for subsidiary goroutines wg sync.WaitGroup - - // nLiveNodes is a passed in function that allows this node to: - // 1. see how many live nodes there are in total, so we can prevent the last alive node in a pool from being - // moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all. - // 2. compare against the highest head (by number or difficulty) to ensure we don't fall behind too far. - nLiveNodes func() (count int, blockNumber int64, totalDifficulty *big.Int) } func NewNode[ @@ -150,7 +150,6 @@ func NewNode[ "nodeOrder", n.order, ) n.lfcLog = logger.Named(lggr, "Lifecycle") - n.stateLatestBlockNumber = -1 n.rpc = rpc n.chainFamily = chainFamily return n @@ -243,7 +242,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) verifyChainID(callerCtx context.Context, lgg promPoolRPCNodeVerifiesFailed.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc() } - st := n.State() + st := n.getCachedState() switch st { case nodeStateClosed: // The node is already closed, and any subsequent transition is invalid. @@ -258,7 +257,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) verifyChainID(callerCtx context.Context, lgg var err error if chainID, err = n.rpc.ChainID(callerCtx); err != nil { promFailed() - lggr.Errorw("Failed to verify chain ID for node", "err", err, "nodeState", n.State()) + lggr.Errorw("Failed to verify chain ID for node", "err", err, "nodeState", n.getCachedState()) return nodeStateUnreachable } else if chainID.String() != n.chainID.String() { promFailed() @@ -269,7 +268,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) verifyChainID(callerCtx context.Context, lgg n.name, errInvalidChainID, ) - lggr.Errorw("Failed to verify RPC node; remote endpoint returned the wrong chain ID", "err", err, "nodeState", n.State()) + lggr.Errorw("Failed to verify RPC node; remote endpoint returned the wrong chain ID", "err", err, "nodeState", n.getCachedState()) return nodeStateInvalidChainID } @@ -282,7 +281,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) verifyChainID(callerCtx context.Context, lgg // Returns desired state if one of the verifications fails. Otherwise, returns nodeStateAlive. func (n *node[CHAIN_ID, HEAD, RPC]) createVerifiedConn(ctx context.Context, lggr logger.Logger) nodeState { if err := n.rpc.Dial(ctx); err != nil { - n.lfcLog.Errorw("Dial failed: Node is unreachable", "err", err, "nodeState", n.State()) + n.lfcLog.Errorw("Dial failed: Node is unreachable", "err", err, "nodeState", n.getCachedState()) return nodeStateUnreachable } @@ -300,12 +299,12 @@ func (n *node[CHAIN_ID, HEAD, RPC]) verifyConn(ctx context.Context, lggr logger. if n.nodePoolCfg.NodeIsSyncingEnabled() { isSyncing, err := n.rpc.IsSyncing(ctx) if err != nil { - lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.State()) + lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.getCachedState()) return nodeStateUnreachable } if isSyncing { - lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.State()) + lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.getCachedState()) return nodeStateSyncing } } @@ -323,3 +322,9 @@ func (n *node[CHAIN_ID, HEAD, RPC]) disconnectAll() { func (n *node[CHAIN_ID, HEAD, RPC]) Order() int32 { return n.order } + +func (n *node[CHAIN_ID, HEAD, RPC]) newCtx() (context.Context, context.CancelFunc) { + ctx, cancel := n.stopCh.NewCtx() + ctx = CtxAddHealthCheckFlag(ctx) + return ctx, cancel +} diff --git a/common/client/node_fsm.go b/common/client/node_fsm.go index e9105dcc06..5a5e255443 100644 --- a/common/client/node_fsm.go +++ b/common/client/node_fsm.go @@ -63,6 +63,8 @@ func (n nodeState) String() string { return "Closed" case nodeStateSyncing: return "Syncing" + case nodeStateFinalizedBlockOutOfSync: + return "FinalizedBlockOutOfSync" default: return fmt.Sprintf("nodeState(%d)", n) } @@ -98,6 +100,8 @@ const ( // to other primary nodes configured in the MultiNode. In contrast, `nodeStateSyncing` represents the internal state of // the node (RPC). nodeStateSyncing + // nodeStateFinalizedBlockOutOfSync - node is lagging behind on latest finalized block + nodeStateFinalizedBlockOutOfSync // nodeStateLen tracks the number of states nodeStateLen ) @@ -115,15 +119,59 @@ func init() { // State allows reading the current state of the node. func (n *node[CHAIN_ID, HEAD, RPC]) State() nodeState { + n.stateMu.RLock() + defer n.stateMu.RUnlock() + return n.recalculateState() +} + +func (n *node[CHAIN_ID, HEAD, RPC]) getCachedState() nodeState { n.stateMu.RLock() defer n.stateMu.RUnlock() return n.state } -func (n *node[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, int64, *big.Int) { +func (n *node[CHAIN_ID, HEAD, RPC]) recalculateState() nodeState { + if n.state != nodeStateAlive { + return n.state + } + + // double check that node is not lagging on finalized block + if n.nodePoolCfg.EnforceRepeatableRead() && n.isFinalizedBlockOutOfSync() { + return nodeStateFinalizedBlockOutOfSync + } + + return nodeStateAlive +} + +func (n *node[CHAIN_ID, HEAD, RPC]) isFinalizedBlockOutOfSync() bool { + if n.poolInfoProvider == nil { + return false + } + + highestObservedByCaller := n.poolInfoProvider.HighestUserObservations() + latest, _ := n.rpc.GetInterceptedChainInfo() + if n.chainCfg.FinalityTagEnabled() { + return latest.FinalizedBlockNumber < highestObservedByCaller.FinalizedBlockNumber-int64(n.chainCfg.FinalizedBlockOffset()) + } + + return latest.BlockNumber < highestObservedByCaller.BlockNumber-int64(n.chainCfg.FinalizedBlockOffset()) +} + +// StateAndLatest returns nodeState with the latest ChainInfo observed by Node during current lifecycle. +func (n *node[CHAIN_ID, HEAD, RPC]) StateAndLatest() (nodeState, ChainInfo) { n.stateMu.RLock() defer n.stateMu.RUnlock() - return n.state, n.stateLatestBlockNumber, n.stateLatestTotalDifficulty + latest, _ := n.rpc.GetInterceptedChainInfo() + return n.recalculateState(), latest +} + +// HighestUserObservations - returns highest ChainInfo ever observed by external user of the Node +func (n *node[CHAIN_ID, HEAD, RPC]) HighestUserObservations() ChainInfo { + _, highestUserObservations := n.rpc.GetInterceptedChainInfo() + return highestUserObservations +} +func (n *node[CHAIN_ID, HEAD, RPC]) SetPoolChainInfoProvider(poolInfoProvider PoolChainInfoProvider) { + n.poolInfoProvider = poolInfoProvider } // setState is only used by internal state management methods. @@ -243,7 +291,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) transitionToUnreachable(fn func()) { } func (n *node[CHAIN_ID, HEAD, RPC]) declareState(state nodeState) { - if n.State() == nodeStateClosed { + if n.getCachedState() == nodeStateClosed { return } switch state { diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index 5947774e20..39e17bb497 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -56,20 +56,11 @@ func zombieNodeCheckInterval(noNewHeadsThreshold time.Duration) time.Duration { return utils.WithJitter(interval) } -func (n *node[CHAIN_ID, HEAD, RPC]) setLatestReceived(blockNumber int64, totalDifficulty *big.Int) { - n.stateMu.Lock() - defer n.stateMu.Unlock() - n.stateLatestBlockNumber = blockNumber - n.stateLatestTotalDifficulty = totalDifficulty -} - const ( msgCannotDisable = "but cannot disable this connection because there are no other RPC endpoints, or all other RPC endpoints are dead." msgDegradedState = "Chainlink is now operating in a degraded state and urgent action is required to resolve the issue" ) -const rpcSubscriptionMethodNewHeads = "newHeads" - // Node is a FSM // Each state has a loop that goes with it, which monitors the node and moves it into another state as necessary. // Only one loop must run at a time. @@ -79,12 +70,12 @@ const rpcSubscriptionMethodNewHeads = "newHeads" // Should only be run ONCE per node, after a successful Dial func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { defer n.wg.Done() - ctx, cancel := n.stopCh.NewCtx() + ctx, cancel := n.newCtx() defer cancel() { // sanity check - state := n.State() + state := n.getCachedState() switch state { case nodeStateAlive: case nodeStateClosed: @@ -99,12 +90,12 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { pollInterval := n.nodePoolCfg.PollInterval() lggr := logger.Sugared(n.lfcLog).Named("Alive").With("noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold) - lggr.Tracew("Alive loop starting", "nodeState", n.State()) + lggr.Tracew("Alive loop starting", "nodeState", n.getCachedState()) headsC := make(chan HEAD) - sub, err := n.rpc.Subscribe(ctx, headsC, rpcSubscriptionMethodNewHeads) + sub, err := n.rpc.SubscribeNewHead(ctx, headsC) if err != nil { - lggr.Errorw("Initial subscribe for heads failed", "nodeState", n.State()) + lggr.Errorw("Initial subscribe for heads failed", "nodeState", n.getCachedState()) n.declareUnreachable() return } @@ -116,7 +107,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { var outOfSyncT *time.Ticker var outOfSyncTC <-chan time.Time if noNewHeadsTimeoutThreshold > 0 { - lggr.Debugw("Head liveness checking enabled", "nodeState", n.State()) + lggr.Debugw("Head liveness checking enabled", "nodeState", n.getCachedState()) outOfSyncT = time.NewTicker(noNewHeadsTimeoutThreshold) defer outOfSyncT.Stop() outOfSyncTC = outOfSyncT.C @@ -148,7 +139,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { pollFinalizedHeadCh = pollT.C } - _, highestReceivedBlockNumber, _ := n.StateAndLatest() + localHighestChainInfo, _ := n.rpc.GetInterceptedChainInfo() var pollFailures uint32 for { @@ -157,7 +148,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { return case <-pollCh: promPoolRPCNodePolls.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Tracew("Polling for version", "nodeState", n.State(), "pollFailures", pollFailures) + lggr.Tracew("Polling for version", "nodeState", n.getCachedState(), "pollFailures", pollFailures) version, err := func(ctx context.Context) (string, error) { ctx, cancel := context.WithTimeout(ctx, pollInterval) defer cancel() @@ -169,16 +160,16 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { promPoolRPCNodePollsFailed.WithLabelValues(n.chainID.String(), n.name).Inc() pollFailures++ } - lggr.Warnw(fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", n.String()), "err", err, "pollFailures", pollFailures, "nodeState", n.State()) + lggr.Warnw(fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", n.String()), "err", err, "pollFailures", pollFailures, "nodeState", n.getCachedState()) } else { - lggr.Debugw("Version poll successful", "nodeState", n.State(), "clientVersion", version) + lggr.Debugw("Version poll successful", "nodeState", n.getCachedState(), "clientVersion", version) promPoolRPCNodePollsSuccess.WithLabelValues(n.chainID.String(), n.name).Inc() pollFailures = 0 } if pollFailureThreshold > 0 && pollFailures >= pollFailureThreshold { - lggr.Errorw(fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailures), "pollFailures", pollFailures, "nodeState", n.State()) - if n.nLiveNodes != nil { - if l, _, _ := n.nLiveNodes(); l < 2 { + lggr.Errorw(fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailures), "pollFailures", pollFailures, "nodeState", n.getCachedState()) + if n.poolInfoProvider != nil { + if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { lggr.Criticalf("RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState) continue } @@ -186,10 +177,10 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { n.declareUnreachable() return } - _, num, td := n.StateAndLatest() - if outOfSync, liveNodes := n.syncStatus(num, td); outOfSync { + _, ci := n.StateAndLatest() + if outOfSync, liveNodes := n.syncStatus(ci.BlockNumber, ci.TotalDifficulty); outOfSync { // note: there must be another live node for us to be out of sync - lggr.Errorw("RPC endpoint has fallen behind", "blockNumber", num, "totalDifficulty", td, "nodeState", n.State()) + lggr.Errorw("RPC endpoint has fallen behind", "blockNumber", ci.BlockNumber, "totalDifficulty", ci.TotalDifficulty, "nodeState", n.getCachedState()) if liveNodes < 2 { lggr.Criticalf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) continue @@ -199,40 +190,39 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { } case bh, open := <-headsC: if !open { - lggr.Errorw("Subscription channel unexpectedly closed", "nodeState", n.State()) + lggr.Errorw("Subscription channel unexpectedly closed", "nodeState", n.getCachedState()) n.declareUnreachable() return } promPoolRPCNodeNumSeenBlocks.WithLabelValues(n.chainID.String(), n.name).Inc() lggr.Tracew("Got head", "head", bh) - if bh.BlockNumber() > highestReceivedBlockNumber { + if bh.BlockNumber() > localHighestChainInfo.BlockNumber { promPoolRPCNodeHighestSeenBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(bh.BlockNumber())) - lggr.Tracew("Got higher block number, resetting timer", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State()) - highestReceivedBlockNumber = bh.BlockNumber() + lggr.Tracew("Got higher block number, resetting timer", "latestReceivedBlockNumber", localHighestChainInfo.BlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.getCachedState()) + localHighestChainInfo.BlockNumber = bh.BlockNumber() } else { - lggr.Tracew("Ignoring previously seen block number", "latestReceivedBlockNumber", highestReceivedBlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.State()) + lggr.Tracew("Ignoring previously seen block number", "latestReceivedBlockNumber", localHighestChainInfo.BlockNumber, "blockNumber", bh.BlockNumber(), "nodeState", n.getCachedState()) } if outOfSyncT != nil { outOfSyncT.Reset(noNewHeadsTimeoutThreshold) } - n.setLatestReceived(bh.BlockNumber(), bh.BlockDifficulty()) if !n.chainCfg.FinalityTagEnabled() { latestFinalizedBN := max(bh.BlockNumber()-int64(n.chainCfg.FinalityDepth()), 0) - if latestFinalizedBN > n.stateLatestFinalizedBlockNumber { + if latestFinalizedBN > localHighestChainInfo.FinalizedBlockNumber { promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) - n.stateLatestFinalizedBlockNumber = latestFinalizedBN + localHighestChainInfo.FinalizedBlockNumber = latestFinalizedBN } } case err := <-sub.Err(): - lggr.Errorw("Subscription was terminated", "err", err, "nodeState", n.State()) + lggr.Errorw("Subscription was terminated", "err", err, "nodeState", n.getCachedState()) n.declareUnreachable() return case <-outOfSyncTC: // We haven't received a head on the channel for at least the // threshold amount of time, mark it broken - lggr.Errorw(fmt.Sprintf("RPC endpoint detected out of sync; no new heads received for %s (last head received was %v)", noNewHeadsTimeoutThreshold, highestReceivedBlockNumber), "nodeState", n.State(), "latestReceivedBlockNumber", highestReceivedBlockNumber, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold) - if n.nLiveNodes != nil { - if l, _, _ := n.nLiveNodes(); l < 2 { + lggr.Errorw(fmt.Sprintf("RPC endpoint detected out of sync; no new heads received for %s (last head received was %v)", noNewHeadsTimeoutThreshold, localHighestChainInfo.BlockNumber), "nodeState", n.getCachedState(), "latestReceivedBlockNumber", localHighestChainInfo.BlockNumber, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold) + if n.poolInfoProvider != nil { + if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { lggr.Criticalf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) // We don't necessarily want to wait the full timeout to check again, we should // check regularly and log noisily in this state @@ -240,7 +230,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { continue } } - n.declareOutOfSync(func(num int64, td *big.Int) bool { return num < highestReceivedBlockNumber }) + n.declareOutOfSync(func(num int64, td *big.Int) bool { return num < localHighestChainInfo.BlockNumber }) return case <-pollFinalizedHeadCh: latestFinalized, err := func(ctx context.Context) (HEAD, error) { @@ -259,9 +249,9 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { } latestFinalizedBN := latestFinalized.BlockNumber() - if latestFinalizedBN > n.stateLatestFinalizedBlockNumber { + if latestFinalizedBN > localHighestChainInfo.FinalizedBlockNumber { promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) - n.stateLatestFinalizedBlockNumber = latestFinalizedBN + localHighestChainInfo.FinalizedBlockNumber = latestFinalizedBN } } } @@ -276,7 +266,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSync(num int64, td *big.Int) (outOfSy // Always returns outOfSync false for SyncThreshold 0. // liveNodes is only included when outOfSync is true. func (n *node[CHAIN_ID, HEAD, RPC]) syncStatus(num int64, td *big.Int) (outOfSync bool, liveNodes int) { - if n.nLiveNodes == nil { + if n.poolInfoProvider == nil { return // skip for tests } threshold := n.nodePoolCfg.SyncThreshold() @@ -284,14 +274,14 @@ func (n *node[CHAIN_ID, HEAD, RPC]) syncStatus(num int64, td *big.Int) (outOfSyn return // disabled } // Check against best node - ln, highest, greatest := n.nLiveNodes() + ln, ci := n.poolInfoProvider.LatestChainInfo() mode := n.nodePoolCfg.SelectionMode() switch mode { case NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel: - return num < highest-int64(threshold), ln + return num < ci.BlockNumber-int64(threshold), ln case NodeSelectionModeTotalDifficulty: bigThreshold := big.NewInt(int64(threshold)) - return td.Cmp(bigmath.Sub(greatest, bigThreshold)) < 0, ln + return td.Cmp(bigmath.Sub(ci.TotalDifficulty, bigThreshold)) < 0, ln default: panic("unrecognized NodeSelectionMode: " + mode) } @@ -305,12 +295,12 @@ const ( // outOfSyncLoop takes an OutOfSync node and waits until isOutOfSync returns false to go back to live status func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td *big.Int) bool) { defer n.wg.Done() - ctx, cancel := n.stopCh.NewCtx() + ctx, cancel := n.newCtx() defer cancel() { // sanity check - state := n.State() + state := n.getCachedState() switch state { case nodeStateOutOfSync: case nodeStateClosed: @@ -323,7 +313,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td outOfSyncAt := time.Now() lggr := logger.Sugared(logger.Named(n.lfcLog, "OutOfSync")) - lggr.Debugw("Trying to revive out-of-sync RPC node", "nodeState", n.State()) + lggr.Debugw("Trying to revive out-of-sync RPC node", "nodeState", n.getCachedState()) // Need to redial since out-of-sync nodes are automatically disconnected state := n.createVerifiedConn(ctx, lggr) @@ -332,12 +322,12 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td return } - lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.State()) + lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node", "nodeState", n.getCachedState()) ch := make(chan HEAD) - sub, err := n.rpc.Subscribe(ctx, ch, rpcSubscriptionMethodNewHeads) + sub, err := n.rpc.SubscribeNewHead(ctx, ch) if err != nil { - lggr.Errorw("Failed to subscribe heads on out-of-sync RPC node", "nodeState", n.State(), "err", err) + lggr.Errorw("Failed to subscribe heads on out-of-sync RPC node", "nodeState", n.getCachedState(), "err", err) n.declareUnreachable() return } @@ -349,28 +339,27 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td return case head, open := <-ch: if !open { - lggr.Error("Subscription channel unexpectedly closed", "nodeState", n.State()) + lggr.Error("Subscription channel unexpectedly closed", "nodeState", n.getCachedState()) n.declareUnreachable() return } - n.setLatestReceived(head.BlockNumber(), head.BlockDifficulty()) if !isOutOfSync(head.BlockNumber(), head.BlockDifficulty()) { // back in-sync! flip back into alive loop - lggr.Infow(fmt.Sprintf("%s: %s. Node was out-of-sync for %s", msgInSync, n.String(), time.Since(outOfSyncAt)), "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "nodeState", n.State()) + lggr.Infow(fmt.Sprintf("%s: %s. Node was out-of-sync for %s", msgInSync, n.String(), time.Since(outOfSyncAt)), "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "nodeState", n.getCachedState()) n.declareInSync() return } - lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "nodeState", n.State()) + lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "nodeState", n.getCachedState()) case <-time.After(zombieNodeCheckInterval(n.chainCfg.NodeNoNewHeadsThreshold())): - if n.nLiveNodes != nil { - if l, _, _ := n.nLiveNodes(); l < 1 { + if n.poolInfoProvider != nil { + if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 1 { lggr.Critical("RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state") n.declareInSync() return } } case err := <-sub.Err(): - lggr.Errorw("Subscription was terminated", "nodeState", n.State(), "err", err) + lggr.Errorw("Subscription was terminated", "nodeState", n.getCachedState(), "err", err) n.declareUnreachable() return } @@ -379,12 +368,12 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { defer n.wg.Done() - ctx, cancel := n.stopCh.NewCtx() + ctx, cancel := n.newCtx() defer cancel() { // sanity check - state := n.State() + state := n.getCachedState() switch state { case nodeStateUnreachable: case nodeStateClosed: @@ -397,7 +386,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { unreachableAt := time.Now() lggr := logger.Sugared(logger.Named(n.lfcLog, "Unreachable")) - lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.State()) + lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.getCachedState()) dialRetryBackoff := iutils.NewRedialBackoff() @@ -406,11 +395,11 @@ func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { case <-ctx.Done(): return case <-time.After(dialRetryBackoff.Duration()): - lggr.Tracew("Trying to re-dial RPC node", "nodeState", n.State()) + lggr.Tracew("Trying to re-dial RPC node", "nodeState", n.getCachedState()) err := n.rpc.Dial(ctx) if err != nil { - lggr.Errorw(fmt.Sprintf("Failed to redial RPC node; still unreachable: %v", err), "err", err, "nodeState", n.State()) + lggr.Errorw(fmt.Sprintf("Failed to redial RPC node; still unreachable: %v", err), "err", err, "nodeState", n.getCachedState()) continue } @@ -422,7 +411,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { n.setState(nodeStateUnreachable) continue case nodeStateAlive: - lggr.Infow(fmt.Sprintf("Successfully redialled and verified RPC node %s. Node was offline for %s", n.String(), time.Since(unreachableAt)), "nodeState", n.State()) + lggr.Infow(fmt.Sprintf("Successfully redialled and verified RPC node %s. Node was offline for %s", n.String(), time.Since(unreachableAt)), "nodeState", n.getCachedState()) fallthrough default: n.declareState(state) @@ -434,12 +423,12 @@ func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() { defer n.wg.Done() - ctx, cancel := n.stopCh.NewCtx() + ctx, cancel := n.newCtx() defer cancel() { // sanity check - state := n.State() + state := n.getCachedState() switch state { case nodeStateInvalidChainID: case nodeStateClosed: @@ -460,7 +449,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() { return } - lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with invalid chain ID", n.String()), "nodeState", n.State()) + lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with invalid chain ID", n.String()), "nodeState", n.getCachedState()) chainIDRecheckBackoff := iutils.NewRedialBackoff() @@ -474,7 +463,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() { case nodeStateInvalidChainID: continue case nodeStateAlive: - lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was offline for %s", time.Since(invalidAt)), "nodeState", n.State()) + lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was offline for %s", time.Since(invalidAt)), "nodeState", n.getCachedState()) fallthrough default: n.declareState(state) @@ -486,12 +475,12 @@ func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() { func (n *node[CHAIN_ID, HEAD, RPC]) syncingLoop() { defer n.wg.Done() - ctx, cancel := n.stopCh.NewCtx() + ctx, cancel := n.newCtx() defer cancel() { // sanity check - state := n.State() + state := n.getCachedState() switch state { case nodeStateSyncing: case nodeStateClosed: @@ -504,7 +493,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) syncingLoop() { syncingAt := time.Now() lggr := logger.Sugared(logger.Named(n.lfcLog, "Syncing")) - lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with syncing status", n.String()), "nodeState", n.State()) + lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with syncing status", n.String()), "nodeState", n.getCachedState()) // Need to redial since syncing nodes are automatically disconnected state := n.createVerifiedConn(ctx, lggr) if state != nodeStateSyncing { @@ -519,20 +508,20 @@ func (n *node[CHAIN_ID, HEAD, RPC]) syncingLoop() { case <-ctx.Done(): return case <-time.After(recheckBackoff.Duration()): - lggr.Tracew("Trying to recheck if the node is still syncing", "nodeState", n.State()) + lggr.Tracew("Trying to recheck if the node is still syncing", "nodeState", n.getCachedState()) isSyncing, err := n.rpc.IsSyncing(ctx) if err != nil { - lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.State()) + lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.getCachedState()) n.declareUnreachable() return } if isSyncing { - lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.State()) + lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.getCachedState()) continue } - lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was syncing for %s", time.Since(syncingAt)), "nodeState", n.State()) + lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was syncing for %s", time.Since(syncingAt)), "nodeState", n.getCachedState()) n.declareAlive() return } diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go index 4bdfd698f7..863a15a1fa 100644 --- a/common/client/node_lifecycle_test.go +++ b/common/client/node_lifecycle_test.go @@ -15,7 +15,6 @@ import ( "go.uber.org/zap" "github.com/smartcontractkit/chainlink-common/pkg/logger" - bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" @@ -49,8 +48,8 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { defer func() { assert.NoError(t, node.close()) }() expectedError := errors.New("failed to subscribe to rpc") - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(nil, expectedError).Once() rpc.On("DisconnectAll").Once() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, expectedError).Once() // might be called in unreachable loop rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() node.declareAlive() @@ -67,6 +66,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc: rpc, lggr: lggr, }) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() defer func() { assert.NoError(t, node.close()) }() sub := mocks.NewSubscription(t) @@ -74,7 +74,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { close(errChan) sub.On("Err").Return((<-chan error)(errChan)).Once() sub.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Once() rpc.On("SetAliveLoopSub", sub).Once() // disconnects all on transfer to unreachable rpc.On("DisconnectAll").Once() @@ -89,13 +89,14 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { sub := mocks.NewSubscription(t) sub.On("Err").Return((<-chan error)(nil)) sub.On("Unsubscribe").Once() - opts.rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once() + opts.rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Once() opts.rpc.On("SetAliveLoopSub", sub).Once() return newDialedNode(t, opts) } t.Run("Stays alive and waits for signal", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newSubscribedNode(t, testNodeOpts{ config: testNodeConfig{}, @@ -111,6 +112,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { t.Run("stays alive while below pollFailureThreshold and resets counter on success", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) const pollFailureThreshold = 3 node := newSubscribedNode(t, testNodeOpts{ @@ -152,6 +154,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { t.Run("with threshold poll failures, transitions to unreachable", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) const pollFailureThreshold = 3 node := newSubscribedNode(t, testNodeOpts{ @@ -189,9 +192,12 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return 1, 20, big.NewInt(10) - } + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ + BlockNumber: 20, + }).Once() + node.SetPoolChainInfoProvider(poolInfo) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: 20}, ChainInfo{BlockNumber: 20}) pollError := errors.New("failed to get ClientVersion") rpc.On("ClientVersion", mock.Anything).Return("", pollError) node.declareAlive() @@ -213,10 +219,14 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - node.stateLatestBlockNumber = 20 - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return 10, syncThreshold + node.stateLatestBlockNumber + 1, big.NewInt(10) - } + const mostRecentBlock = 20 + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: mostRecentBlock}, ChainInfo{BlockNumber: 30}) + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(10, ChainInfo{ + BlockNumber: syncThreshold + mostRecentBlock + 1, + TotalDifficulty: big.NewInt(10), + }).Once() + node.SetPoolChainInfoProvider(poolInfo) rpc.On("ClientVersion", mock.Anything).Return("", nil) // tries to redial in outOfSync rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) { @@ -246,10 +256,14 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - node.stateLatestBlockNumber = 20 - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return 1, syncThreshold + node.stateLatestBlockNumber + 1, big.NewInt(10) - } + const mostRecentBlock = 20 + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: mostRecentBlock}, ChainInfo{BlockNumber: 30}) + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ + BlockNumber: syncThreshold + mostRecentBlock + 1, + TotalDifficulty: big.NewInt(10), + }).Once() + node.SetPoolChainInfoProvider(poolInfo) rpc.On("ClientVersion", mock.Anything).Return("", nil) node.declareAlive() tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState)) @@ -268,19 +282,17 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - node.stateLatestBlockNumber = 20 - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return 1, node.stateLatestBlockNumber + 100, big.NewInt(10) - } + const mostRecentBlock = 20 + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: mostRecentBlock}, ChainInfo{BlockNumber: 30}) rpc.On("ClientVersion", mock.Anything).Return("", nil) node.declareAlive() tests.AssertLogCountEventually(t, observedLogs, "Version poll successful", 2) assert.Equal(t, nodeStateAlive, node.State()) }) - t.Run("when no new heads received for threshold, transitions to out of sync", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() node := newSubscribedNode(t, testNodeOpts{ config: testNodeConfig{}, chainConfig: clientMocks.ChainConfig{ @@ -307,6 +319,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { t.Run("when no new heads received for threshold but we are the last live node, forcibly stays alive", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newSubscribedNode(t, testNodeOpts{ config: testNodeConfig{}, @@ -317,21 +330,24 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc: rpc, }) defer func() { assert.NoError(t, node.close()) }() - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return 1, 20, big.NewInt(10) - } + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ + BlockNumber: 20, + TotalDifficulty: big.NewInt(10), + }).Once() + node.SetPoolChainInfoProvider(poolInfo) node.declareAlive() tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState)) assert.Equal(t, nodeStateAlive, node.State()) }) - t.Run("rpc closed head channel", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() sub := mocks.NewSubscription(t) sub.On("Err").Return((<-chan error)(nil)) sub.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { ch := args.Get(1).(chan<- Head) close(ch) }).Return(sub, nil).Once() @@ -354,30 +370,6 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { tests.AssertLogEventually(t, observedLogs, "Subscription channel unexpectedly closed") assert.Equal(t, nodeStateUnreachable, node.State()) }) - t.Run("updates block number and difficulty on new head", func(t *testing.T) { - t.Parallel() - rpc := newMockNodeClient[types.ID, Head](t) - sub := mocks.NewSubscription(t) - sub.On("Err").Return((<-chan error)(nil)) - sub.On("Unsubscribe").Once() - expectedBlockNumber := rand.Int64() - expectedDiff := big.NewInt(rand.Int64()) - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { - ch := args.Get(1).(chan<- Head) - go writeHeads(t, ch, head{BlockNumber: expectedBlockNumber, BlockDifficulty: expectedDiff}) - }).Return(sub, nil).Once() - rpc.On("SetAliveLoopSub", sub).Once() - node := newDialedNode(t, testNodeOpts{ - config: testNodeConfig{}, - rpc: rpc, - }) - defer func() { assert.NoError(t, node.close()) }() - node.declareAlive() - tests.AssertEventually(t, func() bool { - state, block, diff := node.StateAndLatest() - return state == nodeStateAlive && block == expectedBlockNumber == bigmath.Equal(diff, expectedDiff) - }) - }) t.Run("If finality tag is not enabled updates finalized block metric using finality depth and latest head", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) @@ -387,7 +379,8 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { const blockNumber = 1000 const finalityDepth = 10 const expectedBlock = 990 - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { ch := args.Get(1).(chan<- Head) go writeHeads(t, ch, head{BlockNumber: blockNumber - 1}, head{BlockNumber: blockNumber}, head{BlockNumber: blockNumber - 1}) }).Return(sub, nil).Once() @@ -413,11 +406,12 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { t.Run("Logs warning if failed to get finalized block", func(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() rpc.On("LatestFinalizedBlock", mock.Anything).Return(newMockHead(t), errors.New("failed to get finalized block")) sub := mocks.NewSubscription(t) sub.On("Err").Return((<-chan error)(nil)) sub.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Once() rpc.On("SetAliveLoopSub", sub).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newDialedNode(t, testNodeOpts{ @@ -440,10 +434,11 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { head := newMockHead(t) head.On("IsValid").Return(false) rpc.On("LatestFinalizedBlock", mock.Anything).Return(head, nil) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() sub := mocks.NewSubscription(t) sub.On("Err").Return((<-chan error)(nil)) sub.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Once() rpc.On("SetAliveLoopSub", sub).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newDialedNode(t, testNodeOpts{ @@ -470,12 +465,13 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { sub := mocks.NewSubscription(t) sub.On("Err").Return((<-chan error)(nil)) sub.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { ch := args.Get(1).(chan<- Head) // ensure that "calculated" finalized head is larger than actual, to ensure we are correctly setting // the metric go writeHeads(t, ch, head{BlockNumber: expectedBlock*2 + finalityDepth}) }).Return(sub, nil).Once() + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() rpc.On("SetAliveLoopSub", sub).Once() name := "node-" + rand.Str(5) node := newDialedNode(t, testNodeOpts{ @@ -531,8 +527,9 @@ func setupRPCForAliveLoop(t *testing.T, rpc *mockNodeClient[types.ID, Head]) { aliveSubscription := mocks.NewSubscription(t) aliveSubscription.On("Err").Return((<-chan error)(nil)).Maybe() aliveSubscription.On("Unsubscribe").Maybe() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(aliveSubscription, nil).Maybe() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(aliveSubscription, nil).Maybe() rpc.On("SetAliveLoopSub", mock.Anything).Maybe() + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Maybe() } func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { @@ -577,7 +574,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) outOfSyncSubscription.On("Unsubscribe").Once() heads := []head{{BlockNumber: 7}, {BlockNumber: 11}, {BlockNumber: 13}} - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { ch := args.Get(1).(chan<- Head) go writeHeads(t, ch, heads...) }).Return(outOfSyncSubscription, nil).Once() @@ -701,7 +698,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { rpc.On("Dial", mock.Anything).Return(nil).Once() rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() expectedError := errors.New("failed to subscribe") - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(nil, expectedError) + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, expectedError) rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() node.declareOutOfSync(stubIsOutOfSync) tests.AssertEventually(t, func() bool { @@ -728,7 +725,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { errChan <- errors.New("subscription was terminate") sub.On("Err").Return((<-chan error)(errChan)) sub.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Once() rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() node.declareOutOfSync(stubIsOutOfSync) tests.AssertLogEventually(t, observedLogs, "Subscription was terminated") @@ -754,7 +751,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { sub := mocks.NewSubscription(t) sub.On("Err").Return((<-chan error)(nil)) sub.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { ch := args.Get(1).(chan<- Head) close(ch) }).Return(sub, nil).Once() @@ -785,10 +782,11 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) outOfSyncSubscription.On("Unsubscribe").Once() const highestBlock = 1000 - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { ch := args.Get(1).(chan<- Head) go writeHeads(t, ch, head{BlockNumber: highestBlock - 1}, head{BlockNumber: highestBlock}) }).Return(outOfSyncSubscription, nil).Once() + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: highestBlock}, ChainInfo{BlockNumber: highestBlock}) setupRPCForAliveLoop(t, rpc) @@ -815,9 +813,13 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return 0, 100, big.NewInt(200) - } + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(0, ChainInfo{ + BlockNumber: 100, + TotalDifficulty: big.NewInt(200), + }) + node.SetPoolChainInfoProvider(poolInfo) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{BlockNumber: 0}, ChainInfo{BlockNumber: 0}) rpc.On("Dial", mock.Anything).Return(nil).Once() rpc.On("ChainID", mock.Anything).Return(nodeChainID, nil).Once() @@ -825,7 +827,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { outOfSyncSubscription := mocks.NewSubscription(t) outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) outOfSyncSubscription.On("Unsubscribe").Once() - rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(outOfSyncSubscription, nil).Once() + rpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(outOfSyncSubscription, nil).Once() setupRPCForAliveLoop(t, rpc) @@ -1304,9 +1306,8 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { }) t.Run("skip if syncThreshold is not configured", func(t *testing.T) { node := newTestNode(t, testNodeOpts{}) - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return - } + poolInfo := newMockPoolChainInfoProvider(t) + node.SetPoolChainInfoProvider(poolInfo) outOfSync, liveNodes := node.syncStatus(0, nil) assert.Equal(t, false, outOfSync) assert.Equal(t, 0, liveNodes) @@ -1315,9 +1316,9 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { node := newTestNode(t, testNodeOpts{ config: testNodeConfig{syncThreshold: 1}, }) - node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { - return - } + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(1, ChainInfo{}).Once() + node.SetPoolChainInfoProvider(poolInfo) assert.Panics(t, func() { _, _ = node.syncStatus(0, nil) }) @@ -1361,9 +1362,12 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { selectionMode: selectionMode, }, }) - node.nLiveNodes = func() (int, int64, *big.Int) { - return nodesNum, highestBlock, big.NewInt(totalDifficulty) - } + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(nodesNum, ChainInfo{ + BlockNumber: highestBlock, + TotalDifficulty: big.NewInt(totalDifficulty), + }) + node.SetPoolChainInfoProvider(poolInfo) for _, td := range []int64{totalDifficulty - syncThreshold - 1, totalDifficulty - syncThreshold, totalDifficulty, totalDifficulty + 1} { for _, testCase := range testCases { t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: total difficulty: %d", testCase.name, selectionMode, td), func(t *testing.T) { @@ -1413,9 +1417,13 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { selectionMode: NodeSelectionModeTotalDifficulty, }, }) - node.nLiveNodes = func() (int, int64, *big.Int) { - return nodesNum, highestBlock, big.NewInt(totalDifficulty) - } + + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("LatestChainInfo").Return(nodesNum, ChainInfo{ + BlockNumber: highestBlock, + TotalDifficulty: big.NewInt(totalDifficulty), + }) + node.SetPoolChainInfoProvider(poolInfo) for _, hb := range []int64{highestBlock - syncThreshold - 1, highestBlock - syncThreshold, highestBlock, highestBlock + 1} { for _, testCase := range testCases { t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: highest block: %d", testCase.name, NodeSelectionModeTotalDifficulty, hb), func(t *testing.T) { @@ -1573,3 +1581,98 @@ func TestUnit_NodeLifecycle_SyncingLoop(t *testing.T) { }) }) } + +func TestNode_State(t *testing.T) { + t.Run("If not Alive, returns as is", func(t *testing.T) { + for state := nodeState(0); state < nodeStateLen; state++ { + if state == nodeStateAlive { + continue + } + + node := newTestNode(t, testNodeOpts{}) + node.setState(state) + assert.Equal(t, state, node.State()) + } + }) + t.Run("If repeatable read is not enforced, returns alive", func(t *testing.T) { + node := newTestNode(t, testNodeOpts{}) + node.setState(nodeStateAlive) + assert.Equal(t, nodeStateAlive, node.State()) + }) + testCases := []struct { + Name string + FinalizedBlockOffsetVal uint32 + IsFinalityTagEnabled bool + PoolChainInfo ChainInfo + NodeChainInfo ChainInfo + ExpectedState nodeState + }{ + { + Name: "If finality lag does not exceeds offset, returns alive (FinalityDepth)", + FinalizedBlockOffsetVal: 15, + PoolChainInfo: ChainInfo{ + BlockNumber: 20, + }, + NodeChainInfo: ChainInfo{ + BlockNumber: 5, + }, + ExpectedState: nodeStateAlive, + }, + { + Name: "If finality lag does not exceeds offset, returns alive (FinalityTag)", + FinalizedBlockOffsetVal: 15, + IsFinalityTagEnabled: true, + PoolChainInfo: ChainInfo{ + FinalizedBlockNumber: 20, + }, + NodeChainInfo: ChainInfo{ + FinalizedBlockNumber: 5, + }, + ExpectedState: nodeStateAlive, + }, + { + Name: "If finality lag exceeds offset, returns nodeStateFinalizedBlockOutOfSync (FinalityDepth)", + FinalizedBlockOffsetVal: 15, + PoolChainInfo: ChainInfo{ + BlockNumber: 20, + }, + NodeChainInfo: ChainInfo{ + BlockNumber: 4, + }, + ExpectedState: nodeStateFinalizedBlockOutOfSync, + }, + { + Name: "If finality lag exceeds offset, returns nodeStateFinalizedBlockOutOfSync (FinalityTag)", + FinalizedBlockOffsetVal: 15, + IsFinalityTagEnabled: true, + PoolChainInfo: ChainInfo{ + FinalizedBlockNumber: 20, + }, + NodeChainInfo: ChainInfo{ + FinalizedBlockNumber: 4, + }, + ExpectedState: nodeStateFinalizedBlockOutOfSync, + }, + } + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("GetInterceptedChainInfo").Return(tc.NodeChainInfo, tc.PoolChainInfo).Once() + node := newTestNode(t, testNodeOpts{ + config: testNodeConfig{ + enforceRepeatableRead: true, + }, + chainConfig: clientMocks.ChainConfig{ + FinalizedBlockOffsetVal: tc.FinalizedBlockOffsetVal, + IsFinalityTagEnabled: tc.IsFinalityTagEnabled, + }, + rpc: rpc, + }) + poolInfo := newMockPoolChainInfoProvider(t) + poolInfo.On("HighestUserObservations").Return(tc.PoolChainInfo).Once() + node.SetPoolChainInfoProvider(poolInfo) + node.setState(nodeStateAlive) + assert.Equal(t, tc.ExpectedState, node.State()) + }) + } +} diff --git a/common/client/node_selector_highest_head.go b/common/client/node_selector_highest_head.go index 99a130004a..25a931fc01 100644 --- a/common/client/node_selector_highest_head.go +++ b/common/client/node_selector_highest_head.go @@ -24,7 +24,8 @@ func (s highestHeadNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID, HE var highestHeadNumber int64 = math.MinInt64 var highestHeadNodes []Node[CHAIN_ID, HEAD, RPC] for _, n := range s { - state, currentHeadNumber, _ := n.StateAndLatest() + state, currentChainInfo := n.StateAndLatest() + currentHeadNumber := currentChainInfo.BlockNumber if state == nodeStateAlive && currentHeadNumber >= highestHeadNumber { if highestHeadNumber < currentHeadNumber { highestHeadNumber = currentHeadNumber diff --git a/common/client/node_selector_highest_head_test.go b/common/client/node_selector_highest_head_test.go index 6e47bbedca..e245924589 100644 --- a/common/client/node_selector_highest_head_test.go +++ b/common/client/node_selector_highest_head_test.go @@ -24,13 +24,13 @@ func TestHighestHeadNodeSelector(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) if i == 0 { // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil) + node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: int64(-1)}) } else if i == 1 { // second node is alive, LatestReceivedBlockNumber = 1 - node.On("StateAndLatest").Return(nodeStateAlive, int64(1), nil) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(1)}) } else { // third node is alive, LatestReceivedBlockNumber = 2 (best node) - node.On("StateAndLatest").Return(nodeStateAlive, int64(2), nil) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(2)}) } node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -42,7 +42,7 @@ func TestHighestHeadNodeSelector(t *testing.T) { t.Run("stick to the same node", func(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) // fourth node is alive, LatestReceivedBlockNumber = 2 (same as 3rd) - node.On("StateAndLatest").Return(nodeStateAlive, int64(2), nil) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(2)}) node.On("Order").Return(int32(1)) nodes = append(nodes, node) @@ -53,7 +53,7 @@ func TestHighestHeadNodeSelector(t *testing.T) { t.Run("another best node", func(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) // fifth node is alive, LatestReceivedBlockNumber = 3 (better than 3rd and 4th) - node.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) node.On("Order").Return(int32(1)) nodes = append(nodes, node) @@ -63,10 +63,10 @@ func TestHighestHeadNodeSelector(t *testing.T) { t.Run("nodes never update latest block number", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(-1)}) node1.On("Order").Return(int32(1)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(-1)}) node2.On("Order").Return(int32(1)) selector := newNodeSelector(NodeSelectionModeHighestHead, []Node[types.ID, Head, nodeClient]{node1, node2}) assert.Same(t, node1, selector.Select()) @@ -83,10 +83,10 @@ func TestHighestHeadNodeSelector_None(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) if i == 0 { // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil) + node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: int64(-1)}) } else { // others are unreachable - node.On("StateAndLatest").Return(nodeStateUnreachable, int64(1), nil) + node.On("StateAndLatest").Return(nodeStateUnreachable, ChainInfo{BlockNumber: int64(-1)}) } nodes = append(nodes, node) } @@ -104,7 +104,7 @@ func TestHighestHeadNodeSelectorWithOrder(t *testing.T) { t.Run("same head and order", func(t *testing.T) { for i := 0; i < 3; i++ { node := newMockNode[types.ID, Head, nodeClient](t) - node.On("StateAndLatest").Return(nodeStateAlive, int64(1), nil) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(1)}) node.On("Order").Return(int32(2)) nodes = append(nodes, node) } @@ -115,15 +115,15 @@ func TestHighestHeadNodeSelectorWithOrder(t *testing.T) { t.Run("same head but different order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) node1.On("Order").Return(int32(3)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) node2.On("Order").Return(int32(1)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil) + node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) node3.On("Order").Return(int32(2)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3} @@ -134,15 +134,15 @@ func TestHighestHeadNodeSelectorWithOrder(t *testing.T) { t.Run("different head but same order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), nil) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(1)}) node1.On("Order").Maybe().Return(int32(3)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(2), nil) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(2)}) node2.On("Order").Maybe().Return(int32(3)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), nil) + node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(3)}) node3.On("Order").Return(int32(3)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3} @@ -153,19 +153,19 @@ func TestHighestHeadNodeSelectorWithOrder(t *testing.T) { t.Run("different head and different order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(10), nil) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(10)}) node1.On("Order").Maybe().Return(int32(3)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(11), nil) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(11)}) node2.On("Order").Maybe().Return(int32(4)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(11), nil) + node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(11)}) node3.On("Order").Maybe().Return(int32(3)) node4 := newMockNode[types.ID, Head, nodeClient](t) - node4.On("StateAndLatest").Return(nodeStateAlive, int64(10), nil) + node4.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: int64(10)}) node4.On("Order").Maybe().Return(int32(1)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3, node4} diff --git a/common/client/node_selector_total_difficulty.go b/common/client/node_selector_total_difficulty.go index 35491503bc..6b45e75528 100644 --- a/common/client/node_selector_total_difficulty.go +++ b/common/client/node_selector_total_difficulty.go @@ -27,11 +27,12 @@ func (s totalDifficultyNodeSelector[CHAIN_ID, HEAD, RPC]) Select() Node[CHAIN_ID var aliveNodes []Node[CHAIN_ID, HEAD, RPC] for _, n := range s { - state, _, currentTD := n.StateAndLatest() + state, currentChainInfo := n.StateAndLatest() if state != nodeStateAlive { continue } + currentTD := currentChainInfo.TotalDifficulty aliveNodes = append(aliveNodes, n) if currentTD != nil && (highestTD == nil || currentTD.Cmp(highestTD) >= 0) { if highestTD == nil || currentTD.Cmp(highestTD) > 0 { diff --git a/common/client/node_selector_total_difficulty_test.go b/common/client/node_selector_total_difficulty_test.go index 5c43cdd847..0bc214918d 100644 --- a/common/client/node_selector_total_difficulty_test.go +++ b/common/client/node_selector_total_difficulty_test.go @@ -1,7 +1,7 @@ package client import ( - big "math/big" + "math/big" "testing" "github.com/smartcontractkit/chainlink/v2/common/types" @@ -24,13 +24,13 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) if i == 0 { // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil) + node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: -1}) } else if i == 1 { // second node is alive - node.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(7)) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(7)}) } else { // third node is alive and best - node.On("StateAndLatest").Return(nodeStateAlive, int64(2), big.NewInt(8)) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 2, TotalDifficulty: big.NewInt(8)}) } node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -42,7 +42,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { t.Run("stick to the same node", func(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) // fourth node is alive (same as 3rd) - node.On("StateAndLatest").Return(nodeStateAlive, int64(2), big.NewInt(8)) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 2, TotalDifficulty: big.NewInt(8)}) node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -53,7 +53,7 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { t.Run("another best node", func(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) // fifth node is alive (better than 3rd and 4th) - node.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(11)) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(11)}) node.On("Order").Maybe().Return(int32(1)) nodes = append(nodes, node) @@ -63,10 +63,10 @@ func TestTotalDifficultyNodeSelector(t *testing.T) { t.Run("nodes never update latest block number", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: -1, TotalDifficulty: nil}) node1.On("Order").Maybe().Return(int32(1)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(-1), nil) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: -1, TotalDifficulty: nil}) node2.On("Order").Maybe().Return(int32(1)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2} @@ -85,10 +85,10 @@ func TestTotalDifficultyNodeSelector_None(t *testing.T) { node := newMockNode[types.ID, Head, nodeClient](t) if i == 0 { // first node is out of sync - node.On("StateAndLatest").Return(nodeStateOutOfSync, int64(-1), nil) + node.On("StateAndLatest").Return(nodeStateOutOfSync, ChainInfo{BlockNumber: -1, TotalDifficulty: nil}) } else { // others are unreachable - node.On("StateAndLatest").Return(nodeStateUnreachable, int64(1), big.NewInt(7)) + node.On("StateAndLatest").Return(nodeStateUnreachable, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(7)}) } nodes = append(nodes, node) } @@ -106,7 +106,7 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("same td and order", func(t *testing.T) { for i := 0; i < 3; i++ { node := newMockNode[types.ID, Head, nodeClient](t) - node.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(10)) + node.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(10)}) node.On("Order").Return(int32(2)) nodes = append(nodes, node) } @@ -117,15 +117,15 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("same td but different order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(10)) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(10)}) node1.On("Order").Return(int32(3)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(10)) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(10)}) node2.On("Order").Return(int32(1)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(3), big.NewInt(10)) + node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 3, TotalDifficulty: big.NewInt(10)}) node3.On("Order").Return(int32(2)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3} @@ -136,15 +136,15 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("different td but same order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(10)) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(10)}) node1.On("Order").Maybe().Return(int32(3)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(11)) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(11)}) node2.On("Order").Maybe().Return(int32(3)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(12)) + node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(12)}) node3.On("Order").Return(int32(3)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3} @@ -155,19 +155,19 @@ func TestTotalDifficultyNodeSelectorWithOrder(t *testing.T) { t.Run("different head and different order", func(t *testing.T) { node1 := newMockNode[types.ID, Head, nodeClient](t) - node1.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(100)) + node1.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(100)}) node1.On("Order").Maybe().Return(int32(4)) node2 := newMockNode[types.ID, Head, nodeClient](t) - node2.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(110)) + node2.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(110)}) node2.On("Order").Maybe().Return(int32(5)) node3 := newMockNode[types.ID, Head, nodeClient](t) - node3.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(110)) + node3.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(110)}) node3.On("Order").Maybe().Return(int32(1)) node4 := newMockNode[types.ID, Head, nodeClient](t) - node4.On("StateAndLatest").Return(nodeStateAlive, int64(1), big.NewInt(105)) + node4.On("StateAndLatest").Return(nodeStateAlive, ChainInfo{BlockNumber: 1, TotalDifficulty: big.NewInt(105)}) node4.On("Order").Maybe().Return(int32(2)) nodes := []Node[types.ID, Head, nodeClient]{node1, node2, node3, node4} diff --git a/common/client/node_test.go b/common/client/node_test.go index a97f26555a..3b971e8490 100644 --- a/common/client/node_test.go +++ b/common/client/node_test.go @@ -17,7 +17,9 @@ type testNodeConfig struct { selectionMode string syncThreshold uint32 nodeIsSyncingEnabled bool + enforceRepeatableRead bool finalizedBlockPollInterval time.Duration + deathDeclarationDelay time.Duration } func (n testNodeConfig) PollFailureThreshold() uint32 { @@ -44,6 +46,14 @@ func (n testNodeConfig) FinalizedBlockPollInterval() time.Duration { return n.finalizedBlockPollInterval } +func (n testNodeConfig) EnforceRepeatableRead() bool { + return n.enforceRepeatableRead +} + +func (n testNodeConfig) DeathDeclarationDelay() time.Duration { + return n.deathDeclarationDelay +} + type testNode struct { *node[types.ID, Head, NodeClient[types.ID, Head]] } diff --git a/common/client/types.go b/common/client/types.go index a27e6a50b7..3d548b9deb 100644 --- a/common/client/types.go +++ b/common/client/types.go @@ -66,6 +66,7 @@ type NodeClient[ connection[CHAIN_ID, HEAD] DialHTTP() error + // DisconnectAll - cancels all inflight requests, terminates all subscriptions and resets latest ChainInfo. DisconnectAll() Close() ClientVersion(context.Context) (string, error) @@ -74,6 +75,17 @@ type NodeClient[ UnsubscribeAllExceptAliveLoop() IsSyncing(ctx context.Context) (bool, error) LatestFinalizedBlock(ctx context.Context) (HEAD, error) + // GetInterceptedChainInfo - returns latest and highest observed by application layer ChainInfo. + // latest ChainInfo is the most recent value received within a NodeClient's current lifecycle between Dial and DisconnectAll. + // highestUserObservations ChainInfo is the highest ChainInfo observed excluding health checks calls. + // Its values must not be reset. + // The results of corresponding calls, to get the most recent head and the latest finalized head, must be + // intercepted and reflected in ChainInfo before being returned to a caller. Otherwise, MultiNode is not able to + // provide repeatable read guarantee. + // DisconnectAll must reset latest ChainInfo to default value. + // Ensure implementation does not have a race condition when values are reset before request completion and as + // a result latest ChainInfo contains information from the previous cycle. + GetInterceptedChainInfo() (latest, highestUserObservations ChainInfo) } // clientAPI includes all the direct RPC methods required by the generalized common client to implement its own. @@ -145,5 +157,41 @@ type connection[ ] interface { ChainID(ctx context.Context) (CHAIN_ID, error) Dial(ctx context.Context) error - Subscribe(ctx context.Context, channel chan<- HEAD, args ...interface{}) (types.Subscription, error) + SubscribeNewHead(ctx context.Context, channel chan<- HEAD) (types.Subscription, error) +} + +// PoolChainInfoProvider - provides aggregation of nodes pool ChainInfo +// +//go:generate mockery --quiet --name PoolChainInfoProvider --structname mockPoolChainInfoProvider --filename "mock_pool_chain_info_provider_test.go" --inpackage --case=underscore +type PoolChainInfoProvider interface { + // LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being + // moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all. + // Returns highest latest ChainInfo within the alive nodes. E.g. most recent block number and highest block number + // observed by Node A are 10 and 15; Node B - 12 and 14. This method will return 12. + LatestChainInfo() (int, ChainInfo) + // HighestUserObservations - returns highest ChainInfo ever observed by any user of MultiNode. + HighestUserObservations() ChainInfo +} + +// ChainInfo - defines RPC's or MultiNode's view on the chain +type ChainInfo struct { + BlockNumber int64 + FinalizedBlockNumber int64 + TotalDifficulty *big.Int +} + +func MaxTotalDifficulty(a, b *big.Int) *big.Int { + if a == nil { + if b == nil { + return nil + } + + return big.NewInt(0).Set(b) + } + + if b == nil || a.Cmp(b) >= 0 { + return big.NewInt(0).Set(a) + } + + return big.NewInt(0).Set(b) } diff --git a/common/client/types_test.go b/common/client/types_test.go new file mode 100644 index 0000000000..68d7a3fe78 --- /dev/null +++ b/common/client/types_test.go @@ -0,0 +1,34 @@ +package client + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMaxDifficulty(t *testing.T) { + cases := []struct { + A, B, Result *big.Int + }{ + { + A: nil, B: nil, Result: nil, + }, + { + A: nil, B: big.NewInt(1), Result: big.NewInt(1), + }, + { + A: big.NewInt(1), B: big.NewInt(1), Result: big.NewInt(1), + }, + { + A: big.NewInt(1), B: big.NewInt(2), Result: big.NewInt(2), + }, + } + + for _, test := range cases { + actualResult := MaxTotalDifficulty(test.A, test.B) + assert.Equal(t, test.Result, actualResult, "expected max(%v, %v) to produce %v", test.A, test.B, test.Result) + inverted := MaxTotalDifficulty(test.B, test.A) + assert.Equal(t, actualResult, inverted, "expected max(%v, %v) == max(%v, %v)", test.A, test.B, test.B, test.A) + } +} diff --git a/common/headtracker/head_listener.go b/common/headtracker/head_listener.go index 15977c4dfe..25715b3528 100644 --- a/common/headtracker/head_listener.go +++ b/common/headtracker/head_listener.go @@ -36,7 +36,7 @@ type headHandler[H types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] func(ctx c type HeadListener[H types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] interface { // ListenForNewHeads kicks off the listen loop (not thread safe) // done() must be executed upon leaving ListenForNewHeads() - ListenForNewHeads(handleNewHead headHandler[H, BLOCK_HASH], done func()) + ListenForNewHeads(onSubscribe func(), handleNewHead headHandler[H, BLOCK_HASH], done func()) // ReceivingHeads returns true if the listener is receiving heads (thread safe) ReceivingHeads() bool @@ -88,7 +88,7 @@ func (hl *headListener[HTH, S, ID, BLOCK_HASH]) Name() string { return hl.logger.Name() } -func (hl *headListener[HTH, S, ID, BLOCK_HASH]) ListenForNewHeads(handleNewHead headHandler[HTH, BLOCK_HASH], done func()) { +func (hl *headListener[HTH, S, ID, BLOCK_HASH]) ListenForNewHeads(onSubscription func(), handleNewHead headHandler[HTH, BLOCK_HASH], done func()) { defer done() defer hl.unsubscribe() @@ -99,6 +99,8 @@ func (hl *headListener[HTH, S, ID, BLOCK_HASH]) ListenForNewHeads(handleNewHead if !hl.subscribe(ctx) { break } + + onSubscription() err := hl.receiveHeaders(ctx, handleNewHead) if ctx.Err() != nil { break diff --git a/common/headtracker/head_tracker.go b/common/headtracker/head_tracker.go index 48c4859a64..bc5f5274c0 100644 --- a/common/headtracker/head_tracker.go +++ b/common/headtracker/head_tracker.go @@ -40,8 +40,11 @@ const HeadsBufferSize = 10 type HeadTracker[H types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] interface { services.Service // Backfill given a head will fill in any missing heads up to latestFinalized - Backfill(ctx context.Context, headWithChain, latestFinalized H) (err error) + Backfill(ctx context.Context, headWithChain H) (err error) LatestChain() H + // LatestAndFinalizedBlock - returns latest and latest finalized blocks. + // NOTE: Returns latest finalized block as is, ignoring the FinalityTagBypass feature flag. + LatestAndFinalizedBlock(ctx context.Context) (latest, finalized H, err error) } type headTracker[ @@ -114,16 +117,15 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) Start(ctx context.Context) error // anyway when we connect (but we should not rely on this because it is // not specced). If it happens this is fine, and the head will be // ignored as a duplicate. - err := ht.handleInitialHead(ctx) - if err != nil { - if ctx.Err() != nil { - return ctx.Err() + onSubscribe := func() { + err := ht.handleInitialHead(ctx) + if err != nil { + ht.log.Errorw("Error handling initial head", "err", err.Error()) } - ht.log.Errorw("Error handling initial head", "err", err.Error()) } ht.wgDone.Add(3) - go ht.headListener.ListenForNewHeads(ht.handleNewHead, ht.wgDone.Done) + go ht.headListener.ListenForNewHeads(onSubscribe, ht.handleNewHead, ht.wgDone.Done) go ht.backfillLoop() go ht.broadcastLoop() @@ -145,7 +147,7 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) handleInitialHead(ctx context.Con } ht.log.Debugw("Got initial head", "head", initialHead, "blockNumber", initialHead.BlockNumber(), "blockHash", initialHead.BlockHash()) - latestFinalized, err := ht.calculateLatestFinalized(ctx, initialHead) + latestFinalized, err := ht.calculateLatestFinalized(ctx, initialHead, ht.htConfig.FinalityTagBypass()) if err != nil { return fmt.Errorf("failed to calculate latest finalized head: %w", err) } @@ -195,7 +197,12 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) HealthReport() map[string]error { return report } -func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) Backfill(ctx context.Context, headWithChain, latestFinalized HTH) (err error) { +func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) Backfill(ctx context.Context, headWithChain HTH) (err error) { + latestFinalized, err := ht.calculateLatestFinalized(ctx, headWithChain, ht.htConfig.FinalityTagBypass()) + if err != nil { + return fmt.Errorf("failed to calculate finalized block: %w", err) + } + if !latestFinalized.IsValid() { return errors.New("can not perform backfill without a valid latestFinalized head") } @@ -208,6 +215,11 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) Backfill(ctx context.Context, hea return errors.New(errMsg) } + if headWithChain.BlockNumber()-latestFinalized.BlockNumber() > int64(ht.htConfig.MaxAllowedFinalityDepth()) { + return fmt.Errorf("gap between latest finalized block (%d) and current head (%d) is too large (> %d)", + latestFinalized.BlockNumber(), headWithChain.BlockNumber(), ht.htConfig.MaxAllowedFinalityDepth()) + } + return ht.backfill(ctx, headWithChain, latestFinalized) } @@ -317,13 +329,7 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) backfillLoop() { break } { - latestFinalized, err := ht.calculateLatestFinalized(ctx, head) - if err != nil { - ht.log.Warnw("Failed to calculate finalized block", "err", err) - continue - } - - err = ht.Backfill(ctx, head, latestFinalized) + err := ht.Backfill(ctx, head) if err != nil { ht.log.Warnw("Unexpected error while backfilling heads", "err", err) } else if ctx.Err() != nil { @@ -335,12 +341,58 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) backfillLoop() { } } +// LatestAndFinalizedBlock - returns latest and latest finalized blocks. +// NOTE: Returns latest finalized block as is, ignoring the FinalityTagBypass feature flag. +// TODO: BCI-3321 use cached values instead of making RPC requests +func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) LatestAndFinalizedBlock(ctx context.Context) (latest, finalized HTH, err error) { + latest, err = ht.client.HeadByNumber(ctx, nil) + if err != nil { + err = fmt.Errorf("failed to get latest block: %w", err) + return + } + + if !latest.IsValid() { + err = fmt.Errorf("expected latest block to be valid") + return + } + + finalized, err = ht.calculateLatestFinalized(ctx, latest, false) + if err != nil { + err = fmt.Errorf("failed to calculate latest finalized block: %w", err) + return + } + if !finalized.IsValid() { + err = fmt.Errorf("expected finalized block to be valid") + return + } + + return +} + +func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) getHeadAtHeight(ctx context.Context, chainHeadHash BLOCK_HASH, blockHeight int64) (HTH, error) { + chainHead := ht.headSaver.Chain(chainHeadHash) + if chainHead.IsValid() { + // check if provided chain contains a block of specified height + headAtHeight, err := chainHead.HeadAtHeight(blockHeight) + if err == nil { + // we are forced to reload the block due to type mismatched caused by generics + hthAtHeight := ht.headSaver.Chain(headAtHeight.BlockHash()) + // ensure that the block was not removed from the chain by another goroutine + if hthAtHeight.IsValid() { + return hthAtHeight, nil + } + } + } + + return ht.client.HeadByNumber(ctx, big.NewInt(blockHeight)) +} + // calculateLatestFinalized - returns latest finalized block. It's expected that currentHeadNumber - is the head of // canonical chain. There is no guaranties that returned block belongs to the canonical chain. Additional verification // must be performed before usage. -func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) calculateLatestFinalized(ctx context.Context, currentHead HTH) (latestFinalized HTH, err error) { - if ht.config.FinalityTagEnabled() && !ht.htConfig.FinalityTagBypass() { - latestFinalized, err = ht.client.LatestFinalizedBlock(ctx) +func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) calculateLatestFinalized(ctx context.Context, currentHead HTH, finalityTagBypass bool) (HTH, error) { + if ht.config.FinalityTagEnabled() && !finalityTagBypass { + latestFinalized, err := ht.client.LatestFinalizedBlock(ctx) if err != nil { return latestFinalized, fmt.Errorf("failed to get latest finalized block: %w", err) } @@ -349,22 +401,22 @@ func (ht *headTracker[HTH, S, ID, BLOCK_HASH]) calculateLatestFinalized(ctx cont return latestFinalized, fmt.Errorf("failed to get valid latest finalized block") } - if currentHead.BlockNumber()-latestFinalized.BlockNumber() > int64(ht.htConfig.MaxAllowedFinalityDepth()) { - return latestFinalized, fmt.Errorf("gap between latest finalized block (%d) and current head (%d) is too large (> %d)", - latestFinalized.BlockNumber(), currentHead.BlockNumber(), ht.htConfig.MaxAllowedFinalityDepth()) + if ht.config.FinalizedBlockOffset() == 0 { + return latestFinalized, nil } - return latestFinalized, nil + finalizedBlockNumber := max(latestFinalized.BlockNumber()-int64(ht.config.FinalizedBlockOffset()), 0) + return ht.getHeadAtHeight(ctx, latestFinalized.BlockHash(), finalizedBlockNumber) } // no need to make an additional RPC call on chains with instant finality - if ht.config.FinalityDepth() == 0 { + if ht.config.FinalityDepth() == 0 && ht.config.FinalizedBlockOffset() == 0 { return currentHead, nil } - finalizedBlockNumber := currentHead.BlockNumber() - int64(ht.config.FinalityDepth()) + finalizedBlockNumber := currentHead.BlockNumber() - int64(ht.config.FinalityDepth()) - int64(ht.config.FinalizedBlockOffset()) if finalizedBlockNumber <= 0 { finalizedBlockNumber = 0 } - return ht.client.HeadByNumber(ctx, big.NewInt(finalizedBlockNumber)) + return ht.getHeadAtHeight(ctx, currentHead.BlockHash(), finalizedBlockNumber) } // backfill fetches all missing heads up until the latestFinalizedHead diff --git a/common/headtracker/mocks/head_tracker.go b/common/headtracker/mocks/head_tracker.go index 0e30b44154..b02c605f53 100644 --- a/common/headtracker/mocks/head_tracker.go +++ b/common/headtracker/mocks/head_tracker.go @@ -15,17 +15,17 @@ type HeadTracker[H types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] struct { mock.Mock } -// Backfill provides a mock function with given fields: ctx, headWithChain, latestFinalized -func (_m *HeadTracker[H, BLOCK_HASH]) Backfill(ctx context.Context, headWithChain H, latestFinalized H) error { - ret := _m.Called(ctx, headWithChain, latestFinalized) +// Backfill provides a mock function with given fields: ctx, headWithChain +func (_m *HeadTracker[H, BLOCK_HASH]) Backfill(ctx context.Context, headWithChain H) error { + ret := _m.Called(ctx, headWithChain) if len(ret) == 0 { panic("no return value specified for Backfill") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, H, H) error); ok { - r0 = rf(ctx, headWithChain, latestFinalized) + if rf, ok := ret.Get(0).(func(context.Context, H) error); ok { + r0 = rf(ctx, headWithChain) } else { r0 = ret.Error(0) } @@ -71,6 +71,41 @@ func (_m *HeadTracker[H, BLOCK_HASH]) HealthReport() map[string]error { return r0 } +// LatestAndFinalizedBlock provides a mock function with given fields: ctx +func (_m *HeadTracker[H, BLOCK_HASH]) LatestAndFinalizedBlock(ctx context.Context) (H, H, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for LatestAndFinalizedBlock") + } + + var r0 H + var r1 H + var r2 error + if rf, ok := ret.Get(0).(func(context.Context) (H, H, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) H); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(H) + } + + if rf, ok := ret.Get(1).(func(context.Context) H); ok { + r1 = rf(ctx) + } else { + r1 = ret.Get(1).(H) + } + + if rf, ok := ret.Get(2).(func(context.Context) error); ok { + r2 = rf(ctx) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // LatestChain provides a mock function with given fields: func (_m *HeadTracker[H, BLOCK_HASH]) LatestChain() H { ret := _m.Called() diff --git a/common/headtracker/types/config.go b/common/headtracker/types/config.go index e0eb422672..06ad93d39d 100644 --- a/common/headtracker/types/config.go +++ b/common/headtracker/types/config.go @@ -6,6 +6,7 @@ type Config interface { BlockEmissionIdleWarningThreshold() time.Duration FinalityDepth() uint32 FinalityTagEnabled() bool + FinalizedBlockOffset() uint32 } type HeadTrackerConfig interface { diff --git a/common/types/head.go b/common/types/head.go index 9d927d4f5e..77a2a7a0dc 100644 --- a/common/types/head.go +++ b/common/types/head.go @@ -33,6 +33,9 @@ type Head[BLOCK_HASH Hashable] interface { // If not in chain, returns the zero hash HashAtHeight(blockNum int64) BLOCK_HASH + // HeadAtHeight returns head at specified height or an error, if one does not exist in provided chain. + HeadAtHeight(blockNum int64) (Head[BLOCK_HASH], error) + // Returns the total difficulty of the block. For chains who do not have a concept of block // difficulty, return 0. BlockDifficulty() *big.Int diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go index 1234fd3893..102368199a 100644 --- a/common/types/mocks/head.go +++ b/common/types/mocks/head.go @@ -184,6 +184,36 @@ func (_m *Head[BLOCK_HASH]) HashAtHeight(blockNum int64) BLOCK_HASH { return r0 } +// HeadAtHeight provides a mock function with given fields: blockNum +func (_m *Head[BLOCK_HASH]) HeadAtHeight(blockNum int64) (types.Head[BLOCK_HASH], error) { + ret := _m.Called(blockNum) + + if len(ret) == 0 { + panic("no return value specified for HeadAtHeight") + } + + var r0 types.Head[BLOCK_HASH] + var r1 error + if rf, ok := ret.Get(0).(func(int64) (types.Head[BLOCK_HASH], error)); ok { + return rf(blockNum) + } + if rf, ok := ret.Get(0).(func(int64) types.Head[BLOCK_HASH]); ok { + r0 = rf(blockNum) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.Head[BLOCK_HASH]) + } + } + + if rf, ok := ret.Get(1).(func(int64) error); ok { + r1 = rf(blockNum) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // IsValid provides a mock function with given fields: func (_m *Head[BLOCK_HASH]) IsValid() bool { ret := _m.Called() diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index 8d1dcb6cc8..f18c900b03 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -60,6 +60,9 @@ type Client interface { HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) HeadByHash(ctx context.Context, n common.Hash) (*evmtypes.Head, error) SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error) + // LatestFinalizedBlock - returns the latest finalized block as it's returned from an RPC. + // CAUTION: Using this method might cause local finality violations. It's highly recommended + // to use HeadTracker to get latest finalized block. LatestFinalizedBlock(ctx context.Context) (head *evmtypes.Head, err error) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) @@ -132,6 +135,7 @@ func NewChainClient( chainID *big.Int, chainType chaintype.ChainType, clientErrors evmconfig.ClientErrors, + deathDeclarationDelay time.Duration, ) Client { multiNode := commonclient.NewMultiNode( lggr, @@ -146,6 +150,7 @@ func NewChainClient( return ClassifySendError(err, clientErrors, logger.Sugared(logger.Nop()), tx, common.Address{}, chainType.IsL2()) }, 0, // use the default value provided by the implementation + deathDeclarationDelay, ) return &chainClient{ multiNode: multiNode, @@ -306,12 +311,7 @@ func (c *chainClient) SubscribeFilterLogs(ctx context.Context, q ethereum.Filter } func (c *chainClient) SubscribeNewHead(ctx context.Context, ch chan<- *evmtypes.Head) (ethereum.Subscription, error) { - csf := newChainIDSubForwarder(c.ConfiguredChainID(), ch) - err := csf.start(c.multiNode.Subscribe(ctx, csf.srcCh, "newHeads")) - if err != nil { - return nil, err - } - return csf, nil + return c.multiNode.SubscribeNewHead(ctx, ch) } func (c *chainClient) SuggestGasPrice(ctx context.Context) (p *big.Int, err error) { diff --git a/core/chains/evm/client/chain_client_test.go b/core/chains/evm/client/chain_client_test.go index f18ec53967..33955c1645 100644 --- a/core/chains/evm/client/chain_client_test.go +++ b/core/chains/evm/client/chain_client_test.go @@ -751,7 +751,7 @@ func newMockRpc(t *testing.T) *mocks.RPCClient { mockRpc.On("Close").Return(nil).Once() mockRpc.On("ChainID", mock.Anything).Return(testutils.FixtureChainID, nil).Once() // node does not always manage to fully setup aliveLoop, so we have to make calls optional to avoid flakes - mockRpc.On("Subscribe", mock.Anything, mock.Anything, mock.Anything).Return(client.NewMockSubscription(), nil).Maybe() + mockRpc.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(client.NewMockSubscription(), nil).Maybe() mockRpc.On("SetAliveLoopSub", mock.Anything).Return().Maybe() return mockRpc } @@ -777,6 +777,7 @@ func TestChainClient_BatchCallContext(t *testing.T) { } mockRpc := newMockRpc(t) + mockRpc.On("GetInterceptedChainInfo").Return(commonclient.ChainInfo{}, commonclient.ChainInfo{}).Maybe() mockRpc.On("BatchCallContext", mock.Anything, b).Run(func(args mock.Arguments) { reqs := args.Get(1).([]rpc.BatchElem) for i := 0; i < len(reqs); i++ { diff --git a/core/chains/evm/client/chain_id_sub_test.go b/core/chains/evm/client/chain_id_sub_test.go deleted file mode 100644 index f959376acc..0000000000 --- a/core/chains/evm/client/chain_id_sub_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package client - -import ( - "errors" - "math/big" - "testing" - - "github.com/stretchr/testify/assert" - - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" -) - -func TestChainIDSubForwarder(t *testing.T) { - t.Parallel() - - chainID := big.NewInt(123) - - t.Run("unsubscribe forwarder", func(t *testing.T) { - t.Parallel() - - ch := make(chan *evmtypes.Head) - forwarder := newChainIDSubForwarder(chainID, ch) - sub := NewMockSubscription() - err := forwarder.start(sub, nil) - assert.NoError(t, err) - forwarder.Unsubscribe() - - assert.True(t, sub.unsubscribed) - _, ok := <-sub.Err() - assert.False(t, ok) - _, ok = <-forwarder.Err() - assert.False(t, ok) - }) - - t.Run("unsubscribe forwarder with error", func(t *testing.T) { - t.Parallel() - - ch := make(chan *evmtypes.Head) - forwarder := newChainIDSubForwarder(chainID, ch) - sub := NewMockSubscription() - err := forwarder.start(sub, nil) - assert.NoError(t, err) - sub.Errors <- errors.New("boo") - forwarder.Unsubscribe() - - assert.True(t, sub.unsubscribed) - _, ok := <-sub.Err() - assert.False(t, ok) - _, ok = <-forwarder.Err() - assert.False(t, ok) - }) - - t.Run("unsubscribe forwarder with message", func(t *testing.T) { - t.Parallel() - - ch := make(chan *evmtypes.Head) - forwarder := newChainIDSubForwarder(chainID, ch) - sub := NewMockSubscription() - err := forwarder.start(sub, nil) - assert.NoError(t, err) - forwarder.srcCh <- &evmtypes.Head{} - forwarder.Unsubscribe() - - assert.True(t, sub.unsubscribed) - _, ok := <-sub.Err() - assert.False(t, ok) - _, ok = <-forwarder.Err() - assert.False(t, ok) - }) - - t.Run("non nil error parameter", func(t *testing.T) { - t.Parallel() - - ch := make(chan *evmtypes.Head) - forwarder := newChainIDSubForwarder(chainID, ch) - sub := NewMockSubscription() - errIn := errors.New("foo") - errOut := forwarder.start(sub, errIn) - assert.Equal(t, errIn, errOut) - }) - - t.Run("forwarding", func(t *testing.T) { - t.Parallel() - - ch := make(chan *evmtypes.Head) - forwarder := newChainIDSubForwarder(chainID, ch) - sub := NewMockSubscription() - err := forwarder.start(sub, nil) - assert.NoError(t, err) - - head := &evmtypes.Head{ - ID: 1, - } - forwarder.srcCh <- head - receivedHead := <-ch - assert.Equal(t, head, receivedHead) - assert.Equal(t, ubig.New(chainID), receivedHead.EVMChainID) - - expectedErr := errors.New("error") - sub.Errors <- expectedErr - receivedErr := <-forwarder.Err() - assert.Equal(t, expectedErr, receivedErr) - }) -} diff --git a/core/chains/evm/client/config_builder.go b/core/chains/evm/client/config_builder.go index ae41d40dd3..19e0f14fd6 100644 --- a/core/chains/evm/client/config_builder.go +++ b/core/chains/evm/client/config_builder.go @@ -38,6 +38,9 @@ func NewClientConfigs( noNewHeadsThreshold time.Duration, finalityDepth *uint32, finalityTagEnabled *bool, + finalizedBlockOffset *uint32, + enforceRepeatableRead *bool, + deathDeclarationDelay time.Duration, ) (commonclient.ChainConfig, evmconfig.NodePool, []*toml.Node, error) { nodes, err := parseNodeConfigs(nodeCfgs) @@ -45,21 +48,24 @@ func NewClientConfigs( return nil, nil, nil, err } nodePool := toml.NodePool{ - SelectionMode: selectionMode, - LeaseDuration: commonconfig.MustNewDuration(leaseDuration), - PollFailureThreshold: pollFailureThreshold, - PollInterval: commonconfig.MustNewDuration(pollInterval), - SyncThreshold: syncThreshold, - NodeIsSyncingEnabled: nodeIsSyncingEnabled, + SelectionMode: selectionMode, + LeaseDuration: commonconfig.MustNewDuration(leaseDuration), + PollFailureThreshold: pollFailureThreshold, + PollInterval: commonconfig.MustNewDuration(pollInterval), + SyncThreshold: syncThreshold, + NodeIsSyncingEnabled: nodeIsSyncingEnabled, + EnforceRepeatableRead: enforceRepeatableRead, + DeathDeclarationDelay: commonconfig.MustNewDuration(deathDeclarationDelay), } nodePoolCfg := &evmconfig.NodePoolConfig{C: nodePool} chainConfig := &evmconfig.EVMConfig{ C: &toml.EVMConfig{ Chain: toml.Chain{ - ChainType: chaintype.NewChainTypeConfig(chainType), - FinalityDepth: finalityDepth, - FinalityTagEnabled: finalityTagEnabled, - NoNewHeadsThreshold: commonconfig.MustNewDuration(noNewHeadsThreshold), + ChainType: chaintype.NewChainTypeConfig(chainType), + FinalityDepth: finalityDepth, + FinalityTagEnabled: finalityTagEnabled, + NoNewHeadsThreshold: commonconfig.MustNewDuration(noNewHeadsThreshold), + FinalizedBlockOffset: finalizedBlockOffset, }, }, } diff --git a/core/chains/evm/client/config_builder_test.go b/core/chains/evm/client/config_builder_test.go index 0e24161b27..7c08bf18c1 100644 --- a/core/chains/evm/client/config_builder_test.go +++ b/core/chains/evm/client/config_builder_test.go @@ -23,6 +23,9 @@ func TestClientConfigBuilder(t *testing.T) { syncThreshold := ptr(uint32(5)) nodeIsSyncingEnabled := ptr(false) chainTypeStr := "" + finalizedBlockOffset := ptr[uint32](16) + enforceRepeatableRead := ptr(true) + deathDeclarationDelay := time.Second * 3 nodeConfigs := []client.NodeConfig{ { Name: ptr("foo"), @@ -34,7 +37,8 @@ func TestClientConfigBuilder(t *testing.T) { finalityTagEnabled := ptr(true) noNewHeadsThreshold := time.Second chainCfg, nodePool, nodes, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, - pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, finalityTagEnabled) + pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, + finalityTagEnabled, finalizedBlockOffset, enforceRepeatableRead, deathDeclarationDelay) require.NoError(t, err) // Validate node pool configs @@ -44,6 +48,8 @@ func TestClientConfigBuilder(t *testing.T) { require.Equal(t, pollInterval, nodePool.PollInterval()) require.Equal(t, *syncThreshold, nodePool.SyncThreshold()) require.Equal(t, *nodeIsSyncingEnabled, nodePool.NodeIsSyncingEnabled()) + require.Equal(t, *enforceRepeatableRead, nodePool.EnforceRepeatableRead()) + require.Equal(t, deathDeclarationDelay, nodePool.DeathDeclarationDelay()) // Validate node configs require.Equal(t, *nodeConfigs[0].Name, *nodes[0].Name) @@ -54,6 +60,7 @@ func TestClientConfigBuilder(t *testing.T) { require.Equal(t, noNewHeadsThreshold, chainCfg.NodeNoNewHeadsThreshold()) require.Equal(t, *finalityDepth, chainCfg.FinalityDepth()) require.Equal(t, *finalityTagEnabled, chainCfg.FinalityTagEnabled()) + require.Equal(t, *finalizedBlockOffset, chainCfg.FinalizedBlockOffset()) // let combiler tell us, when we do not have sufficient data to create evm client _ = client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), big.NewInt(10), nodes, chaintype.ChainType(chainTypeStr)) diff --git a/core/chains/evm/client/evm_client.go b/core/chains/evm/client/evm_client.go index 4d30944059..fd7fa5868a 100644 --- a/core/chains/evm/client/evm_client.go +++ b/core/chains/evm/client/evm_client.go @@ -35,5 +35,5 @@ func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, cli } return NewChainClient(lggr, cfg.SelectionMode(), cfg.LeaseDuration(), chainCfg.NodeNoNewHeadsThreshold(), - primaries, sendonlys, chainID, chainType, clientErrors) + primaries, sendonlys, chainID, chainType, clientErrors, cfg.DeathDeclarationDelay()) } diff --git a/core/chains/evm/client/evm_client_test.go b/core/chains/evm/client/evm_client_test.go index 29113d4c3c..9ad25f9602 100644 --- a/core/chains/evm/client/evm_client_test.go +++ b/core/chains/evm/client/evm_client_test.go @@ -24,6 +24,9 @@ func TestNewEvmClient(t *testing.T) { syncThreshold := ptr(uint32(5)) nodeIsSyncingEnabled := ptr(false) chainTypeStr := "" + finalizedBlockOffset := ptr[uint32](16) + enforceRepeatableRead := ptr(true) + deathDeclarationDelay := time.Second * 3 nodeConfigs := []client.NodeConfig{ { Name: ptr("foo"), @@ -34,7 +37,8 @@ func TestNewEvmClient(t *testing.T) { finalityDepth := ptr(uint32(10)) finalityTagEnabled := ptr(true) chainCfg, nodePool, nodes, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, - pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, finalityTagEnabled) + pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, + finalityTagEnabled, finalizedBlockOffset, enforceRepeatableRead, deathDeclarationDelay) require.NoError(t, err) client := client.NewEvmClient(nodePool, chainCfg, nil, logger.Test(t), testutils.FixtureChainID, nodes, chaintype.ChainType(chainTypeStr)) diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index 391d580c1f..e1017a5564 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -87,6 +87,8 @@ type TestNodePoolConfig struct { NodeIsSyncingEnabledVal bool NodeFinalizedBlockPollInterval time.Duration NodeErrors config.ClientErrors + EnforceRepeatableReadVal bool + NodeDeathDeclarationDelay time.Duration } func (tc TestNodePoolConfig) PollFailureThreshold() uint32 { return tc.NodePollFailureThreshold } @@ -109,6 +111,14 @@ func (tc TestNodePoolConfig) Errors() config.ClientErrors { return tc.NodeErrors } +func (tc TestNodePoolConfig) EnforceRepeatableRead() bool { + return tc.EnforceRepeatableReadVal +} + +func (tc TestNodePoolConfig) DeathDeclarationDelay() time.Duration { + return tc.NodeDeathDeclarationDelay +} + func NewChainClientWithTestNode( t *testing.T, nodeCfg commonclient.NodeConfig, @@ -150,7 +160,7 @@ func NewChainClientWithTestNode( var chainType chaintype.ChainType clientErrors := NewTestClientErrors() - c := NewChainClient(lggr, nodeCfg.SelectionMode(), leaseDuration, noNewHeadsThreshold, primaries, sendonlys, chainID, chainType, &clientErrors) + c := NewChainClient(lggr, nodeCfg.SelectionMode(), leaseDuration, noNewHeadsThreshold, primaries, sendonlys, chainID, chainType, &clientErrors, 0) t.Cleanup(c.Close) return c, nil } @@ -165,7 +175,7 @@ func NewChainClientWithEmptyNode( lggr := logger.Test(t) var chainType chaintype.ChainType - c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, nil, nil, chainID, chainType, nil) + c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, nil, nil, chainID, chainType, nil, 0) t.Cleanup(c.Close) return c } @@ -191,7 +201,7 @@ func NewChainClientWithMockedRpc( cfg, clientMocks.ChainConfig{NoNewHeadsThresholdVal: noNewHeadsThreshold}, lggr, *parsed, nil, "eth-primary-node-0", 1, chainID, 1, rpc, "EVM") primaries := []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient]{n} clientErrors := NewTestClientErrors() - c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, primaries, nil, chainID, chainType, &clientErrors) + c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, primaries, nil, chainID, chainType, &clientErrors, 0) t.Cleanup(c.Close) return c } diff --git a/core/chains/evm/client/mocks/rpc_client.go b/core/chains/evm/client/mocks/rpc_client.go index 1c39d22136..e6cb07af2f 100644 --- a/core/chains/evm/client/mocks/rpc_client.go +++ b/core/chains/evm/client/mocks/rpc_client.go @@ -9,6 +9,8 @@ import ( common "github.com/ethereum/go-ethereum/common" + commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + commontypes "github.com/smartcontractkit/chainlink/v2/common/types" context "context" @@ -442,6 +444,34 @@ func (_m *RPCClient) FilterEvents(ctx context.Context, query ethereum.FilterQuer return r0, r1 } +// GetInterceptedChainInfo provides a mock function with given fields: +func (_m *RPCClient) GetInterceptedChainInfo() (commonclient.ChainInfo, commonclient.ChainInfo) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetInterceptedChainInfo") + } + + var r0 commonclient.ChainInfo + var r1 commonclient.ChainInfo + if rf, ok := ret.Get(0).(func() (commonclient.ChainInfo, commonclient.ChainInfo)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() commonclient.ChainInfo); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(commonclient.ChainInfo) + } + + if rf, ok := ret.Get(1).(func() commonclient.ChainInfo); ok { + r1 = rf() + } else { + r1 = ret.Get(1).(commonclient.ChainInfo) + } + + return r0, r1 +} + // HeaderByHash provides a mock function with given fields: ctx, h func (_m *RPCClient) HeaderByHash(ctx context.Context, h common.Hash) (*coretypes.Header, error) { ret := _m.Called(ctx, h) @@ -805,32 +835,29 @@ func (_m *RPCClient) SimulateTransaction(ctx context.Context, tx *coretypes.Tran return r0 } -// Subscribe provides a mock function with given fields: ctx, channel, args -func (_m *RPCClient) Subscribe(ctx context.Context, channel chan<- *types.Head, args ...interface{}) (commontypes.Subscription, error) { - var _ca []interface{} - _ca = append(_ca, ctx, channel) - _ca = append(_ca, args...) - ret := _m.Called(_ca...) +// SubscribeFilterLogs provides a mock function with given fields: ctx, q, ch +func (_m *RPCClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- coretypes.Log) (ethereum.Subscription, error) { + ret := _m.Called(ctx, q, ch) if len(ret) == 0 { - panic("no return value specified for Subscribe") + panic("no return value specified for SubscribeFilterLogs") } - var r0 commontypes.Subscription + var r0 ethereum.Subscription var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan<- *types.Head, ...interface{}) (commontypes.Subscription, error)); ok { - return rf(ctx, channel, args...) + if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) (ethereum.Subscription, error)); ok { + return rf(ctx, q, ch) } - if rf, ok := ret.Get(0).(func(context.Context, chan<- *types.Head, ...interface{}) commontypes.Subscription); ok { - r0 = rf(ctx, channel, args...) + if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) ethereum.Subscription); ok { + r0 = rf(ctx, q, ch) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(commontypes.Subscription) + r0 = ret.Get(0).(ethereum.Subscription) } } - if rf, ok := ret.Get(1).(func(context.Context, chan<- *types.Head, ...interface{}) error); ok { - r1 = rf(ctx, channel, args...) + if rf, ok := ret.Get(1).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) error); ok { + r1 = rf(ctx, q, ch) } else { r1 = ret.Error(1) } @@ -838,29 +865,29 @@ func (_m *RPCClient) Subscribe(ctx context.Context, channel chan<- *types.Head, return r0, r1 } -// SubscribeFilterLogs provides a mock function with given fields: ctx, q, ch -func (_m *RPCClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- coretypes.Log) (ethereum.Subscription, error) { - ret := _m.Called(ctx, q, ch) +// SubscribeNewHead provides a mock function with given fields: ctx, channel +func (_m *RPCClient) SubscribeNewHead(ctx context.Context, channel chan<- *types.Head) (commontypes.Subscription, error) { + ret := _m.Called(ctx, channel) if len(ret) == 0 { - panic("no return value specified for SubscribeFilterLogs") + panic("no return value specified for SubscribeNewHead") } - var r0 ethereum.Subscription + var r0 commontypes.Subscription var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) (ethereum.Subscription, error)); ok { - return rf(ctx, q, ch) + if rf, ok := ret.Get(0).(func(context.Context, chan<- *types.Head) (commontypes.Subscription, error)); ok { + return rf(ctx, channel) } - if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) ethereum.Subscription); ok { - r0 = rf(ctx, q, ch) + if rf, ok := ret.Get(0).(func(context.Context, chan<- *types.Head) commontypes.Subscription); ok { + r0 = rf(ctx, channel) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(ethereum.Subscription) + r0 = ret.Get(0).(commontypes.Subscription) } } - if rf, ok := ret.Get(1).(func(context.Context, ethereum.FilterQuery, chan<- coretypes.Log) error); ok { - r1 = rf(ctx, q, ch) + if rf, ok := ret.Get(1).(func(context.Context, chan<- *types.Head) error); ok { + r1 = rf(ctx, channel) } else { r1 = ret.Error(1) } diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 5b64900a0c..6499b18f79 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -101,6 +101,7 @@ type RPCClient interface { SuggestGasPrice(ctx context.Context) (p *big.Int, err error) 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) } type rawclient struct { @@ -132,6 +133,11 @@ type rpcClient struct { // this rpcClient. Closing and replacing should be serialized through // stateMu since it can happen on state transitions as well as rpcClient Close. chStopInFlight chan struct{} + + // 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) + latestChainInfo commonclient.ChainInfo } // NewRPCCLient returns a new *rpcClient as commonclient.RPC @@ -289,21 +295,32 @@ func (r *rpcClient) getRPCDomain() string { } // registerSub adds the sub to the rpcClient list -func (r *rpcClient) registerSub(sub ethereum.Subscription) { +func (r *rpcClient) registerSub(sub ethereum.Subscription, stopInFLightCh chan struct{}) error { r.stateMu.Lock() defer r.stateMu.Unlock() + // ensure that the `sub` belongs to current life cycle of the `rpcClient` and it should not be killed due to + // previous `DisconnectAll` call. + select { + case <-stopInFLightCh: + sub.Unsubscribe() + return fmt.Errorf("failed to register subscription - all in-flight requests were canceled") + default: + } + // TODO: BCI-3358 - delete sub when caller unsubscribes. r.subs = append(r.subs, sub) + return nil } -// disconnectAll disconnects all clients connected to the rpcClient -// WARNING: NOT THREAD-SAFE -// This must be called from within the r.stateMu lock +// DisconnectAll disconnects all clients connected to the rpcClient func (r *rpcClient) DisconnectAll() { + r.stateMu.Lock() + defer r.stateMu.Unlock() if r.ws.rpc != nil { r.ws.rpc.Close() } r.cancelInflightRequests() r.unsubscribeAll() + r.latestChainInfo = commonclient.ChainInfo{} } // unsubscribeAll unsubscribes all subscriptions @@ -388,24 +405,35 @@ func (r *rpcClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) err return err } -func (r *rpcClient) Subscribe(ctx context.Context, channel chan<- *evmtypes.Head, args ...interface{}) (commontypes.Subscription, error) { - ctx, cancel, ws, _ := r.makeLiveQueryCtxAndSafeGetClients(ctx) +func (r *rpcClient) SubscribeNewHead(ctx context.Context, channel chan<- *evmtypes.Head) (_ commontypes.Subscription, err error) { + ctx, cancel, chStopInFlight, ws, _ := r.acquireQueryCtx(ctx) defer cancel() + args := []interface{}{"newHeads"} lggr := r.newRqLggr().With("args", args) lggr.Debug("RPC call: evmclient.Client#EthSubscribe") start := time.Now() - var sub commontypes.Subscription - sub, err := ws.rpc.EthSubscribe(ctx, channel, args...) - if err == nil { - sub = newSubscriptionErrorWrapper(sub, r.rpcClientErrorPrefix()) - r.registerSub(sub) + defer func() { + duration := time.Since(start) + r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe") + err = r.wrapWS(err) + }() + subForwarder := newSubForwarder(channel, func(head *evmtypes.Head) *evmtypes.Head { + head.EVMChainID = ubig.New(r.chainID) + r.onNewHead(ctx, chStopInFlight, head) + return head + }, r.wrapRPCClientError) + err = subForwarder.start(ws.rpc.EthSubscribe(ctx, subForwarder.srcCh, args...)) + if err != nil { + return } - duration := time.Since(start) - r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe") + err = r.registerSub(subForwarder, chStopInFlight) + if err != nil { + return + } - return sub, r.wrapWS(err) + return subForwarder, nil } // GethClient wrappers @@ -513,7 +541,7 @@ func (r *rpcClient) HeaderByHash(ctx context.Context, hash common.Hash) (header return } -func (r *rpcClient) LatestFinalizedBlock(ctx context.Context) (head *evmtypes.Head, err error) { +func (r *rpcClient) LatestFinalizedBlock(ctx context.Context) (*evmtypes.Head, error) { return r.blockByNumber(ctx, rpc.FinalizedBlockNumber.String()) } @@ -523,7 +551,25 @@ func (r *rpcClient) BlockByNumber(ctx context.Context, number *big.Int) (head *e } func (r *rpcClient) blockByNumber(ctx context.Context, number string) (head *evmtypes.Head, err error) { - err = r.CallContext(ctx, &head, "eth_getBlockByNumber", number, false) + ctx, cancel, chStopInFlight, ws, http := r.acquireQueryCtx(ctx) + defer cancel() + const method = "eth_getBlockByNumber" + args := []interface{}{number, false} + lggr := r.newRqLggr().With( + "method", method, + "args", args, + ) + + lggr.Debug("RPC call: evmclient.Client#CallContext") + start := time.Now() + if http != nil { + err = r.wrapHTTP(http.rpc.CallContext(ctx, &head, method, args...)) + } else { + err = r.wrapWS(ws.rpc.CallContext(ctx, &head, method, args...)) + } + duration := time.Since(start) + + r.logResult(lggr, err, duration, r.getRPCDomain(), "CallContext") if err != nil { return nil, err } @@ -532,6 +578,14 @@ func (r *rpcClient) blockByNumber(ctx context.Context, number string) (head *evm return } head.EVMChainID = ubig.New(r.chainID) + + switch number { + case rpc.FinalizedBlockNumber.String(): + r.onNewFinalizedHead(ctx, chStopInFlight, head) + case rpc.LatestBlockNumber.String(): + r.onNewHead(ctx, chStopInFlight, head) + } + return } @@ -958,24 +1012,30 @@ func (r *rpcClient) ClientVersion(ctx context.Context) (version string, err erro return } -func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (sub ethereum.Subscription, err error) { - ctx, cancel, ws, _ := r.makeLiveQueryCtxAndSafeGetClients(ctx) +func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (_ ethereum.Subscription, err error) { + ctx, cancel, chStopInFlight, ws, _ := r.acquireQueryCtx(ctx) defer cancel() lggr := r.newRqLggr().With("q", q) lggr.Debug("RPC call: evmclient.Client#SubscribeFilterLogs") start := time.Now() - sub, err = ws.geth.SubscribeFilterLogs(ctx, q, ch) - if err == nil { - sub = newSubscriptionErrorWrapper(sub, r.rpcClientErrorPrefix()) - r.registerSub(sub) + defer func() { + duration := time.Since(start) + r.logResult(lggr, err, duration, r.getRPCDomain(), "SubscribeFilterLogs") + err = r.wrapWS(err) + }() + sub := newSubForwarder(ch, nil, r.wrapRPCClientError) + err = sub.start(ws.geth.SubscribeFilterLogs(ctx, q, sub.srcCh)) + if err != nil { + return } - err = r.wrapWS(err) - duration := time.Since(start) - r.logResult(lggr, err, duration, r.getRPCDomain(), "SubscribeFilterLogs") + err = r.registerSub(sub, chStopInFlight) + if err != nil { + return + } - return + return sub, nil } func (r *rpcClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err error) { @@ -1060,17 +1120,23 @@ func (r *rpcClient) wrapHTTP(err error) error { // makeLiveQueryCtxAndSafeGetClients wraps makeQueryCtx func (r *rpcClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context) (ctx context.Context, cancel context.CancelFunc, ws rawclient, http *rawclient) { + ctx, cancel, _, ws, http = r.acquireQueryCtx(parentCtx) + return +} + +func (r *rpcClient) acquireQueryCtx(parentCtx context.Context) (ctx context.Context, cancel context.CancelFunc, + chStopInFlight chan struct{}, ws rawclient, http *rawclient) { // Need to wrap in mutex because state transition can cancel and replace the // context r.stateMu.RLock() - cancelCh := r.chStopInFlight + chStopInFlight = r.chStopInFlight ws = r.ws if r.http != nil { cp := *r.http http = &cp } r.stateMu.RUnlock() - ctx, cancel = makeQueryCtx(parentCtx, cancelCh) + ctx, cancel = makeQueryCtx(parentCtx, chStopInFlight) return } @@ -1134,6 +1200,49 @@ func Name(r *rpcClient) string { return r.name } +func (r *rpcClient) onNewHead(ctx context.Context, requestCh <-chan struct{}, head *evmtypes.Head) { + if head == nil { + return + } + + r.stateMu.Lock() + defer r.stateMu.Unlock() + if !commonclient.CtxIsHeathCheckRequest(ctx) { + r.highestUserObservations.BlockNumber = max(r.highestUserObservations.BlockNumber, head.Number) + r.highestUserObservations.TotalDifficulty = commonclient.MaxTotalDifficulty(r.highestUserObservations.TotalDifficulty, head.TotalDifficulty) + } + select { + case <-requestCh: // no need to update latestChainInfo, as rpcClient already started new life cycle + return + default: + r.latestChainInfo.BlockNumber = head.Number + r.latestChainInfo.TotalDifficulty = head.TotalDifficulty + } +} + +func (r *rpcClient) onNewFinalizedHead(ctx context.Context, requestCh <-chan struct{}, head *evmtypes.Head) { + if head == nil { + return + } + r.stateMu.Lock() + defer r.stateMu.Unlock() + if !commonclient.CtxIsHeathCheckRequest(ctx) { + r.highestUserObservations.FinalizedBlockNumber = max(r.highestUserObservations.FinalizedBlockNumber, head.Number) + } + select { + case <-requestCh: // no need to update latestChainInfo, as rpcClient already started new life cycle + return + default: + r.latestChainInfo.FinalizedBlockNumber = head.Number + } +} + +func (r *rpcClient) GetInterceptedChainInfo() (latest, highestUserObservations commonclient.ChainInfo) { + r.stateMu.RLock() + defer r.stateMu.RUnlock() + return r.latestChainInfo, r.highestUserObservations +} + func ToBlockNumArg(number *big.Int) string { if number == nil { return "latest" diff --git a/core/chains/evm/client/rpc_client_test.go b/core/chains/evm/client/rpc_client_test.go new file mode 100644 index 0000000000..682c435245 --- /dev/null +++ b/core/chains/evm/client/rpc_client_test.go @@ -0,0 +1,300 @@ +package client_test + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "net/url" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" + "go.uber.org/zap" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +func makeNewHeadWSMessage(head *evmtypes.Head) string { + asJSON, err := json.Marshal(head) + if err != nil { + panic(fmt.Errorf("failed to marshal head: %w", err)) + } + return fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x00","result":%s}}`, string(asJSON)) +} + +func TestRPCClient_SubscribeNewHead(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithTimeout(tests.Context(t), tests.WaitTimeout(t)) + defer cancel() + + chainId := big.NewInt(123456) + lggr := logger.Test(t) + + serverCallBack := func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + if method == "eth_unsubscribe" { + resp.Result = "true" + return + } + assert.Equal(t, "eth_subscribe", method) + if assert.True(t, params.IsArray()) && assert.Equal(t, "newHeads", params.Array()[0].String()) { + resp.Result = `"0x00"` + } + return + } + t.Run("Updates chain info on new blocks", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary) + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + // set to default values + latest, highestUserObservations := rpc.GetInterceptedChainInfo() + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(0), latest.FinalizedBlockNumber) + assert.Nil(t, latest.TotalDifficulty) + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) + assert.Nil(t, highestUserObservations.TotalDifficulty) + + ch := make(chan *evmtypes.Head) + sub, err := rpc.SubscribeNewHead(tests.Context(t), ch) + require.NoError(t, err) + defer sub.Unsubscribe() + go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)})) + // received 256 head + <-ch + go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 128, TotalDifficulty: big.NewInt(500)})) + // received 128 head + <-ch + + latest, highestUserObservations = rpc.GetInterceptedChainInfo() + assert.Equal(t, int64(128), latest.BlockNumber) + assert.Equal(t, int64(0), latest.FinalizedBlockNumber) + assert.Equal(t, big.NewInt(500), latest.TotalDifficulty) + + assertHighestUserObservations := func(highestUserObservations commonclient.ChainInfo) { + assert.Equal(t, int64(256), highestUserObservations.BlockNumber) + assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) + assert.Equal(t, big.NewInt(1000), highestUserObservations.TotalDifficulty) + } + + assertHighestUserObservations(highestUserObservations) + + // DisconnectAll resets latest + rpc.DisconnectAll() + + latest, highestUserObservations = rpc.GetInterceptedChainInfo() + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(0), latest.FinalizedBlockNumber) + assert.Nil(t, latest.TotalDifficulty) + + assertHighestUserObservations(highestUserObservations) + }) + t.Run("App layer observations are not affected by new block if health check flag is present", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary) + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + ch := make(chan *evmtypes.Head) + sub, err := rpc.SubscribeNewHead(commonclient.CtxAddHealthCheckFlag(tests.Context(t)), ch) + require.NoError(t, err) + defer sub.Unsubscribe() + go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)})) + // received 256 head + <-ch + + latest, highestUserObservations := rpc.GetInterceptedChainInfo() + assert.Equal(t, int64(256), latest.BlockNumber) + assert.Equal(t, int64(0), latest.FinalizedBlockNumber) + assert.Equal(t, big.NewInt(1000), latest.TotalDifficulty) + + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) + assert.Equal(t, (*big.Int)(nil), highestUserObservations.TotalDifficulty) + }) + t.Run("Block's chain ID matched configured", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary) + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + ch := make(chan *evmtypes.Head) + sub, err := rpc.SubscribeNewHead(tests.Context(t), ch) + require.NoError(t, err) + defer sub.Unsubscribe() + go server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256})) + head := <-ch + require.Equal(t, chainId, head.ChainID()) + }) + t.Run("Failed SubscribeNewHead returns and logs proper error", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, func(reqMethod string, reqParams gjson.Result) (resp testutils.JSONRPCResponse) { + return resp + }) + wsURL := server.WSURL() + observedLggr, observed := logger.TestObserved(t, zap.DebugLevel) + rpc := client.NewRPCClient(observedLggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary) + require.NoError(t, rpc.Dial(ctx)) + server.Close() + _, err := rpc.SubscribeNewHead(ctx, make(chan *evmtypes.Head)) + require.ErrorContains(t, err, "RPCClient returned error (rpc)") + tests.AssertLogEventually(t, observed, "evmclient.Client#EthSubscribe RPC call failure") + }) + t.Run("Subscription error is properly wrapper", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary) + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + sub, err := rpc.SubscribeNewHead(ctx, make(chan *evmtypes.Head)) + require.NoError(t, err) + go server.MustWriteBinaryMessageSync(t, "invalid msg") + select { + case err = <-sub.Err(): + require.ErrorContains(t, err, "RPCClient returned error (rpc): invalid character") + case <-ctx.Done(): + t.Errorf("Expected subscription to return an error, but test timeout instead") + } + }) +} + +func TestRPCClient_SubscribeFilterLogs(t *testing.T) { + t.Parallel() + + chainId := big.NewInt(123456) + lggr := logger.Test(t) + ctx, cancel := context.WithTimeout(tests.Context(t), tests.WaitTimeout(t)) + defer cancel() + t.Run("Failed SubscribeFilterLogs logs and returns proper error", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, func(reqMethod string, reqParams gjson.Result) (resp testutils.JSONRPCResponse) { + return resp + }) + wsURL := server.WSURL() + observedLggr, observed := logger.TestObserved(t, zap.DebugLevel) + rpc := client.NewRPCClient(observedLggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary) + require.NoError(t, rpc.Dial(ctx)) + server.Close() + _, err := rpc.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) + require.ErrorContains(t, err, "RPCClient returned error (rpc)") + tests.AssertLogEventually(t, observed, "evmclient.Client#SubscribeFilterLogs RPC call failure") + }) + t.Run("Subscription error is properly wrapper", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + assert.Equal(t, "eth_subscribe", method) + if assert.True(t, params.IsArray()) && assert.Equal(t, "logs", params.Array()[0].String()) { + resp.Result = `"0x00"` + resp.Notify = "{}" + } + return resp + }) + wsURL := server.WSURL() + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary) + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + sub, err := rpc.SubscribeFilterLogs(ctx, ethereum.FilterQuery{}, make(chan types.Log)) + require.NoError(t, err) + go server.MustWriteBinaryMessageSync(t, "invalid msg") + errorCtx, cancel := context.WithTimeout(ctx, tests.DefaultWaitTimeout) + defer cancel() + select { + case err = <-sub.Err(): + require.ErrorContains(t, err, "RPCClient returned error (rpc): invalid character") + case <-errorCtx.Done(): + t.Errorf("Expected subscription to return an error, but test timeout instead") + } + }) +} + +func TestRPCClient_LatestFinalizedBlock(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithTimeout(tests.Context(t), tests.WaitTimeout(t)) + defer cancel() + + chainId := big.NewInt(123456) + lggr := logger.Test(t) + + type rpcServer struct { + Head *evmtypes.Head + URL *url.URL + } + createRPCServer := func() *rpcServer { + server := &rpcServer{} + server.URL = testutils.NewWSServer(t, chainId, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + assert.Equal(t, "eth_getBlockByNumber", method) + if assert.True(t, params.IsArray()) && assert.Equal(t, "finalized", params.Array()[0].String()) { + head := server.Head + jsonHead, err := json.Marshal(head) + if err != nil { + panic(fmt.Errorf("failed to marshal head: %w", err)) + } + resp.Result = string(jsonHead) + } + + return + }).WSURL() + + return server + } + + server := createRPCServer() + rpc := client.NewRPCClient(lggr, *server.URL, nil, "rpc", 1, chainId, commonclient.Primary) + require.NoError(t, rpc.Dial(ctx)) + defer rpc.Close() + server.Head = &evmtypes.Head{Number: 128} + // updates chain info + _, err := rpc.LatestFinalizedBlock(ctx) + require.NoError(t, err) + latest, highestUserObservations := rpc.GetInterceptedChainInfo() + + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + assert.Equal(t, int64(128), highestUserObservations.FinalizedBlockNumber) + + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(128), latest.FinalizedBlockNumber) + + // lower block number does not update highestUserObservations + server.Head = &evmtypes.Head{Number: 127} + _, err = rpc.LatestFinalizedBlock(ctx) + require.NoError(t, err) + latest, highestUserObservations = rpc.GetInterceptedChainInfo() + + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + assert.Equal(t, int64(128), highestUserObservations.FinalizedBlockNumber) + + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(127), latest.FinalizedBlockNumber) + + // health check flg prevents change in highestUserObservations + server.Head = &evmtypes.Head{Number: 256} + _, err = rpc.LatestFinalizedBlock(commonclient.CtxAddHealthCheckFlag(ctx)) + require.NoError(t, err) + latest, highestUserObservations = rpc.GetInterceptedChainInfo() + + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + assert.Equal(t, int64(128), highestUserObservations.FinalizedBlockNumber) + + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(256), latest.FinalizedBlockNumber) + + // DisconnectAll resets latest ChainInfo + rpc.DisconnectAll() + latest, highestUserObservations = rpc.GetInterceptedChainInfo() + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + assert.Equal(t, int64(128), highestUserObservations.FinalizedBlockNumber) + + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(0), latest.FinalizedBlockNumber) +} diff --git a/core/chains/evm/client/sub_error_wrapper.go b/core/chains/evm/client/sub_error_wrapper.go deleted file mode 100644 index 689991ce70..0000000000 --- a/core/chains/evm/client/sub_error_wrapper.go +++ /dev/null @@ -1,77 +0,0 @@ -package client - -import ( - "fmt" - - commontypes "github.com/smartcontractkit/chainlink/v2/common/types" -) - -// subErrorWrapper - adds specified prefix to a subscription error -type subErrorWrapper struct { - sub commontypes.Subscription - errorPrefix string - - done chan struct{} - unSub chan struct{} - errorCh chan error -} - -func newSubscriptionErrorWrapper(sub commontypes.Subscription, errorPrefix string) *subErrorWrapper { - s := &subErrorWrapper{ - sub: sub, - errorPrefix: errorPrefix, - done: make(chan struct{}), - unSub: make(chan struct{}), - errorCh: make(chan error), - } - - go func() { - for { - select { - // sub.Err channel is closed by sub.Unsubscribe - case err, ok := <-sub.Err(): - if !ok { - // might only happen if someone terminated wrapped subscription - // in any case - do our best to release resources - // we can't call Unsubscribe on root sub as this might cause panic - close(s.errorCh) - close(s.done) - return - } - - select { - case s.errorCh <- fmt.Errorf("%s: %w", s.errorPrefix, err): - case <-s.unSub: - s.close() - return - } - case <-s.unSub: - s.close() - return - } - } - }() - - return s -} - -func (s *subErrorWrapper) close() { - s.sub.Unsubscribe() - close(s.errorCh) - close(s.done) -} - -func (s *subErrorWrapper) Unsubscribe() { - select { - // already unsubscribed - case <-s.done: - // signal unsubscribe - case s.unSub <- struct{}{}: - // wait for unsubscribe to complete - <-s.done - } -} - -func (s *subErrorWrapper) Err() <-chan error { - return s.errorCh -} diff --git a/core/chains/evm/client/sub_error_wrapper_test.go b/core/chains/evm/client/sub_error_wrapper_test.go deleted file mode 100644 index 5dd8106957..0000000000 --- a/core/chains/evm/client/sub_error_wrapper_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package client - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" -) - -func TestSubscriptionErrorWrapper(t *testing.T) { - t.Parallel() - t.Run("Unsubscribe wrapper releases resources", func(t *testing.T) { - t.Parallel() - - mockedSub := NewMockSubscription() - const prefix = "RPC returned error" - wrapper := newSubscriptionErrorWrapper(mockedSub, prefix) - wrapper.Unsubscribe() - - // mock's resources were relased - assert.True(t, mockedSub.unsubscribed) - _, ok := <-mockedSub.Err() - assert.False(t, ok) - // wrapper's channels are closed - _, ok = <-wrapper.Err() - assert.False(t, ok) - // subsequence unsubscribe does not causes panic - wrapper.Unsubscribe() - }) - t.Run("Unsubscribe interrupts error delivery", func(t *testing.T) { - t.Parallel() - sub := NewMockSubscription() - const prefix = "RPC returned error" - wrapper := newSubscriptionErrorWrapper(sub, prefix) - sub.Errors <- fmt.Errorf("error") - - wrapper.Unsubscribe() - _, ok := <-wrapper.Err() - assert.False(t, ok) - }) - t.Run("Successfully wraps error", func(t *testing.T) { - t.Parallel() - sub := NewMockSubscription() - const prefix = "RPC returned error" - wrapper := newSubscriptionErrorWrapper(sub, prefix) - sub.Errors <- fmt.Errorf("root error") - - err, ok := <-wrapper.Err() - assert.True(t, ok) - assert.Equal(t, "RPC returned error: root error", err.Error()) - - wrapper.Unsubscribe() - _, ok = <-wrapper.Err() - assert.False(t, ok) - }) - t.Run("Unsubscribe on root does not cause panic", func(t *testing.T) { - t.Parallel() - mockedSub := NewMockSubscription() - wrapper := newSubscriptionErrorWrapper(mockedSub, "") - - mockedSub.Unsubscribe() - // mock's resources were released - assert.True(t, mockedSub.unsubscribed) - _, ok := <-mockedSub.Err() - assert.False(t, ok) - // wrapper's channels are eventually closed - tests.AssertEventually(t, func() bool { - _, ok = <-wrapper.Err() - return !ok - }) - }) -} diff --git a/core/chains/evm/client/chain_id_sub.go b/core/chains/evm/client/sub_forwarder.go similarity index 51% rename from core/chains/evm/client/chain_id_sub.go rename to core/chains/evm/client/sub_forwarder.go index c3162b300c..93e9b106b4 100644 --- a/core/chains/evm/client/chain_id_sub.go +++ b/core/chains/evm/client/sub_forwarder.go @@ -1,42 +1,40 @@ package client import ( - "math/big" - "github.com/ethereum/go-ethereum" - - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) -var _ ethereum.Subscription = &chainIDSubForwarder{} +var _ ethereum.Subscription = &subForwarder[any]{} -// chainIDSubForwarder wraps a head subscription in order to intercept and augment each head with chainID before forwarding. -type chainIDSubForwarder struct { - chainID *big.Int - destCh chan<- *evmtypes.Head +// subForwarder wraps a subscription in order to intercept and augment each result before forwarding. +type subForwarder[T any] struct { + destCh chan<- T - srcCh chan *evmtypes.Head + srcCh chan T srcSub ethereum.Subscription + interceptResult func(T) T + interceptError func(error) error + done chan struct{} err chan error unSub chan struct{} } -func newChainIDSubForwarder(chainID *big.Int, ch chan<- *evmtypes.Head) *chainIDSubForwarder { - return &chainIDSubForwarder{ - chainID: chainID, - destCh: ch, - srcCh: make(chan *evmtypes.Head), - done: make(chan struct{}), - err: make(chan error), - unSub: make(chan struct{}, 1), +func newSubForwarder[T any](destCh chan<- T, interceptResult func(T) T, interceptError func(error) error) *subForwarder[T] { + return &subForwarder[T]{ + interceptResult: interceptResult, + interceptError: interceptError, + destCh: destCh, + srcCh: make(chan T), + done: make(chan struct{}), + err: make(chan error), + unSub: make(chan struct{}, 1), } } // start spawns the forwarding loop for sub. -func (c *chainIDSubForwarder) start(sub ethereum.Subscription, err error) error { +func (c *subForwarder[T]) start(sub ethereum.Subscription, err error) error { if err != nil { close(c.srcCh) return err @@ -48,7 +46,7 @@ func (c *chainIDSubForwarder) start(sub ethereum.Subscription, err error) error // forwardLoop receives from src, adds the chainID, and then sends to dest. // It also handles Unsubscribing, which may interrupt either forwarding operation. -func (c *chainIDSubForwarder) forwardLoop() { +func (c *subForwarder[T]) forwardLoop() { // the error channel must be closed when unsubscribing defer close(c.err) defer close(c.done) @@ -56,6 +54,9 @@ func (c *chainIDSubForwarder) forwardLoop() { for { select { case err := <-c.srcSub.Err(): + if c.interceptError != nil { + err = c.interceptError(err) + } select { case c.err <- err: case <-c.unSub: @@ -64,7 +65,9 @@ func (c *chainIDSubForwarder) forwardLoop() { return case h := <-c.srcCh: - h.EVMChainID = ubig.New(c.chainID) + if c.interceptResult != nil { + h = c.interceptResult(h) + } select { case c.destCh <- h: case <-c.unSub: @@ -79,7 +82,7 @@ func (c *chainIDSubForwarder) forwardLoop() { } } -func (c *chainIDSubForwarder) Unsubscribe() { +func (c *subForwarder[T]) Unsubscribe() { // tell forwardLoop to unsubscribe select { case c.unSub <- struct{}{}: @@ -90,6 +93,6 @@ func (c *chainIDSubForwarder) Unsubscribe() { <-c.done } -func (c *chainIDSubForwarder) Err() <-chan error { +func (c *subForwarder[T]) Err() <-chan error { return c.err } diff --git a/core/chains/evm/client/sub_forwarder_test.go b/core/chains/evm/client/sub_forwarder_test.go new file mode 100644 index 0000000000..1bc0122603 --- /dev/null +++ b/core/chains/evm/client/sub_forwarder_test.go @@ -0,0 +1,190 @@ +package client + +import ( + "errors" + "fmt" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + commontypes "github.com/smartcontractkit/chainlink/v2/common/types" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" +) + +func TestChainIDSubForwarder(t *testing.T) { + t.Parallel() + + newChainIDSubForwarder := func(chainID *big.Int, ch chan<- *evmtypes.Head) *subForwarder[*evmtypes.Head] { + return newSubForwarder(ch, func(head *evmtypes.Head) *evmtypes.Head { + head.EVMChainID = ubig.New(chainID) + return head + }, nil) + } + + chainID := big.NewInt(123) + + t.Run("unsubscribe forwarder", func(t *testing.T) { + t.Parallel() + + ch := make(chan *evmtypes.Head) + forwarder := newChainIDSubForwarder(chainID, ch) + sub := NewMockSubscription() + err := forwarder.start(sub, nil) + assert.NoError(t, err) + forwarder.Unsubscribe() + + assert.True(t, sub.unsubscribed) + _, ok := <-sub.Err() + assert.False(t, ok) + _, ok = <-forwarder.Err() + assert.False(t, ok) + }) + + t.Run("unsubscribe forwarder with error", func(t *testing.T) { + t.Parallel() + + ch := make(chan *evmtypes.Head) + forwarder := newChainIDSubForwarder(chainID, ch) + sub := NewMockSubscription() + err := forwarder.start(sub, nil) + assert.NoError(t, err) + sub.Errors <- errors.New("boo") + forwarder.Unsubscribe() + + assert.True(t, sub.unsubscribed) + _, ok := <-sub.Err() + assert.False(t, ok) + _, ok = <-forwarder.Err() + assert.False(t, ok) + }) + + t.Run("unsubscribe forwarder with message", func(t *testing.T) { + t.Parallel() + + ch := make(chan *evmtypes.Head) + forwarder := newChainIDSubForwarder(chainID, ch) + sub := NewMockSubscription() + err := forwarder.start(sub, nil) + assert.NoError(t, err) + forwarder.srcCh <- &evmtypes.Head{} + forwarder.Unsubscribe() + + assert.True(t, sub.unsubscribed) + _, ok := <-sub.Err() + assert.False(t, ok) + _, ok = <-forwarder.Err() + assert.False(t, ok) + }) + + t.Run("non nil error parameter", func(t *testing.T) { + t.Parallel() + + ch := make(chan *evmtypes.Head) + forwarder := newChainIDSubForwarder(chainID, ch) + sub := NewMockSubscription() + errIn := errors.New("foo") + errOut := forwarder.start(sub, errIn) + assert.Equal(t, errIn, errOut) + }) + + t.Run("forwarding", func(t *testing.T) { + t.Parallel() + + ch := make(chan *evmtypes.Head) + forwarder := newChainIDSubForwarder(chainID, ch) + sub := NewMockSubscription() + err := forwarder.start(sub, nil) + assert.NoError(t, err) + + head := &evmtypes.Head{ + ID: 1, + } + forwarder.srcCh <- head + receivedHead := <-ch + assert.Equal(t, head, receivedHead) + assert.Equal(t, ubig.New(chainID), receivedHead.EVMChainID) + + expectedErr := errors.New("error") + sub.Errors <- expectedErr + receivedErr := <-forwarder.Err() + assert.Equal(t, expectedErr, receivedErr) + }) +} + +func TestSubscriptionErrorWrapper(t *testing.T) { + t.Parallel() + newSubscriptionErrorWrapper := func(t *testing.T, sub commontypes.Subscription, errorPrefix string) ethereum.Subscription { + ch := make(chan *evmtypes.Head) + result := newSubForwarder(ch, nil, func(err error) error { + return fmt.Errorf("%s: %w", errorPrefix, err) + }) + require.NoError(t, result.start(sub, nil)) + return result + } + t.Run("Unsubscribe wrapper releases resources", func(t *testing.T) { + t.Parallel() + + mockedSub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(t, mockedSub, prefix) + wrapper.Unsubscribe() + + // mock's resources were released + assert.True(t, mockedSub.unsubscribed) + _, ok := <-mockedSub.Err() + assert.False(t, ok) + // wrapper's channels are closed + _, ok = <-wrapper.Err() + assert.False(t, ok) + // subsequence unsubscribe does not causes panic + wrapper.Unsubscribe() + }) + t.Run("Unsubscribe interrupts error delivery", func(t *testing.T) { + t.Parallel() + sub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(t, sub, prefix) + sub.Errors <- fmt.Errorf("error") + + wrapper.Unsubscribe() + _, ok := <-wrapper.Err() + assert.False(t, ok) + }) + t.Run("Successfully wraps error", func(t *testing.T) { + t.Parallel() + sub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(t, sub, prefix) + sub.Errors <- fmt.Errorf("root error") + + err, ok := <-wrapper.Err() + assert.True(t, ok) + assert.Equal(t, "RPC returned error: root error", err.Error()) + + wrapper.Unsubscribe() + _, ok = <-wrapper.Err() + assert.False(t, ok) + }) + t.Run("Unsubscribe on root does not cause panic", func(t *testing.T) { + t.Parallel() + mockedSub := NewMockSubscription() + wrapper := newSubscriptionErrorWrapper(t, mockedSub, "") + + mockedSub.Unsubscribe() + // mock's resources were released + assert.True(t, mockedSub.unsubscribed) + _, ok := <-mockedSub.Err() + assert.False(t, ok) + // wrapper's channels are eventually closed + tests.AssertEventually(t, func() bool { + _, ok = <-wrapper.Err() + return !ok + }) + }) +} diff --git a/core/chains/evm/config/chain_scoped.go b/core/chains/evm/config/chain_scoped.go index 8064e2de20..db598e3e82 100644 --- a/core/chains/evm/config/chain_scoped.go +++ b/core/chains/evm/config/chain_scoped.go @@ -179,3 +179,7 @@ func (e *EVMConfig) OperatorFactoryAddress() string { func (e *EVMConfig) LogPrunePageSize() uint32 { return *e.C.LogPrunePageSize } + +func (e *EVMConfig) FinalizedBlockOffset() uint32 { + return *e.C.FinalizedBlockOffset +} diff --git a/core/chains/evm/config/chain_scoped_node_pool.go b/core/chains/evm/config/chain_scoped_node_pool.go index 5026936682..a497436648 100644 --- a/core/chains/evm/config/chain_scoped_node_pool.go +++ b/core/chains/evm/config/chain_scoped_node_pool.go @@ -38,6 +38,12 @@ func (n *NodePoolConfig) FinalizedBlockPollInterval() time.Duration { return n.C.FinalizedBlockPollInterval.Duration() } -func (n *NodePoolConfig) Errors() ClientErrors { - return &clientErrorsConfig{c: n.C.Errors} +func (n *NodePoolConfig) Errors() ClientErrors { return &clientErrorsConfig{c: n.C.Errors} } + +func (n *NodePoolConfig) EnforceRepeatableRead() bool { + return *n.C.EnforceRepeatableRead +} + +func (n *NodePoolConfig) DeathDeclarationDelay() time.Duration { + return n.C.DeathDeclarationDelay.Duration() } diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index b44c112e20..ffb2a496ba 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -45,6 +45,7 @@ type EVM interface { OperatorFactoryAddress() string RPCDefaultBatchSize() uint32 NodeNoNewHeadsThreshold() time.Duration + FinalizedBlockOffset() uint32 IsEnabled() bool TOMLString() (string, error) @@ -170,6 +171,8 @@ type NodePool interface { NodeIsSyncingEnabled() bool FinalizedBlockPollInterval() time.Duration Errors() ClientErrors + EnforceRepeatableRead() bool + DeathDeclarationDelay() time.Duration } // TODO BCF-2509 does the chainscopedconfig really need the entire app config? diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index 26ac2db085..ba362bda98 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -326,6 +326,8 @@ func TestNodePoolConfig(t *testing.T) { require.Equal(t, time.Duration(10000000000), cfg.EVM().NodePool().PollInterval()) require.Equal(t, uint32(5), cfg.EVM().NodePool().PollFailureThreshold()) require.Equal(t, false, cfg.EVM().NodePool().NodeIsSyncingEnabled()) + require.Equal(t, false, cfg.EVM().NodePool().EnforceRepeatableRead()) + require.Equal(t, time.Duration(10000000000), cfg.EVM().NodePool().DeathDeclarationDelay()) } func TestClientErrorsConfig(t *testing.T) { diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index d35f9bd0a3..3e35bb4b55 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -358,6 +358,7 @@ type Chain struct { OperatorFactoryAddress *types.EIP55Address RPCDefaultBatchSize *uint32 RPCBlockQueryDelay *uint16 + FinalizedBlockOffset *uint32 Transactions Transactions `toml:",omitempty"` BalanceMonitor BalanceMonitor `toml:",omitempty"` @@ -389,6 +390,11 @@ func (c *Chain) ValidateConfig() (err error) { Msg: "must be greater than or equal to 1"}) } + if *c.FinalizedBlockOffset > *c.HeadTracker.HistoryDepth { + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "HeadTracker.HistoryDepth", Value: *c.HeadTracker.HistoryDepth, + Msg: "must be greater than or equal to FinalizedBlockOffset"}) + } + // AutoPurge configs depend on ChainType so handling validation on per chain basis if c.Transactions.AutoPurge.Enabled != nil && *c.Transactions.AutoPurge.Enabled { chainType := c.ChainType.ChainType() @@ -842,6 +848,8 @@ type NodePool struct { NodeIsSyncingEnabled *bool FinalizedBlockPollInterval *commonconfig.Duration Errors ClientErrors `toml:",omitempty"` + EnforceRepeatableRead *bool + DeathDeclarationDelay *commonconfig.Duration } func (p *NodePool) setFrom(f *NodePool) { @@ -866,6 +874,14 @@ func (p *NodePool) setFrom(f *NodePool) { if v := f.FinalizedBlockPollInterval; v != nil { p.FinalizedBlockPollInterval = v } + + if v := f.EnforceRepeatableRead; v != nil { + p.EnforceRepeatableRead = v + } + + if v := f.DeathDeclarationDelay; v != nil { + p.DeathDeclarationDelay = v + } p.Errors.setFrom(&f.Errors) } diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go index e006babfb6..38eef40bf7 100644 --- a/core/chains/evm/config/toml/defaults.go +++ b/core/chains/evm/config/toml/defaults.go @@ -161,6 +161,9 @@ func (c *Chain) SetFrom(f *Chain) { if v := f.RPCBlockQueryDelay; v != nil { c.RPCBlockQueryDelay = v } + if v := f.FinalizedBlockOffset; v != nil { + c.FinalizedBlockOffset = v + } c.Transactions.setFrom(&f.Transactions) c.BalanceMonitor.setFrom(&f.BalanceMonitor) diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index 5a16aca091..a11e646e08 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -14,6 +14,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -68,6 +69,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 diff --git a/core/chains/evm/forwarders/forwarder_manager_test.go b/core/chains/evm/forwarders/forwarder_manager_test.go index be8513f592..c3fae5292a 100644 --- a/core/chains/evm/forwarders/forwarder_manager_test.go +++ b/core/chains/evm/forwarders/forwarder_manager_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -75,7 +76,8 @@ func TestFwdMgr_MaybeForwardTransaction(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), evmClient, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(evmClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), evmClient, lggr, ht, lpOpts) fwdMgr := forwarders.NewFwdMgr(db, evmClient, lp, lggr, evmcfg.EVM()) fwdMgr.ORM = forwarders.NewORM(db) @@ -136,7 +138,8 @@ func TestFwdMgr_AccountUnauthorizedToForward_SkipsForwarding(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), evmClient, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(evmClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), evmClient, lggr, ht, lpOpts) fwdMgr := forwarders.NewFwdMgr(db, evmClient, lp, lggr, evmcfg.EVM()) fwdMgr.ORM = forwarders.NewORM(db) @@ -201,7 +204,8 @@ func TestFwdMgr_InvalidForwarderForOCR2FeedsStates(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), evmClient, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(evmClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), evmClient, lggr, ht, lpOpts) fwdMgr := forwarders.NewFwdMgr(db, evmClient, lp, lggr, evmcfg.EVM()) fwdMgr.ORM = forwarders.NewORM(db) diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go index 2da41de877..7ac61ab34b 100644 --- a/core/chains/evm/headtracker/head_broadcaster_test.go +++ b/core/chains/evm/headtracker/head_broadcaster_test.go @@ -60,8 +60,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) { chchHeaders <- args.Get(1).(chan<- *evmtypes.Head) }). Return(sub, nil) - // 2 for initial and 2 for backfill - ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(1), nil).Times(4) + ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(1), nil) sub.On("Unsubscribe").Return() sub.On("Err").Return(nil) diff --git a/core/chains/evm/headtracker/head_listener_test.go b/core/chains/evm/headtracker/head_listener_test.go index 2e1a9c81d5..29b090bbff 100644 --- a/core/chains/evm/headtracker/head_listener_test.go +++ b/core/chains/evm/headtracker/head_listener_test.go @@ -70,7 +70,7 @@ func Test_HeadListener_HappyPath(t *testing.T) { done := func() { doneAwaiter.ItHappened() } - go hl.ListenForNewHeads(handler, done) + go hl.ListenForNewHeads(func() {}, handler, done) subscribeAwaiter.AwaitOrFail(t, tests.WaitTimeout(t)) require.Eventually(t, hl.Connected, tests.WaitTimeout(t), tests.TestInterval) @@ -129,7 +129,7 @@ func Test_HeadListener_NotReceivingHeads(t *testing.T) { done := func() { doneAwaiter.ItHappened() } - go hl.ListenForNewHeads(handler, done) + go hl.ListenForNewHeads(func() {}, handler, done) subscribeAwaiter.AwaitOrFail(t, tests.WaitTimeout(t)) @@ -190,7 +190,7 @@ func Test_HeadListener_SubscriptionErr(t *testing.T) { subscribeAwaiter.ItHappened() }) go func() { - hl.ListenForNewHeads(hnh, done) + hl.ListenForNewHeads(func() {}, hnh, done) }() // Put a head on the channel to ensure we test all code paths diff --git a/core/chains/evm/headtracker/head_saver_test.go b/core/chains/evm/headtracker/head_saver_test.go index 9be9f838d0..43e79235e9 100644 --- a/core/chains/evm/headtracker/head_saver_test.go +++ b/core/chains/evm/headtracker/head_saver_test.go @@ -47,6 +47,7 @@ type config struct { finalityDepth uint32 blockEmissionIdleWarningThreshold time.Duration finalityTagEnabled bool + finalizedBlockOffset uint32 } func (c *config) FinalityDepth() uint32 { return c.finalityDepth } @@ -58,6 +59,10 @@ func (c *config) FinalityTagEnabled() bool { return c.finalityTagEnabled } +func (c *config) FinalizedBlockOffset() uint32 { + return c.finalizedBlockOffset +} + type saverOpts struct { headTrackerConfig *headTrackerConfig } diff --git a/core/chains/evm/headtracker/head_tracker.go b/core/chains/evm/headtracker/head_tracker.go index 357c4dae99..d6c2cdc64e 100644 --- a/core/chains/evm/headtracker/head_tracker.go +++ b/core/chains/evm/headtracker/head_tracker.go @@ -49,7 +49,10 @@ func (*nullTracker) Ready() error { return nil } func (*nullTracker) HealthReport() map[string]error { return map[string]error{} } func (*nullTracker) Name() string { return "" } func (*nullTracker) SetLogLevel(zapcore.Level) {} -func (*nullTracker) Backfill(ctx context.Context, headWithChain, latestFinalized *evmtypes.Head) (err error) { +func (*nullTracker) Backfill(ctx context.Context, headWithChain *evmtypes.Head) (err error) { return nil } func (*nullTracker) LatestChain() *evmtypes.Head { return nil } +func (*nullTracker) LatestAndFinalizedBlock(ctx context.Context) (latest, finalized *evmtypes.Head, err error) { + return nil, nil, nil +} diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 4da8d27c55..81ba3ea85f 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -3,6 +3,7 @@ package headtracker_test import ( "context" "errors" + "fmt" "math/big" "slices" "sync" @@ -20,17 +21,19 @@ import ( "go.uber.org/zap/zaptest/observer" "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" + "github.com/jmoiron/sqlx" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" htmocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" commontypes "github.com/smartcontractkit/chainlink/v2/common/headtracker/types" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" @@ -60,6 +63,12 @@ func TestHeadTracker_New(t *testing.T) { ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(testutils.Head(0), nil) // finalized ethClient.On("HeadByNumber", mock.Anything, big.NewInt(0)).Return(testutils.Head(0), nil) + mockEth := &testutils.MockEth{ + EthClient: ethClient, + } + ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything). + Maybe(). + Return(mockEth.NewSub(t), nil) orm := headtracker.NewORM(*testutils.FixtureChainID, db) assert.Nil(t, orm.IdempotentInsertHead(tests.Context(t), testutils.Head(1))) @@ -71,9 +80,10 @@ func TestHeadTracker_New(t *testing.T) { ht := createHeadTracker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), orm) ht.Start(t) - latest := ht.headSaver.LatestChain() - require.NotNil(t, latest) - assert.Equal(t, last.Number, latest.Number) + tests.AssertEventually(t, func() bool { + latest := ht.headSaver.LatestChain() + return latest != nil && last.Number == latest.Number + }) } func TestHeadTracker_MarkFinalized_MarksAndTrimsTable(t *testing.T) { @@ -126,7 +136,8 @@ func TestHeadTracker_Get(t *testing.T) { {"nil no initial", nil, nil, big.NewInt(0)}, } - for _, test := range cases { + for i := range cases { + test := cases[i] t.Run(test.name, func(t *testing.T) { db := pgtest.NewSqlxDB(t) config := testutils.NewTestChainScopedConfig(t, nil) @@ -146,9 +157,9 @@ func TestHeadTracker_Get(t *testing.T) { }, func(ctx context.Context, ch chan<- *evmtypes.Head) error { return nil }, ) - ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(testutils.Head(0), nil) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(testutils.Head(0), nil).Maybe() - fnCall := ethClient.On("HeadByNumber", mock.Anything, mock.Anything) + fnCall := ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Maybe() fnCall.RunFn = func(args mock.Arguments) { num := args.Get(1).(*big.Int) fnCall.ReturnArguments = mock.Arguments{testutils.Head(num.Int64()), nil} @@ -166,7 +177,10 @@ func TestHeadTracker_Get(t *testing.T) { assert.NoError(t, err) } - assert.Equal(t, test.want, ht.headSaver.LatestChain().ToInt()) + tests.AssertEventually(t, func() bool { + latest := ht.headSaver.LatestChain().ToInt() + return latest != nil && test.want.Cmp(latest) == 0 + }) }) } } @@ -226,19 +240,12 @@ func TestHeadTracker_Start(t *testing.T) { } }) orm := headtracker.NewORM(*testutils.FixtureChainID, db) - ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + mockEth := &testutils.MockEth{EthClient: ethClient} + sub := mockEth.NewSub(t) + ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Maybe() return createHeadTracker(t, ethClient, config.EVM(), config.EVM().HeadTracker(), orm) } - - t.Run("Fail start if context was canceled", func(t *testing.T) { - ctx, cancel := context.WithCancel(tests.Context(t)) - ht := newHeadTracker(t, opts{}) - ht.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Run(func(args mock.Arguments) { - cancel() - }).Return(testutils.Head(0), context.Canceled) - err := ht.headTracker.Start(ctx) - require.ErrorIs(t, err, context.Canceled) - }) t.Run("Starts even if failed to get initialHead", func(t *testing.T) { ht := newHeadTracker(t, opts{}) ht.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(testutils.Head(0), errors.New("failed to get init head")) @@ -268,20 +275,6 @@ func TestHeadTracker_Start(t *testing.T) { ht.Start(t) tests.AssertLogEventually(t, ht.observer, "Error handling initial head") }) - t.Run("Logs error if finality gap is too big", func(t *testing.T) { - ht := newHeadTracker(t, opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(false), MaxAllowedFinalityDepth: ptr(uint32(10))}) - head := testutils.Head(1000) - ht.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(head, nil).Once() - ht.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(testutils.Head(989), nil).Once() - ht.ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, errors.New("failed to connect")).Maybe() - ht.Start(t) - tests.AssertEventually(t, func() bool { - // must exactly match the error passed to logger - field := zap.String("err", "failed to calculate latest finalized head: gap between latest finalized block (989) and current head (1000) is too large (> 10)") - filtered := ht.observer.FilterMessage("Error handling initial head").FilterField(field) - return filtered.Len() > 0 - }) - }) t.Run("Happy path (finality tag)", func(t *testing.T) { head := testutils.Head(1000) ht := newHeadTracker(t, opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(false)}) @@ -877,10 +870,23 @@ func TestHeadTracker_Backfill(t *testing.T) { ctx := tests.Context(t) type opts struct { - Heads []evmtypes.Head + Heads []evmtypes.Head + FinalityTagEnabled bool + FinalizedBlockOffset uint32 + FinalityDepth uint32 + MaxAllowedFinalityDepth uint32 } newHeadTrackerUniverse := func(t *testing.T, opts opts) *headTrackerUniverse { - evmcfg := testutils.NewTestChainScopedConfig(t, nil) + evmcfg := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { + c.FinalityTagEnabled = ptr(opts.FinalityTagEnabled) + c.FinalizedBlockOffset = ptr(opts.FinalizedBlockOffset) + c.FinalityDepth = ptr(opts.FinalityDepth) + c.HeadTracker.FinalityTagBypass = ptr(false) + if opts.MaxAllowedFinalityDepth > 0 { + c.HeadTracker.MaxAllowedFinalityDepth = ptr(opts.MaxAllowedFinalityDepth) + } + }) + db := pgtest.NewSqlxDB(t) orm := headtracker.NewORM(*testutils.FixtureChainID, db) for i := range opts.Heads { @@ -894,26 +900,44 @@ func TestHeadTracker_Backfill(t *testing.T) { return ht } + t.Run("returns error if failed to get latestFinalized block", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + const expectedError = "failed to fetch latest finalized block" + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, errors.New(expectedError)).Once() + + err := htu.headTracker.Backfill(ctx, &h12) + require.ErrorContains(t, err, expectedError) + }) t.Run("returns error if latestFinalized is not valid", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{}) + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, nil).Once() + + err := htu.headTracker.Backfill(ctx, &h12) + require.EqualError(t, err, "failed to calculate finalized block: failed to get valid latest finalized block") + }) + t.Run("Returns error if finality gap is too big", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, MaxAllowedFinalityDepth: 2}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h9, nil).Once() - err := htu.headTracker.Backfill(ctx, &h12, nil) - require.EqualError(t, err, "can not perform backfill without a valid latestFinalized head") + err := htu.headTracker.Backfill(ctx, &h12) + require.EqualError(t, err, "gap between latest finalized block (9) and current head (12) is too large (> 2)") }) t.Run("Returns error if finalized head is ahead of canonical", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{}) + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14Orphaned, nil).Once() - err := htu.headTracker.Backfill(ctx, &h12, &h14Orphaned) + err := htu.headTracker.Backfill(ctx, &h12) require.EqualError(t, err, "invariant violation: expected head of canonical chain to be ahead of the latestFinalized") }) t.Run("Returns error if finalizedHead is not present in the canonical chain", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: heads}) + htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14Orphaned, nil).Once() - err := htu.headTracker.Backfill(ctx, &h15, &h14Orphaned) + err := htu.headTracker.Backfill(ctx, &h15) require.EqualError(t, err, "expected finalized block to be present in canonical chain") }) t.Run("Marks all blocks in chain that are older than finalized", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: heads}) + htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) assertFinalized := func(expectedFinalized bool, msg string, heads ...evmtypes.Head) { for _, h := range heads { @@ -922,18 +946,20 @@ func TestHeadTracker_Backfill(t *testing.T) { } } - err := htu.headTracker.Backfill(ctx, &h15, &h14) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14, nil).Once() + err := htu.headTracker.Backfill(ctx, &h15) require.NoError(t, err) assertFinalized(true, "expected heads to be marked as finalized after backfill", h14, h13, h12, h11) assertFinalized(false, "expected heads to remain unfinalized", h15, head10) }) t.Run("fetches a missing head", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: heads}) + htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h9, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil) - err := htu.headTracker.Backfill(ctx, &h12, &h9) + err := htu.headTracker.Backfill(ctx, &h12) require.NoError(t, err) h := htu.headSaver.Chain(h12.Hash) @@ -950,16 +976,16 @@ func TestHeadTracker_Backfill(t *testing.T) { require.NoError(t, err) assert.Equal(t, int64(10), writtenHead.Number) }) - t.Run("fetches only heads that are missing", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: heads}) + htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&head8, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil) htu.ethClient.On("HeadByHash", mock.Anything, head8.Hash). Return(&head8, nil) - err := htu.headTracker.Backfill(ctx, &h15, &head8) + err := htu.headTracker.Backfill(ctx, &h15) require.NoError(t, err) h := htu.headSaver.Chain(h15.Hash) @@ -971,7 +997,8 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("abandons backfill and returns error if the eth node returns not found", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: heads}) + htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&head8, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil). Once() @@ -979,9 +1006,9 @@ func TestHeadTracker_Backfill(t *testing.T) { Return(nil, ethereum.NotFound). Once() - err := htu.headTracker.Backfill(ctx, &h12, &head8) + err := htu.headTracker.Backfill(ctx, &h12) require.Error(t, err) - require.EqualError(t, err, "fetchAndSaveHead failed: not found") + require.ErrorContains(t, err, "fetchAndSaveHead failed: not found") h := htu.headSaver.Chain(h12.Hash) @@ -991,7 +1018,8 @@ func TestHeadTracker_Backfill(t *testing.T) { }) t.Run("abandons backfill and returns error if the context time budget is exceeded", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: heads}) + htu := newHeadTrackerUniverse(t, opts{Heads: heads, FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&head8, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, head10.Hash). Return(&head10, nil) lctx, cancel := context.WithCancel(ctx) @@ -1000,9 +1028,9 @@ func TestHeadTracker_Backfill(t *testing.T) { cancel() }) - err := htu.headTracker.Backfill(lctx, &h12, &head8) + err := htu.headTracker.Backfill(lctx, &h12) require.Error(t, err) - require.EqualError(t, err, "fetchAndSaveHead failed: context canceled") + require.ErrorContains(t, err, "fetchAndSaveHead failed: context canceled") h := htu.headSaver.Chain(h12.Hash) @@ -1010,17 +1038,17 @@ func TestHeadTracker_Backfill(t *testing.T) { assert.Equal(t, 4, int(h.ChainLength())) assert.Equal(t, int64(9), h.EarliestInChain().BlockNumber()) }) - t.Run("abandons backfill and returns error when fetching a block by hash fails, indicating a reorg", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{}) + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h11, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(nil, errors.New("not found")).Once() - err := htu.headTracker.Backfill(ctx, &h15, &h11) + err := htu.headTracker.Backfill(ctx, &h15) require.Error(t, err) - require.EqualError(t, err, "fetchAndSaveHead failed: not found") + require.ErrorContains(t, err, "fetchAndSaveHead failed: not found") h := htu.headSaver.Chain(h14.Hash) @@ -1029,9 +1057,10 @@ func TestHeadTracker_Backfill(t *testing.T) { assert.Equal(t, int64(13), h.EarliestInChain().BlockNumber()) }) t.Run("marks head as finalized, if latestHead = finalizedHead (0 finality depth)", func(t *testing.T) { - htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}}) + htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityTagEnabled: true}) finalizedH15 := h15 // copy h15 to have different addresses - err := htu.headTracker.Backfill(ctx, &h15, &finalizedH15) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&finalizedH15, nil).Once() + err := htu.headTracker.Backfill(ctx, &h15) require.NoError(t, err) h := htu.headSaver.LatestChain() @@ -1042,12 +1071,215 @@ func TestHeadTracker_Backfill(t *testing.T) { assert.Equal(t, h15.BlockNumber(), h.BlockNumber()) assert.Equal(t, h15.Hash, h.Hash) }) + t.Run("marks block as finalized according to FinalizedBlockOffset (finality tag)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityTagEnabled: true, FinalizedBlockOffset: 2}) + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&h14, nil).Once() + // calculateLatestFinalizedBlock fetches blocks at LatestFinalized - FinalizedBlockOffset + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(h12.Number)).Return(&h12, nil).Once() + // backfill from 15 to 12 + htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(&h12, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() + err := htu.headTracker.Backfill(ctx, &h15) + require.NoError(t, err) + + h := htu.headSaver.LatestChain() + // h - must contain 15, 14, 13, 12 and only 12 is finalized + assert.Equal(t, 4, int(h.ChainLength())) + for ; h.Hash != h12.Hash; h = h.Parent { + assert.False(t, h.IsFinalized) + } + + assert.True(t, h.IsFinalized) + assert.Equal(t, h12.BlockNumber(), h.BlockNumber()) + assert.Equal(t, h12.Hash, h.Hash) + }) + t.Run("marks block as finalized according to FinalizedBlockOffset (finality depth)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityDepth: 1, FinalizedBlockOffset: 2}) + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(12)).Return(&h12, nil).Once() + + // backfill from 15 to 12 + htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h12.Hash).Return(&h12, nil).Once() + err := htu.headTracker.Backfill(ctx, &h15) + require.NoError(t, err) + + h := htu.headSaver.LatestChain() + // h - must contain 15, 14, 13, 12 and only 12 is finalized + assert.Equal(t, 4, int(h.ChainLength())) + for ; h.Hash != h12.Hash; h = h.Parent { + assert.False(t, h.IsFinalized) + } + + assert.True(t, h.IsFinalized) + assert.Equal(t, h12.BlockNumber(), h.BlockNumber()) + assert.Equal(t, h12.Hash, h.Hash) + }) + t.Run("marks block as finalized according to FinalizedBlockOffset even with instant finality", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{Heads: []evmtypes.Head{h15}, FinalityDepth: 0, FinalizedBlockOffset: 2}) + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(13)).Return(&h13, nil).Once() + + // backfill from 15 to 13 + htu.ethClient.On("HeadByHash", mock.Anything, h14.Hash).Return(&h14, nil).Once() + htu.ethClient.On("HeadByHash", mock.Anything, h13.Hash).Return(&h13, nil).Once() + err := htu.headTracker.Backfill(ctx, &h15) + require.NoError(t, err) + + h := htu.headSaver.LatestChain() + // h - must contain 15, 14, 13, only 13 is finalized + assert.Equal(t, 3, int(h.ChainLength())) + for ; h.Hash != h13.Hash; h = h.Parent { + assert.False(t, h.IsFinalized) + } + + assert.True(t, h.IsFinalized) + assert.Equal(t, h13.BlockNumber(), h.BlockNumber()) + assert.Equal(t, h13.Hash, h.Hash) + }) +} + +func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + + h11 := testutils.Head(11) + h11.ParentHash = utils.NewHash() + + h12 := testutils.Head(12) + h12.ParentHash = h11.Hash + + h13 := testutils.Head(13) + h13.ParentHash = h12.Hash + + type opts struct { + Heads []evmtypes.Head + FinalityTagEnabled bool + FinalizedBlockOffset uint32 + FinalityDepth uint32 + } + + newHeadTrackerUniverse := func(t *testing.T, opts opts) *headTrackerUniverse { + evmcfg := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { + c.FinalityTagEnabled = ptr(opts.FinalityTagEnabled) + c.FinalizedBlockOffset = ptr(opts.FinalizedBlockOffset) + c.FinalityDepth = ptr(opts.FinalityDepth) + }) + + db := pgtest.NewSqlxDB(t) + orm := headtracker.NewORM(*testutils.FixtureChainID, db) + for i := range opts.Heads { + require.NoError(t, orm.IdempotentInsertHead(tests.Context(t), &opts.Heads[i])) + } + ethClient := evmtest.NewEthClientMock(t) + ethClient.On("ConfiguredChainID", mock.Anything).Return(testutils.FixtureChainID, nil) + ht := createHeadTracker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), orm) + _, err := ht.headSaver.Load(tests.Context(t), 0) + require.NoError(t, err) + return ht + } + t.Run("returns error if failed to get latest block", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + const expectedError = "failed to fetch latest block" + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, errors.New(expectedError)).Once() + + _, _, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.ErrorContains(t, err, expectedError) + }) + t.Run("returns error if latest block is invalid", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil).Once() + + _, _, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.ErrorContains(t, err, "expected latest block to be valid") + }) + t.Run("returns error if failed to get latest finalized (finality tag)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + const expectedError = "failed to get latest finalized block" + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, fmt.Errorf(expectedError)).Once() + + _, _, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.ErrorContains(t, err, expectedError) + }) + t.Run("returns error if latest finalized block is not valid (finality tag)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, nil).Once() + + _, _, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.ErrorContains(t, err, "failed to get valid latest finalized block") + }) + t.Run("returns latest finalized block as is if FinalizedBlockOffset is 0 (finality tag)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h11, nil).Once() + + actualL, actualLF, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.NoError(t, err) + assert.Equal(t, actualL, h13) + assert.Equal(t, actualLF, h11) + }) + t.Run("returns latest finalized block with offset from cache (finality tag)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, FinalizedBlockOffset: 1, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h12, nil).Once() + + actualL, actualLF, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.NoError(t, err) + assert.Equal(t, actualL.Number, h13.Number) + assert.Equal(t, actualLF.Number, h11.Number) + }) + t.Run("returns latest finalized block with offset from RPC (finality tag)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityTagEnabled: true, FinalizedBlockOffset: 2, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + htu.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(h12, nil).Once() + h10 := testutils.Head(10) + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(10)).Return(h10, nil).Once() + + actualL, actualLF, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.NoError(t, err) + assert.Equal(t, actualL.Number, h13.Number) + assert.Equal(t, actualLF.Number, h10.Number) + }) + t.Run("returns current head for both latest and finalized for FD = 0 (finality depth)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + + actualL, actualLF, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.NoError(t, err) + assert.Equal(t, actualL.Number, h13.Number) + assert.Equal(t, actualLF.Number, h13.Number) + }) + t.Run("returns latest finalized block with offset from cache (finality depth)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityDepth: 1, FinalizedBlockOffset: 1, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + + actualL, actualLF, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.NoError(t, err) + assert.Equal(t, actualL.Number, h13.Number) + assert.Equal(t, actualLF.Number, h11.Number) + }) + t.Run("returns latest finalized block with offset from RPC (finality depth)", func(t *testing.T) { + htu := newHeadTrackerUniverse(t, opts{FinalityDepth: 1, FinalizedBlockOffset: 2, Heads: []evmtypes.Head{*h13, *h12, *h11}}) + htu.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h13, nil).Once() + h10 := testutils.Head(10) + htu.ethClient.On("HeadByNumber", mock.Anything, big.NewInt(10)).Return(h10, nil).Once() + + actualL, actualLF, err := htu.headTracker.LatestAndFinalizedBlock(ctx) + require.NoError(t, err) + assert.Equal(t, actualL.Number, h13.Number) + assert.Equal(t, actualLF.Number, h10.Number) + }) } // BenchmarkHeadTracker_Backfill - benchmarks HeadTracker's Backfill with focus on efficiency after initial // backfill on start up func BenchmarkHeadTracker_Backfill(b *testing.B) { - evmcfg := testutils.NewTestChainScopedConfig(b, nil) + evmcfg := testutils.NewTestChainScopedConfig(b, func(c *toml.EVMConfig) { + c.FinalityTagEnabled = ptr(true) + }) db := pgtest.NewSqlxDB(b) chainID := big.NewInt(evmclient.NullClientChainID) orm := headtracker.NewORM(*chainID, db) @@ -1068,15 +1300,17 @@ func BenchmarkHeadTracker_Backfill(b *testing.B) { number := hash.Big().Int64() return makeBlock(number), nil }) + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(finalized, nil).Once() // run initial backfill to populate the database - err := ht.headTracker.Backfill(ctx, latest, finalized) + err := ht.headTracker.Backfill(ctx, latest) require.NoError(b, err) b.ResetTimer() // focus benchmark on processing of a new latest block for i := 0; i < b.N; i++ { latest = makeBlock(int64(finalityDepth + i)) finalized = makeBlock(int64(i + 1)) - err := ht.headTracker.Backfill(ctx, latest, finalized) + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(finalized, nil).Once() + err := ht.headTracker.Backfill(ctx, latest) require.NoError(b, err) } } @@ -1129,8 +1363,8 @@ type headTrackerUniverse struct { ethClient *evmclimocks.Client } -func (u *headTrackerUniverse) Backfill(ctx context.Context, head, finalizedHead *evmtypes.Head) error { - return u.headTracker.Backfill(ctx, head, finalizedHead) +func (u *headTrackerUniverse) Backfill(ctx context.Context, head *evmtypes.Head) error { + return u.headTracker.Backfill(ctx, head) } func (u *headTrackerUniverse) Start(t *testing.T) { diff --git a/core/chains/evm/headtracker/simulated_head_tracker.go b/core/chains/evm/headtracker/simulated_head_tracker.go new file mode 100644 index 0000000000..e1e550de99 --- /dev/null +++ b/core/chains/evm/headtracker/simulated_head_tracker.go @@ -0,0 +1,53 @@ +package headtracker + +import ( + "context" + "fmt" + "math/big" + + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +// simulatedHeadTracker - simplified version of HeadTracker that works with simulated backed +type simulatedHeadTracker struct { + ec evmclient.Client + useFinalityTag bool + finalityDepth int64 +} + +func NewSimulatedHeadTracker(ec evmclient.Client, useFinalityTag bool, finalityDepth int64) *simulatedHeadTracker { + return &simulatedHeadTracker{ + ec: ec, + useFinalityTag: useFinalityTag, + finalityDepth: finalityDepth, + } +} + +func (ht *simulatedHeadTracker) LatestAndFinalizedBlock(ctx context.Context) (*evmtypes.Head, *evmtypes.Head, error) { + latest, err := ht.ec.HeadByNumber(ctx, nil) + if err != nil { + return nil, nil, err + } + + if latest == nil { + return nil, nil, fmt.Errorf("expected latest block to be valid") + } + + var finalizedBlock *evmtypes.Head + if ht.useFinalityTag { + finalizedBlock, err = ht.ec.LatestFinalizedBlock(ctx) + } else { + finalizedBlock, err = ht.ec.HeadByNumber(ctx, big.NewInt(max(latest.Number-ht.finalityDepth, 0))) + } + + if err != nil { + return nil, nil, fmt.Errorf("simulatedHeadTracker failed to get finalized block") + } + + if finalizedBlock == nil { + return nil, nil, fmt.Errorf("expected finalized block to be valid") + } + + return latest, finalizedBlock, nil +} diff --git a/core/chains/evm/logpoller/helper_test.go b/core/chains/evm/logpoller/helper_test.go index 3b2a10df6c..3f589d84d5 100644 --- a/core/chains/evm/logpoller/helper_test.go +++ b/core/chains/evm/logpoller/helper_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "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/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -68,10 +69,11 @@ func SetupTH(t testing.TB, opts logpoller.Opts) TestHarness { head := esc.Backend().Blockchain().CurrentHeader() esc.Backend().Blockchain().SetFinalized(head) + headTracker := headtracker.NewSimulatedHeadTracker(esc, opts.UseFinalityTag, opts.FinalityDepth) if opts.PollPeriod == 0 { opts.PollPeriod = 1 * time.Hour } - lp := logpoller.NewLogPoller(o, esc, lggr, opts) + lp := logpoller.NewLogPoller(o, esc, lggr, headTracker, opts) emitterAddress1, _, emitter1, err := log_emitter.DeployLogEmitter(owner, ec) require.NoError(t, err) emitterAddress2, _, emitter2, err := log_emitter.DeployLogEmitter(owner, ec) diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index bc0dd40e28..333c5b70f8 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -27,6 +27,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -88,6 +89,10 @@ type Client interface { ConfiguredChainID() *big.Int } +type HeadTracker interface { + LatestAndFinalizedBlock(ctx context.Context) (latest, finalized *evmtypes.Head, err error) +} + var ( _ LogPollerTest = &logPoller{} ErrReplayRequestAborted = pkgerrors.New("aborted, replay request cancelled") @@ -100,6 +105,7 @@ type logPoller struct { services.StateMachine ec Client orm ORM + headTracker HeadTracker lggr logger.SugaredLogger pollPeriod time.Duration // poll period set by block production rate useFinalityTag bool // indicates whether logPoller should use chain's finality or pick a fixed depth for finality @@ -150,11 +156,12 @@ type Opts struct { // // How fast that can be done depends largely on network speed and DB, but even for the fastest // support chain, polygon, which has 2s block times, we need RPCs roughly with <= 500ms latency -func NewLogPoller(orm ORM, ec Client, lggr logger.Logger, opts Opts) *logPoller { +func NewLogPoller(orm ORM, ec Client, lggr logger.Logger, headTracker HeadTracker, opts Opts) *logPoller { return &logPoller{ stopCh: make(chan struct{}), ec: ec, orm: orm, + headTracker: headTracker, lggr: logger.Sugared(logger.Named(lggr, "LogPoller")), replayStart: make(chan int64), replayComplete: make(chan error), @@ -1007,38 +1014,15 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int } } -// Returns information about latestBlock, latestFinalizedBlockNumber -// If finality tag is not enabled, latestFinalizedBlockNumber is calculated as latestBlockNumber - lp.finalityDepth (configured param) -// Otherwise, we return last finalized block number returned from chain +// Returns information about latestBlock, latestFinalizedBlockNumber provided by HeadTracker func (lp *logPoller) latestBlocks(ctx context.Context) (*evmtypes.Head, int64, error) { - // If finality is not enabled, we can only fetch the latest block - if !lp.useFinalityTag { - // Example: - // finalityDepth = 2 - // Blocks: 1->2->3->4->5(latestBlock) - // latestFinalizedBlockNumber would be 3 - latestBlock, err := lp.ec.HeadByNumber(ctx, nil) - if err != nil { - return nil, 0, err - } - if latestBlock == nil { - // Shouldn't happen with a real client, but still better rather to - // return error than panic - return nil, 0, errors.New("latest block is nil") - } - // If chain has fewer blocks than finalityDepth, return 0 - return latestBlock, mathutil.Max(latestBlock.Number-lp.finalityDepth, 0), nil - } - - // If finality is enabled, we need to get the latest and finalized blocks. - blocks, err := lp.batchFetchBlocks(ctx, []string{rpc.LatestBlockNumber.String(), rpc.FinalizedBlockNumber.String()}, 2) + latest, finalized, err := lp.headTracker.LatestAndFinalizedBlock(ctx) if err != nil { - return nil, 0, err + return nil, 0, fmt.Errorf("failed to get latest and latest finalized block from HeadTracker: %w", err) } - latest := blocks[0] - finalized := blocks[1] - lp.lggr.Debugw("Latest blocks read from chain", "latest", latest.Number, "finalized", finalized.Number) - return latest, finalized.Number, nil + + lp.lggr.Debugw("Latest blocks read from chain", "latest", latest.Number, "finalized", finalized.BlockNumber()) + return latest, finalized.BlockNumber(), nil } // Find the first place where our chain and their chain have the same block, diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index bc29510587..448710b93f 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "math/big" - "reflect" "strings" "sync" "testing" @@ -22,10 +21,13 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -73,7 +75,7 @@ func TestLogPoller_RegisterFilter(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := NewLogPoller(orm, nil, lggr, lpOpts) + lp := NewLogPoller(orm, nil, lggr, nil, lpOpts) // We expect a zero Filter if nothing registered yet. f := lp.Filter(nil, nil, nil) @@ -208,8 +210,10 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { db := pgtest.NewSqlxDB(t) orm := NewORM(chainID, db, lggr) latestBlock := int64(4) + const finalityDepth = 2 - head := evmtypes.Head{Number: latestBlock} + head := &evmtypes.Head{Number: latestBlock} + finalizedHead := &evmtypes.Head{Number: latestBlock - finalityDepth} events := []common.Hash{EmitterABI.Events["Log1"].ID} log1 := types.Log{ Index: 0, @@ -222,20 +226,22 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { } ec := evmclimocks.NewClient(t) - ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(&head, nil) ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) ec.On("ConfiguredChainID").Return(chainID, nil) + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalizedHead, nil) + ctx := testutils.Context(t) lpOpts := Opts{ PollPeriod: time.Hour, - FinalityDepth: 2, + FinalityDepth: finalityDepth, BackfillBatchSize: 3, RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, BackupPollerBlockDelay: 0, } - lp := NewLogPoller(orm, ec, lggr, lpOpts) + lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) lp.BackupPollAndSaveLogs(ctx) assert.Equal(t, int64(0), lp.backupPollerNextBlock) assert.Equal(t, 1, observedLogs.FilterMessageSnippet("ran before first successful log poller run").Len()) @@ -309,7 +315,14 @@ func TestLogPoller_Replay(t *testing.T) { KeepFinalizedBlocksDepth: 20, BackupPollerBlockDelay: 0, } - lp := NewLogPoller(orm, ec, lggr, lpOpts) + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(func(ctx context.Context) (*evmtypes.Head, *evmtypes.Head, error) { + headCopy := head + finalized := &evmtypes.Head{Number: headCopy.Number - lpOpts.FinalityDepth} + return &headCopy, finalized, nil + }) + lp := NewLogPoller(orm, ec, lggr, headTracker, lpOpts) { ctx := testutils.Context(t) @@ -533,10 +546,6 @@ func (lp *logPoller) reset() { func Test_latestBlockAndFinalityDepth(t *testing.T) { lggr := logger.Test(t) - chainID := testutils.FixtureChainID - db := pgtest.NewSqlxDB(t) - orm := NewORM(chainID, db, lggr) - ctx := testutils.Context(t) lpOpts := Opts{ PollPeriod: time.Hour, @@ -545,71 +554,27 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) { KeepFinalizedBlocksDepth: 20, } - t.Run("pick latest block from chain and use finality from config with finality disabled", func(t *testing.T) { - head := evmtypes.Head{Number: 4} - - lpOpts.UseFinalityTag = false - lpOpts.FinalityDepth = int64(3) - ec := evmclimocks.NewClient(t) - ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(&head, nil) + t.Run("headTracker returns an error", func(t *testing.T) { + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + const expectedError = "finalized block is not available yet" + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(&evmtypes.Head{}, &evmtypes.Head{}, fmt.Errorf(expectedError)) - lp := NewLogPoller(orm, ec, lggr, lpOpts) - latestBlock, lastFinalizedBlockNumber, err := lp.latestBlocks(ctx) - require.NoError(t, err) - require.Equal(t, latestBlock.Number, head.Number) - require.Equal(t, lpOpts.FinalityDepth, latestBlock.Number-lastFinalizedBlockNumber) + lp := NewLogPoller(nil, nil, lggr, headTracker, lpOpts) + _, _, err := lp.latestBlocks(tests.Context(t)) + require.ErrorContains(t, err, expectedError) }) - - t.Run("finality tags in use", func(t *testing.T) { - t.Run("client returns data properly", func(t *testing.T) { - expectedLatestBlockNumber := int64(20) - expectedLastFinalizedBlockNumber := int64(12) - ec := evmclimocks.NewClient(t) - ec.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 2 && - reflect.DeepEqual(b[0].Args, []interface{}{"latest", false}) && - reflect.DeepEqual(b[1].Args, []interface{}{"finalized", false}) - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - // Latest block details - *(elems[0].Result.(*evmtypes.Head)) = evmtypes.Head{Number: expectedLatestBlockNumber, Hash: utils.RandomBytes32()} - // Finalized block details - *(elems[1].Result.(*evmtypes.Head)) = evmtypes.Head{Number: expectedLastFinalizedBlockNumber, Hash: utils.RandomBytes32()} - }) - - lpOpts.UseFinalityTag = true - lp := NewLogPoller(orm, ec, lggr, lpOpts) - - latestBlock, lastFinalizedBlockNumber, err := lp.latestBlocks(ctx) - require.NoError(t, err) - require.Equal(t, expectedLatestBlockNumber, latestBlock.Number) - require.Equal(t, expectedLastFinalizedBlockNumber, lastFinalizedBlockNumber) - }) - - t.Run("client returns error for at least one of the calls", func(t *testing.T) { - ec := evmclimocks.NewClient(t) - ec.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - // Latest block details - *(elems[0].Result.(*evmtypes.Head)) = evmtypes.Head{Number: 10} - // Finalized block details - elems[1].Error = fmt.Errorf("some error") - }) - - lpOpts.UseFinalityTag = true - lp := NewLogPoller(orm, ec, lggr, lpOpts) - _, _, err := lp.latestBlocks(ctx) - require.Error(t, err) - }) - - t.Run("BatchCall returns an error", func(t *testing.T) { - ec := evmclimocks.NewClient(t) - ec.On("BatchCallContext", mock.Anything, mock.Anything).Return(fmt.Errorf("some error")) - lpOpts.UseFinalityTag = true - lp := NewLogPoller(orm, ec, lggr, lpOpts) - _, _, err := lp.latestBlocks(ctx) - require.Error(t, err) - }) + t.Run("headTracker returns valid chain", func(t *testing.T) { + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + finalizedBlock := &evmtypes.Head{Number: 2, IsFinalized: true} + head := &evmtypes.Head{Number: 10} + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalizedBlock, nil) + + lp := NewLogPoller(nil, nil, lggr, headTracker, lpOpts) + latestBlock, finalizedBlockNumber, err := lp.latestBlocks(tests.Context(t)) + require.NoError(t, err) + require.NotNil(t, latestBlock) + assert.Equal(t, head.BlockNumber(), latestBlock.BlockNumber()) + assert.Equal(t, finalizedBlock.Number, finalizedBlockNumber) }) } @@ -653,7 +618,7 @@ func Test_FetchBlocks(t *testing.T) { errors.New("Received unfinalized block 9 while expecting finalized block (latestFinalizedBlockNumber = 5)"), }} - lp := NewLogPoller(orm, ec, lggr, lpOpts) + lp := NewLogPoller(orm, ec, lggr, nil, lpOpts) for _, tc := range cases { for _, lp.useFinalityTag = range []bool{false, true} { blockValidationReq := latestBlock @@ -693,7 +658,7 @@ func benchmarkFilter(b *testing.B, nFilters, nAddresses, nEvents int) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := NewLogPoller(nil, nil, lggr, lpOpts) + lp := NewLogPoller(nil, nil, lggr, nil, lpOpts) for i := 0; i < nFilters; i++ { var addresses []common.Address var events []common.Hash diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 6ef1692150..c83efc83b3 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -28,7 +28,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" "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" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -717,7 +719,9 @@ func TestLogPoller_SynchronizedWithGeth(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(orm, client.NewSimulatedBackendClient(t, ec, chainID), lggr, lpOpts) + simulatedClient := client.NewSimulatedBackendClient(t, ec, chainID) + ht := headtracker.NewSimulatedHeadTracker(simulatedClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(orm, simulatedClient, lggr, ht, lpOpts) for i := 0; i < finalityDepth; i++ { // Have enough blocks that we could reorg the full finalityDepth-1. ec.Commit() } @@ -1493,7 +1497,7 @@ func TestLogPoller_DBErrorHandling(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(o, client.NewSimulatedBackendClient(t, ec, chainID2), lggr, lpOpts) + lp := logpoller.NewLogPoller(o, client.NewSimulatedBackendClient(t, ec, chainID2), lggr, nil, lpOpts) err = lp.Replay(ctx, 5) // block number too high require.ErrorContains(t, err, "Invalid replay block number") @@ -1548,7 +1552,8 @@ func TestTooManyLogResults(t *testing.T) { RpcBatchSize: 10, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(o, ec, lggr, lpOpts) + headTracker := htMocks.NewHeadTracker[*evmtypes.Head, common.Hash](t) + lp := logpoller.NewLogPoller(o, ec, lggr, headTracker, lpOpts) expected := []int64{10, 5, 2, 1} clientErr := client.JsonError{ @@ -1557,9 +1562,13 @@ func TestTooManyLogResults(t *testing.T) { Message: "query returned more than 10000 results. Try with this block range [0x100E698, 0x100E6D4].", } + // Simulate currentBlock = 300 + head := &evmtypes.Head{Number: 300} + finalized := &evmtypes.Head{Number: head.Number - lpOpts.FinalityDepth} + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalized, nil).Once() call1 := ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(ctx context.Context, blockNumber *big.Int) (*evmtypes.Head, error) { if blockNumber == nil { - return &evmtypes.Head{Number: 300}, nil // Simulate currentBlock = 300 + require.FailNow(t, "unexpected call to get current head") } return &evmtypes.Head{Number: blockNumber.Int64()}, nil }) @@ -1601,9 +1610,12 @@ func TestTooManyLogResults(t *testing.T) { // Now jump to block 500, but return error no matter how small the block range gets. // Should exit the loop with a critical error instead of hanging. + head = &evmtypes.Head{Number: 500} + finalized = &evmtypes.Head{Number: head.Number - lpOpts.FinalityDepth} + headTracker.On("LatestAndFinalizedBlock", mock.Anything).Return(head, finalized, nil).Once() call1.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(ctx context.Context, blockNumber *big.Int) (*evmtypes.Head, error) { if blockNumber == nil { - return &evmtypes.Head{Number: 500}, nil // Simulate currentBlock = 300 + require.FailNow(t, "unexpected call to get current head") } return &evmtypes.Head{Number: blockNumber.Int64()}, nil }) @@ -1938,7 +1950,7 @@ func TestFindLCA(t *testing.T) { KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(orm, ec, lggr, lpOpts) + lp := logpoller.NewLogPoller(orm, ec, lggr, nil, lpOpts) t.Run("Fails, if failed to select oldest block", func(t *testing.T) { _, err := lp.FindLCA(ctx) require.ErrorContains(t, err, "failed to select the latest block") diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 8427170f1a..40df5616c9 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -35,6 +35,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -59,7 +60,9 @@ func makeTestEvmTxm( RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), ethClient, lggr, lpOpts) + + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), ethClient, lggr, ht, lpOpts) // logic for building components (from evm/evm_txm.go) ------- lggr.Infow("Initializing EVM transaction manager", diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index 2af5b81ccf..a9e5cd5841 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -118,16 +118,23 @@ func (h *Head) IsInChain(blockHash common.Hash) bool { // HashAtHeight returns the hash of the block at the given height, if it is in the chain. // If not in chain, returns the zero hash func (h *Head) HashAtHeight(blockNum int64) common.Hash { - for { + headAtHeight, err := h.HeadAtHeight(blockNum) + if err != nil { + return common.Hash{} + } + + return headAtHeight.BlockHash() +} + +func (h *Head) HeadAtHeight(blockNum int64) (commontypes.Head[common.Hash], error) { + for h != nil { if h.Number == blockNum { - return h.Hash - } - if h.Parent == nil { - break + return h, nil } + h = h.Parent } - return common.Hash{} + return nil, fmt.Errorf("failed to find head at height %d", blockNum) } // ChainLength returns the length of the chain followed by recursively looking up parents diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go index db7b876bb6..6018d68f96 100644 --- a/core/chains/evm/types/models_test.go +++ b/core/chains/evm/types/models_test.go @@ -247,6 +247,26 @@ func TestHead_EarliestInChain(t *testing.T) { assert.Equal(t, int64(1), head.EarliestInChain().BlockNumber()) } +func TestHead_HeadAtHeight(t *testing.T) { + expectedResult := &evmtypes.Head{ + Hash: common.BigToHash(big.NewInt(10)), + Number: 2, + Parent: &evmtypes.Head{ + Number: 1, + }, + } + head := evmtypes.Head{ + Number: 3, + Parent: expectedResult, + } + + headAtHeight, err := head.HeadAtHeight(2) + require.NoError(t, err) + assert.Equal(t, expectedResult, headAtHeight) + _, err = head.HeadAtHeight(0) + assert.Error(t, err, "expected to get an error if head is not in the chain") +} + func TestHead_IsInChain(t *testing.T) { hash1 := utils.NewHash() hash2 := utils.NewHash() diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 1c94e3d7df..b38cd2c450 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -245,7 +245,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod LogPrunePageSize: int64(cfg.EVM().LogPrunePageSize()), BackupPollerBlockDelay: int64(cfg.EVM().BackupLogPollerBlockDelay()), } - logPoller = logpoller.NewLogPoller(logpoller.NewObservedORM(chainID, opts.DS, l), client, l, lpOpts) + logPoller = logpoller.NewLogPoller(logpoller.NewObservedORM(chainID, opts.DS, l), client, l, headTracker, lpOpts) } } diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index a222d5269d..38c8cb8354 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -85,6 +85,18 @@ RPCDefaultBatchSize = 250 # Default # available from the connected node via RPC, due to race conditions in the code of the remote ETH node. In this case you will get false # "zero" blocks that are missing transactions. RPCBlockQueryDelay = 1 # Default +# FinalizedBlockOffset defines the number of blocks by which the latest finalized block will be shifted/delayed. +# For example, suppose RPC returns block 100 as the latest finalized. In that case, the CL Node will treat block `100 - FinalizedBlockOffset` as the latest finalized block and `latest - FinalityDepth - FinalizedBlockOffset` in case of `FinalityTagEnabled = false.` +# With `EnforceRepeatableRead = true,` RPC is considered healthy only if its most recent finalized block is larger or equal to the highest finalized block observed by the CL Node minus `FinalizedBlockOffset.` +# Higher values of `FinalizedBlockOffset` with `EnforceRepeatableRead = true` reduce the number of false `FinalizedBlockOutOfSync` declarations on healthy RPCs that are slightly lagging behind due to network delays. +# This may increase the number of healthy RPCs and reduce the probability that the CL Node will not have any healthy alternatives to the active RPC. +# CAUTION: Setting this to values higher than 0 may delay transaction creation in products (e.g., CCIP, Automation) that base their decision on finalized on-chain events. +# PoS chains with `FinalityTagEnabled=true` and batched (epochs) blocks finalization (e.g., Ethereum Mainnet) must be treated with special care as a minor increase in the `FinalizedBlockOffset` may lead to significant delays. +# For example, let's say that `FinalizedBlockOffset = 1` and blocks are finalized in batches of 32. +# The latest finalized block on chain is 64, so block 63 is the latest finalized for CL Node. +# Block 64 will be treated as finalized by CL Node only when chain's latest finalized block is 65. As chain finalizes blocks in batches of 32, +# CL Node has to wait for a whole new batch to be finalized to treat block 64 as finalized. +FinalizedBlockOffset = 0 # Default [EVM.Transactions] # ForwardersEnabled enables or disables sending transactions through forwarder contracts. @@ -368,7 +380,17 @@ NodeIsSyncingEnabled = false # Default # # Set to 0 to disable. FinalizedBlockPollInterval = '5s' # Default - +# EnforceRepeatableRead defines if Core should only use RPCs whose most recently finalized block is greater or equal to +# `highest finalized block - FinalizedBlockOffset`. In other words, exclude RPCs lagging on latest finalized +# block. +# +# Set false to disable +EnforceRepeatableRead = false # Default +# DeathDeclarationDelay defines the minimum duration an RPC must be in unhealthy state before producing an error log message. +# Larger values might be helpful to reduce the noisiness of health checks like `EnforceRepeatableRead = true', which might be falsely +# trigger declaration of `FinalizedBlockOutOfSync` due to insignificant network delays in broadcasting of the finalized state among RPCs. +# RPC will not be picked to handle a request even if this option is set to a nonzero value. +DeathDeclarationDelay = '10s' # Default # **ADVANCED** # Errors enable the node to provide custom regex patterns to match against error messages from RPCs. [EVM.NodePool.Errors] diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index b6b656c3a0..4db8fbc948 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -101,8 +101,9 @@ var ( { ChainID: ubig.NewI(1), Chain: evmcfg.Chain{ - FinalityDepth: ptr[uint32](26), - FinalityTagEnabled: ptr[bool](false), + FinalityDepth: ptr[uint32](26), + FinalityTagEnabled: ptr[bool](false), + FinalizedBlockOffset: ptr[uint32](12), }, Nodes: []*evmcfg.Node{ { @@ -504,6 +505,7 @@ func TestConfig_Marshal(t *testing.T) { FinalityDepth: ptr[uint32](42), FinalityTagEnabled: ptr[bool](false), FlagsContractAddress: mustAddress("0xae4E781a6218A8031764928E88d457937A954fC3"), + FinalizedBlockOffset: ptr[uint32](16), GasEstimator: evmcfg.GasEstimator{ Mode: ptr("SuggestedPrice"), @@ -593,6 +595,8 @@ func TestConfig_Marshal(t *testing.T) { LeaseDuration: &zeroSeconds, NodeIsSyncingEnabled: ptr(true), FinalizedBlockPollInterval: &second, + EnforceRepeatableRead: ptr(true), + DeathDeclarationDelay: &minute, Errors: evmcfg.ClientErrors{ NonceTooLow: ptr[string]("(: |^)nonce too low"), NonceTooHigh: ptr[string]("(: |^)nonce too high"), @@ -990,6 +994,7 @@ NoNewHeadsThreshold = '1m0s' OperatorFactoryAddress = '0xa5B85635Be42F21f94F28034B7DA440EeFF0F418' RPCDefaultBatchSize = 17 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 16 [EVM.Transactions] ForwardersEnabled = true @@ -1060,6 +1065,8 @@ SyncThreshold = 13 LeaseDuration = '0s' NodeIsSyncingEnabled = true FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' [EVM.NodePool.Errors] NonceTooLow = '(: |^)nonce too low' @@ -1287,10 +1294,11 @@ func TestConfig_Validate(t *testing.T) { - WSURL: missing: required for primary nodes - HTTPURL: missing: required for all nodes - 1.HTTPURL: missing: required for all nodes - - 1: 9 errors: + - 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, celo, gnosis, kroma, 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 - Transactions.AutoPurge.MinAttempts: missing: needs to be set if auto-purge feature is enabled for Foo diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index fd51d52357..c041a2857b 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -287,6 +287,7 @@ NoNewHeadsThreshold = '1m0s' OperatorFactoryAddress = '0xa5B85635Be42F21f94F28034B7DA440EeFF0F418' RPCDefaultBatchSize = 17 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 16 [EVM.Transactions] ForwardersEnabled = true @@ -357,6 +358,8 @@ SyncThreshold = 13 LeaseDuration = '0s' NodeIsSyncingEnabled = true FinalizedBlockPollInterval = '1s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '1m0s' [EVM.NodePool.Errors] NonceTooLow = '(: |^)nonce too low' diff --git a/core/services/chainlink/testdata/config-invalid.toml b/core/services/chainlink/testdata/config-invalid.toml index 68feeeb045..30fbfff472 100644 --- a/core/services/chainlink/testdata/config-invalid.toml +++ b/core/services/chainlink/testdata/config-invalid.toml @@ -53,6 +53,7 @@ SendOnly = true ChainID = '1' ChainType = 'Foo' FinalityDepth = 32 +FinalizedBlockOffset = 64 [EVM.Transactions.AutoPurge] Enabled = true diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 13aac2db7f..22a49476dc 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -274,6 +274,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 12 [EVM.Transactions] ForwardersEnabled = false @@ -328,6 +329,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 @@ -370,6 +373,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x8007e24251b1D2Fc518Eb843A701d9cD21fe0aA3' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -424,6 +428,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 @@ -460,6 +466,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -514,6 +521,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 diff --git a/core/services/chainlink/testdata/config-multi-chain.toml b/core/services/chainlink/testdata/config-multi-chain.toml index e45255a437..5373e0e62d 100644 --- a/core/services/chainlink/testdata/config-multi-chain.toml +++ b/core/services/chainlink/testdata/config-multi-chain.toml @@ -39,6 +39,7 @@ CPUProfileRate = 7 ChainID = '1' FinalityDepth = 26 FinalityTagEnabled = false +FinalizedBlockOffset = 12 [[EVM.Nodes]] Name = 'primary' diff --git a/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go b/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go index ea8f64c02f..8529ad8945 100644 --- a/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go +++ b/core/services/ocr2/plugins/llo/onchain_channel_definition_cache_integration_test.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "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/gethwrappers/llo-feeds/generated/channel_config_store" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -84,8 +85,9 @@ func Test_ChannelDefinitionCache_Integration(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) lp := logpoller.NewLogPoller( - logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, lpOpts) + logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, ht, lpOpts) servicetest.Run(t, lp) cdc := llo.NewChannelDefinitionCache(lggr, orm, lp, configStoreAddress, 0) @@ -156,8 +158,9 @@ func Test_ChannelDefinitionCache_Integration(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) lp := &mockLogPoller{ - LogPoller: logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, lpOpts), + LogPoller: logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, ht, lpOpts), LatestBlockFn: func(ctx context.Context) (int64, error) { return 0, nil }, @@ -198,7 +201,8 @@ func Test_ChannelDefinitionCache_Integration(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), ethClient, lggr, ht, lpOpts) servicetest.Run(t, lp) cdc := llo.NewChannelDefinitionCache(lggr, orm, lp, configStoreAddress, channel2Block.Number().Int64()+1) 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 ace17ca2db..cdd800071d 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 @@ -6,8 +6,6 @@ import ( "testing" "time" - "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" @@ -17,10 +15,13 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" "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/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -505,7 +506,8 @@ func setupDependencies(t *testing.T, db *sqlx.DB, backend *backends.SimulatedBac RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(lorm, ethClient, pollerLggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(lorm, ethClient, pollerLggr, ht, lpOpts) return lp, ethClient } diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index 2be3f5bacb..b61fa25bdc 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -13,6 +13,7 @@ import ( "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" @@ -46,7 +47,8 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), ethClient, lggr, lpOpts) + 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, diff --git a/core/services/registrysyncer/syncer_test.go b/core/services/registrysyncer/syncer_test.go index 6804e4bec4..56818c81dc 100644 --- a/core/services/registrysyncer/syncer_test.go +++ b/core/services/registrysyncer/syncer_test.go @@ -18,7 +18,9 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/types" + 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" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -83,13 +85,16 @@ func newContractReaderFactory(t *testing.T, simulatedBackend *backends.Simulated testutils.SimulatedChainID, ) db := pgtest.NewSqlxDB(t) + const finalityDepth = 2 + ht := headtracker.NewSimulatedHeadTracker(client, false, finalityDepth) lp := logpoller.NewLogPoller( logpoller.NewORM(testutils.SimulatedChainID, db, lggr), client, lggr, + ht, logpoller.Opts{ PollPeriod: 100 * time.Millisecond, - FinalityDepth: 2, + FinalityDepth: finalityDepth, BackfillBatchSize: 3, RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, diff --git a/core/services/relay/evm/config_poller_test.go b/core/services/relay/evm/config_poller_test.go index 8c02c4e2e7..caf48caf49 100644 --- a/core/services/relay/evm/config_poller_test.go +++ b/core/services/relay/evm/config_poller_test.go @@ -32,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclient "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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -99,7 +100,8 @@ func TestConfigPoller(t *testing.T) { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp = logpoller.NewLogPoller(lorm, ethClient, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp = logpoller.NewLogPoller(lorm, ethClient, lggr, ht, lpOpts) servicetest.Run(t, lp) } diff --git a/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go b/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go index b9f141b2d0..9240780935 100644 --- a/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go +++ b/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go @@ -17,6 +17,7 @@ import ( . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "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/gethwrappers/generated/chain_reader_tester" _ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" // force binding for tx type @@ -199,7 +200,8 @@ func (it *EVMChainReaderInterfaceTester[T]) GetChainReader(t T) clcommontypes.Co RpcBatchSize: 1, KeepFinalizedBlocksDepth: 10000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(it.Helper.ChainID(), db, lggr), it.client, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(it.client, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(it.Helper.ChainID(), db, lggr), it.client, lggr, ht, lpOpts) require.NoError(t, lp.Start(ctx)) // encode and decode the config to ensure the test covers type issues diff --git a/core/services/relay/evm/functions/config_poller_test.go b/core/services/relay/evm/functions/config_poller_test.go index 2d96b2fd15..c44d64c5ba 100644 --- a/core/services/relay/evm/functions/config_poller_test.go +++ b/core/services/relay/evm/functions/config_poller_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" 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" evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" @@ -88,7 +89,8 @@ func runTest(t *testing.T, pluginType functions.FunctionsPluginType, expectedDig RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(lorm, ethClient, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(lorm, ethClient, lggr, ht, lpOpts) servicetest.Run(t, lp) configPoller, err := functions.NewFunctionsConfigPoller(pluginType, lp, lggr) require.NoError(t, err) diff --git a/core/services/relay/evm/mercury/helpers_test.go b/core/services/relay/evm/mercury/helpers_test.go index f2923696bf..c7c59bf2e1 100644 --- a/core/services/relay/evm/mercury/helpers_test.go +++ b/core/services/relay/evm/mercury/helpers_test.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" 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" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" @@ -174,7 +175,8 @@ func SetupTH(t *testing.T, feedID common.Hash) TestHarness { RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, } - lp := logpoller.NewLogPoller(lorm, ethClient, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(lorm, ethClient, lggr, ht, lpOpts) servicetest.Run(t, lp) configPoller, err := NewConfigPoller(testutils.Context(t), lggr, lp, verifierAddress, feedID) diff --git a/core/services/vrf/v2/listener_v2_log_listener_test.go b/core/services/vrf/v2/listener_v2_log_listener_test.go index 5b827a5291..0865245504 100644 --- a/core/services/vrf/v2/listener_v2_log_listener_test.go +++ b/core/services/vrf/v2/listener_v2_log_listener_test.go @@ -21,6 +21,7 @@ import ( "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" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -102,7 +103,8 @@ func setupVRFLogPollerListenerTH(t *testing.T, RpcBatchSize: rpcBatchSize, KeepFinalizedBlocksDepth: keepFinalizedBlocksDepth, } - lp := logpoller.NewLogPoller(o, esc, lggr, lpOpts) + ht := headtracker.NewSimulatedHeadTracker(esc, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(o, esc, lggr, ht, lpOpts) emitterAddress1, _, emitter1, err := log_emitter.DeployLogEmitter(owner, ec) require.NoError(t, err) diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index d69f0aa506..76326f9a4d 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -287,6 +287,7 @@ NoNewHeadsThreshold = '1m0s' OperatorFactoryAddress = '0xa5B85635Be42F21f94F28034B7DA440EeFF0F418' RPCDefaultBatchSize = 17 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = true @@ -356,6 +357,8 @@ SyncThreshold = 13 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.NodePool.Errors] NonceTooLow = '(: |^)nonce too low' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 13aac2db7f..8e6682dee3 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -274,6 +274,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -328,6 +329,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 @@ -370,6 +373,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x8007e24251b1D2Fc518Eb843A701d9cD21fe0aA3' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -424,6 +428,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 @@ -460,6 +466,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -514,6 +521,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 diff --git a/core/web/resolver/testdata/config-multi-chain.toml b/core/web/resolver/testdata/config-multi-chain.toml index 3598e92cdc..9abb171940 100644 --- a/core/web/resolver/testdata/config-multi-chain.toml +++ b/core/web/resolver/testdata/config-multi-chain.toml @@ -39,6 +39,7 @@ CPUProfileRate = 7 ChainID = '1' FinalityDepth = 26 FinalityTagEnabled = false +FinalizedBlockOffset = 0 [EVM.OCR2] [EVM.OCR2.Automation] diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 5f40d9fa69..c35d90211a 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1776,6 +1776,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -1830,6 +1831,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -1866,6 +1869,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -1920,6 +1924,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -1956,6 +1962,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2010,6 +2017,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2046,6 +2055,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2100,6 +2110,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2137,6 +2149,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2191,6 +2204,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -2227,6 +2242,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2281,6 +2297,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2317,6 +2335,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2371,6 +2390,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2408,6 +2429,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x8007e24251b1D2Fc518Eb843A701d9cD21fe0aA3' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2462,6 +2484,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2498,6 +2522,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2552,6 +2577,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2587,6 +2614,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2641,6 +2669,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2676,6 +2706,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2730,6 +2761,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2766,6 +2799,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2820,6 +2854,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2857,6 +2893,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -2911,6 +2948,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -2947,6 +2986,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3001,6 +3041,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -3037,6 +3079,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3091,6 +3134,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -3127,6 +3172,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '12m0s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 15 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3181,6 +3227,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -3217,6 +3265,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '6m0s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 15 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3271,6 +3320,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -3307,6 +3358,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3361,6 +3413,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -3397,6 +3451,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3451,6 +3506,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -3487,6 +3544,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '1m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3541,6 +3599,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -3577,6 +3637,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '1m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3631,6 +3692,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -3667,6 +3730,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '1m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3721,6 +3785,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -3758,6 +3824,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3812,6 +3879,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -3848,6 +3917,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3902,6 +3972,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -3937,6 +4009,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -3991,6 +4064,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4027,6 +4102,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4081,6 +4157,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4117,6 +4195,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '6m0s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 15 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4171,6 +4250,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4207,6 +4288,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4261,6 +4343,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4297,6 +4381,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4351,6 +4436,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4386,6 +4473,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4440,6 +4528,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4476,6 +4566,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '12m0s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4530,6 +4621,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4566,6 +4659,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4620,6 +4714,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4656,6 +4752,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '12m0s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4710,6 +4807,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4746,6 +4845,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4800,6 +4900,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -4835,6 +4937,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4889,6 +4992,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -4925,6 +5030,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4979,6 +5085,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -5015,6 +5123,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5069,6 +5178,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -5106,6 +5217,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5160,6 +5272,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -5196,6 +5310,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '1m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5250,6 +5365,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -5286,6 +5403,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5340,6 +5458,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -5376,6 +5496,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5430,6 +5551,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -5466,6 +5589,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '1m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5520,6 +5644,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -5555,6 +5681,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5609,6 +5736,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -5644,6 +5773,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5698,6 +5828,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -5733,6 +5865,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5787,6 +5920,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -5823,6 +5958,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5877,6 +6013,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -5913,6 +6051,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5967,6 +6106,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -6002,6 +6143,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6056,6 +6198,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -6092,6 +6236,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6146,6 +6291,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6182,6 +6329,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6236,6 +6384,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6273,6 +6423,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6327,6 +6478,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6364,6 +6517,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6418,6 +6572,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6454,6 +6610,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6508,6 +6665,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6544,6 +6703,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6598,6 +6758,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6634,6 +6796,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6688,6 +6851,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6724,6 +6889,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6778,6 +6944,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -6814,6 +6982,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '40s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6868,6 +7037,8 @@ SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6904,6 +7075,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6958,6 +7130,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -6994,6 +7168,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '30s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -7048,6 +7223,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -7236,6 +7413,22 @@ block, but it is possible to receive a head BEFORE that block is actually available from the connected node via RPC, due to race conditions in the code of the remote ETH node. In this case you will get false "zero" blocks that are missing transactions. +### FinalizedBlockOffset +```toml +FinalizedBlockOffset = 0 # Default +``` +FinalizedBlockOffset defines the number of blocks by which the latest finalized block will be shifted/delayed. +For example, suppose RPC returns block 100 as the latest finalized. In that case, the CL Node will treat block `100 - FinalizedBlockOffset` as the latest finalized block and `latest - FinalityDepth - FinalizedBlockOffset` in case of `FinalityTagEnabled = false.` +With `EnforceRepeatableRead = true,` RPC is considered healthy only if its most recent finalized block is larger or equal to the highest finalized block observed by the CL Node minus `FinalizedBlockOffset.` +Higher values of `FinalizedBlockOffset` with `EnforceRepeatableRead = true` reduce the number of false `FinalizedBlockOutOfSync` declarations on healthy RPCs that are slightly lagging behind due to network delays. +This may increase the number of healthy RPCs and reduce the probability that the CL Node will not have any healthy alternatives to the active RPC. +CAUTION: Setting this to values higher than 0 may delay transaction creation in products (e.g., CCIP, Automation) that base their decision on finalized on-chain events. +PoS chains with `FinalityTagEnabled=true` and batched (epochs) blocks finalization (e.g., Ethereum Mainnet) must be treated with special care as a minor increase in the `FinalizedBlockOffset` may lead to significant delays. +For example, let's say that `FinalizedBlockOffset = 1` and blocks are finalized in batches of 32. +The latest finalized block on chain is 64, so block 63 is the latest finalized for CL Node. +Block 64 will be treated as finalized by CL Node only when chain's latest finalized block is 65. As chain finalizes blocks in batches of 32, +CL Node has to wait for a whole new batch to be finalized to treat block 64 as finalized. + ## EVM.Transactions ```toml [EVM.Transactions] @@ -7743,6 +7936,8 @@ SyncThreshold = 5 # Default LeaseDuration = '0s' # Default NodeIsSyncingEnabled = false # Default FinalizedBlockPollInterval = '5s' # Default +EnforceRepeatableRead = false # Default +DeathDeclarationDelay = '10s' # Default ``` The node pool manages multiple RPC endpoints. @@ -7816,6 +8011,25 @@ reported based on latest block and finality depth. Set to 0 to disable. +### EnforceRepeatableRead +```toml +EnforceRepeatableRead = false # Default +``` +EnforceRepeatableRead defines if Core should only use RPCs whose most recently finalized block is greater or equal to +`highest finalized block - FinalizedBlockOffset`. In other words, exclude RPCs lagging on latest finalized +block. + +Set false to disable + +### DeathDeclarationDelay +```toml +DeathDeclarationDelay = '10s' # Default +``` +DeathDeclarationDelay defines the minimum duration an RPC must be in unhealthy state before producing an error log message. +Larger values might be helpful to reduce the noisiness of health checks like `EnforceRepeatableRead = true', which might be falsely +trigger declaration of `FinalizedBlockOutOfSync` due to insignificant network delays in broadcasting of the finalized state among RPCs. +RPC will not be picked to handle a request even if this option is set to a nonzero value. + ## EVM.NodePool.Errors :warning: **_ADVANCED_**: _Do not change these settings unless you know what you are doing._ ```toml diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 6e2a40beb7..e8e1046cef 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -330,6 +330,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -384,6 +385,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 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 5db4e8527d..c7b651e3ae 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -330,6 +330,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -384,6 +385,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index bcf054cbca..1eee9f595c 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -330,6 +330,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -384,6 +385,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 6b5932cfef..73d557c0ae 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -320,6 +320,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -374,6 +375,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 688829513e..76a134b776 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -327,6 +327,7 @@ NoNewHeadsThreshold = '3m0s' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [EVM.Transactions] ForwardersEnabled = false @@ -381,6 +382,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [EVM.OCR] ContractConfirmations = 4 From e7199f78aafe3dd7a8c4b80b70841c76bf6ec623 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Mon, 1 Jul 2024 10:02:56 -0500 Subject: [PATCH 32/61] add make test-short for running short tests with quiet logs (#13628) --- GNUmakefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GNUmakefile b/GNUmakefile index b3077278a1..8353a288e8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -179,6 +179,10 @@ goreleaser-dev-release: ## run goreleaser snapshot release modgraph: ./tools/bin/modgraph > go.md +.PHONY: test-short +test-short: ## Run 'go test -short' and suppress uninteresting output + go test -short ./... | grep -v "[no test files]" | grep -v "\(cached\)" + help: @echo "" @echo " .__ .__ .__ .__ __" From 2ad16bbd5015020273fe22a74a5f48b74723aeb8 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:51:31 -0600 Subject: [PATCH 33/61] fix: solana e2e test ws error (#13728) * fix: solana e2e test ws error * bump to merged commit --- 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 4bbd546766..86a8613d1f 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -277,7 +277,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 21d3207fdd..8d27696be7 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1220,8 +1220,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= diff --git a/go.mod b/go.mod index 02624a20c6..24e6c0cc46 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/go.sum b/go.sum index dbcf086fdc..7102d255f1 100644 --- a/go.sum +++ b/go.sum @@ -1177,8 +1177,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 123811ebe2..800e8a8d19 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -381,7 +381,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b31b5487eb..b6b4863897 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1521,8 +1521,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-testing-framework v1.31.7 h1:Vy4ah8VAfj+Y7vVmhjvwyAO6wG+Fp2vzdkSJwJPMQO4= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 800f514722..3aea458a49 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -367,7 +367,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect - github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 // indirect + github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index d284b8484b..0c0db84271 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1511,8 +1511,8 @@ github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44 h1:hprOn+9+vIG+1N3nIvo96r0Bdw0kUzCtpJNSiOd8qM8= -github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240627134229-63de1a005c44/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= +github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8/go.mod h1:NbXXQaNFskVMYRut0MvBlcHu/vDgipGMwYjamvjVB9Y= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba h1:YNSlhK5mobyAaw02LPGgIEuS3lXyCTXcc6oaV2L6uUI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-testing-framework v1.31.7 h1:Vy4ah8VAfj+Y7vVmhjvwyAO6wG+Fp2vzdkSJwJPMQO4= From 0b7d2c497a508efa5a827714780d908b7b8eda19 Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:25:42 -0700 Subject: [PATCH 34/61] [KS-363] Update Streams codec to new interface (#13725) Separated Unwrap() and Validate(). --- core/capabilities/streams/codec.go | 58 +++++++++++++------------ core/capabilities/streams/codec_test.go | 28 +++++++----- 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, 59 insertions(+), 51 deletions(-) diff --git a/core/capabilities/streams/codec.go b/core/capabilities/streams/codec.go index af574f98fa..d2bc451a39 100644 --- a/core/capabilities/streams/codec.go +++ b/core/capabilities/streams/codec.go @@ -18,38 +18,12 @@ type codec struct { var _ datastreams.ReportCodec = &codec{} -func (c *codec) UnwrapValid(wrapped values.Value, allowedSigners [][]byte, minRequiredSignatures int) ([]datastreams.FeedReport, error) { - signersMap := make(map[common.Address]struct{}) - for _, signer := range allowedSigners { - signersMap[common.BytesToAddress(signer)] = struct{}{} - } +func (c *codec) Unwrap(wrapped values.Value) ([]datastreams.FeedReport, error) { dest, err := datastreams.UnwrapFeedReportList(wrapped) if err != nil { return nil, fmt.Errorf("failed to unwrap: %v", err) } for i, report := range dest { - // signatures (report and context are signed together) - sigData := append(crypto.Keccak256(report.FullReport), report.ReportContext...) - fullHash := crypto.Keccak256(sigData) - validated := map[common.Address]struct{}{} - for _, sig := range report.Signatures { - signerPubkey, err2 := crypto.SigToPub(fullHash, sig) - if err2 != nil { - return nil, fmt.Errorf("malformed signer: %v", err2) - } - signerAddr := crypto.PubkeyToAddress(*signerPubkey) - if _, ok := signersMap[signerAddr]; !ok { - c.lggr.Debugw("invalid signer", "signerAddr", signerAddr) - continue - } - validated[signerAddr] = struct{}{} - if len(validated) >= minRequiredSignatures { - break // early exit - } - } - if len(validated) < minRequiredSignatures { - return nil, fmt.Errorf("not enough valid signatures %d, needed %d", len(validated), minRequiredSignatures) - } // decoding fields id, err2 := datastreams.NewFeedID(report.FeedID) if err2 != nil { @@ -70,6 +44,36 @@ func (c *codec) Wrap(reports []datastreams.FeedReport) (values.Value, error) { return values.Wrap(reports) } +func (c *codec) Validate(report datastreams.FeedReport, allowedSigners [][]byte, minRequiredSignatures int) error { + signersMap := make(map[common.Address]struct{}) + for _, signer := range allowedSigners { + signersMap[common.BytesToAddress(signer)] = struct{}{} + } + // signatures (report and context are signed together) + sigData := append(crypto.Keccak256(report.FullReport), report.ReportContext...) + fullHash := crypto.Keccak256(sigData) + validated := map[common.Address]struct{}{} + for _, sig := range report.Signatures { + signerPubkey, err2 := crypto.SigToPub(fullHash, sig) + if err2 != nil { + return fmt.Errorf("malformed signer: %v", err2) + } + signerAddr := crypto.PubkeyToAddress(*signerPubkey) + if _, ok := signersMap[signerAddr]; !ok { + c.lggr.Debugw("invalid signer", "signerAddr", signerAddr) + continue + } + validated[signerAddr] = struct{}{} + if len(validated) >= minRequiredSignatures { + break // early exit + } + } + if len(validated) < minRequiredSignatures { + return fmt.Errorf("not enough valid signatures %d, needed %d", len(validated), minRequiredSignatures) + } + return nil +} + func NewCodec(lggr logger.Logger) *codec { return &codec{lggr: lggr} } diff --git a/core/capabilities/streams/codec_test.go b/core/capabilities/streams/codec_test.go index 22100b0af5..e3ada731e4 100644 --- a/core/capabilities/streams/codec_test.go +++ b/core/capabilities/streams/codec_test.go @@ -66,21 +66,25 @@ func TestCodec_WrapUnwrap(t *testing.T) { require.NoError(t, err) // wrong type - _, err = codec.UnwrapValid(values.NewBool(true), nil, 0) + _, err = codec.Unwrap(values.NewBool(true)) require.Error(t, err) - // wrong signatures - _, err = codec.UnwrapValid(wrapped, nil, 1) - require.Error(t, err) - - // success - reports, err := codec.UnwrapValid(wrapped, allowedSigners, 2) + // correct reports byt wrong signatures + unwrapped, err := codec.Unwrap(wrapped) require.NoError(t, err) - require.Equal(t, 2, len(reports)) - require.Equal(t, price1.Bytes(), reports[0].BenchmarkPrice) - require.Equal(t, price2.Bytes(), reports[1].BenchmarkPrice) - require.Equal(t, timestamp1, reports[0].ObservationTimestamp) - require.Equal(t, timestamp2, reports[1].ObservationTimestamp) + require.Equal(t, 2, len(unwrapped)) + require.Equal(t, price1.Bytes(), unwrapped[0].BenchmarkPrice) + require.Equal(t, price2.Bytes(), unwrapped[1].BenchmarkPrice) + require.Equal(t, timestamp1, unwrapped[0].ObservationTimestamp) + require.Equal(t, timestamp2, unwrapped[1].ObservationTimestamp) + for _, report := range unwrapped { + require.Error(t, codec.Validate(report, nil, 1)) + } + + // valid signatures + for _, report := range unwrapped { + require.NoError(t, codec.Validate(report, allowedSigners, 2)) + } } func newFeedID(t *testing.T) ([32]byte, string) { diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 86a8613d1f..b7f5b9ab60 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 8d27696be7..196c76cdf3 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1212,8 +1212,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.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/go.mod b/go.mod index 24e6c0cc46..510540ab0e 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 diff --git a/go.sum b/go.sum index 7102d255f1..75e9455326 100644 --- a/go.sum +++ b/go.sum @@ -1169,8 +1169,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.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 800e8a8d19..897e51240d 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -28,7 +28,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b6b4863897..5009b6ea85 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1513,8 +1513,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.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 3aea458a49..e7b879b6a3 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.1.7-0.20240627145530-c769d7129f16 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 0c0db84271..6b770542b9 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1503,8 +1503,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.1.7-0.20240627145530-c769d7129f16 h1:YTE+iBNaRNZplGiiTZFYlnUrVYq1pyQr8Yiz3V3gsN8= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240627145530-c769d7129f16/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From 2c2ca6a27899295dc87e48e4378671dbbe06ac48 Mon Sep 17 00:00:00 2001 From: Yong Kang Chia <165454358+yongkangchia@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:17:20 +0800 Subject: [PATCH 35/61] [BCI-2953] Initial Aptos keystore (#13564) * chain type to include aptos * aptos key ed25519 implementation * add aptos to keystore master * added exports for keys * removed sdk dependency * updated go mod * Added tests for account sdk deps * added aptos keystore * added interface assertion to solana * added aptos keyring * added aptos keystore mocks * added aptos key controller & router * Added aptos keys command * added aptos keystore e2e tests * Added Aptos network ORM test for key * Added aptos ocr2 keys support * Revert "Added Aptos network ORM test for key" This reverts commit 444fe9509647db003b501abd2d8cb72941eea141. * Added Aptos export functionality * Modified Aptos Accounts for key rotation * added aptos keystore to orm validation * Addded Change logs * Updated keys implementation to remove address * Revert "updated go mod" This reverts commit a8f7e84c8b868eda256f71b576251ce1e76247b6. * Update changeset * Updated GraphQL to include Aptos * Linting fixes * added aptos configs for keystore * Changed Aptos config to RawConfig * Added Mock file for general config * using *bool type for aptos enabled * added debug for error * Fixed tests + added ORM * Added Test Scripts * Updated type of raw config * update all packages go mod tidy * update all packages go mod * Update core/services/chainlink/config.go Co-authored-by: Jordan Krage * Removed Address in key * Fixed merge conflicts * nit changes based on reviews * Added typecast check for keyring * Added config type cast check * make generate update version * update validation method * update config validation * Removed Pointer type for RawConfig * Updated Validate with better error message * Added Error config * Update struct of RawConfig * removed uncessary config validation * Added missing starknet keystore tests * added styling feedback * Update core/services/keystore/keys/aptoskey/account.go Co-authored-by: Jordan Krage * Removed empty array table for config * fixed lint --------- Co-authored-by: Jordan Krage --- .changeset/real-fireants-rule.md | 5 + core/cmd/app.go | 1 + core/cmd/aptos_keys_commands.go | 57 ++++ core/cmd/aptos_keys_commands_test.go | 175 ++++++++++++ core/config/app_config.go | 1 + core/internal/cltest/cltest.go | 2 + core/services/chainlink/config.go | 26 ++ core/services/chainlink/config_general.go | 9 + core/services/chainlink/config_test.go | 5 +- .../chainlink/mocks/general_config.go | 18 ++ .../chainlink/testdata/config-invalid.toml | 3 + core/services/job/job_orm_test.go | 12 + core/services/job/orm.go | 6 +- core/services/keystore/aptos.go | 182 ++++++++++++ core/services/keystore/aptos_test.go | 138 +++++++++ core/services/keystore/chaintype/chaintype.go | 4 +- .../keystore/keys/aptoskey/account.go | 72 +++++ .../keystore/keys/aptoskey/account_test.go | 141 +++++++++ .../services/keystore/keys/aptoskey/export.go | 48 ++++ .../keystore/keys/aptoskey/export_test.go | 19 ++ core/services/keystore/keys/aptoskey/key.go | 103 +++++++ .../keystore/keys/ocr2key/aptos_keyring.go | 118 ++++++++ .../keys/ocr2key/aptos_keyring_test.go | 58 ++++ .../keystore/keys/ocr2key/cosmos_keyring.go | 13 +- core/services/keystore/keys/ocr2key/export.go | 2 + .../keystore/keys/ocr2key/export_test.go | 1 + .../keystore/keys/ocr2key/key_bundle.go | 7 + core/services/keystore/keys/solkey/key.go | 2 +- core/services/keystore/keystoretest.go | 1 + core/services/keystore/master.go | 10 + core/services/keystore/mocks/aptos.go | 268 ++++++++++++++++++ core/services/keystore/mocks/master.go | 20 ++ core/services/keystore/models.go | 18 ++ core/services/keystore/solana.go | 3 + core/web/aptos_keys_controller.go | 12 + core/web/aptos_keys_controller_test.go | 109 +++++++ core/web/auth/auth_test.go | 10 + core/web/presenters/aptos_key.go | 32 +++ core/web/resolver/ocr2_keys.go | 6 + core/web/resolver/ocr2_keys_test.go | 1 + core/web/router.go | 1 + core/web/schema/type/ocr2_keys.graphql | 1 + testdata/scripts/help-all/help-all.txtar | 6 + testdata/scripts/keys/aptos/help.txtar | 20 ++ testdata/scripts/keys/help.txtar | 1 + 45 files changed, 1737 insertions(+), 10 deletions(-) create mode 100644 .changeset/real-fireants-rule.md create mode 100644 core/cmd/aptos_keys_commands.go create mode 100644 core/cmd/aptos_keys_commands_test.go create mode 100644 core/services/keystore/aptos.go create mode 100644 core/services/keystore/aptos_test.go create mode 100644 core/services/keystore/keys/aptoskey/account.go create mode 100644 core/services/keystore/keys/aptoskey/account_test.go create mode 100644 core/services/keystore/keys/aptoskey/export.go create mode 100644 core/services/keystore/keys/aptoskey/export_test.go create mode 100644 core/services/keystore/keys/aptoskey/key.go create mode 100644 core/services/keystore/keys/ocr2key/aptos_keyring.go create mode 100644 core/services/keystore/keys/ocr2key/aptos_keyring_test.go create mode 100644 core/services/keystore/mocks/aptos.go create mode 100644 core/web/aptos_keys_controller.go create mode 100644 core/web/aptos_keys_controller_test.go create mode 100644 core/web/presenters/aptos_key.go create mode 100644 testdata/scripts/keys/aptos/help.txtar diff --git a/.changeset/real-fireants-rule.md b/.changeset/real-fireants-rule.md new file mode 100644 index 0000000000..4e3e83b484 --- /dev/null +++ b/.changeset/real-fireants-rule.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#changed Added Aptos Keystore to Core. This includes Aptos Key which uses ED25519, Keystore, Relevant tests diff --git a/core/cmd/app.go b/core/cmd/app.go index 378f7e8bd6..94acfc4d74 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -194,6 +194,7 @@ func NewApp(s *Shell) *cli.App { keysCommand("Cosmos", NewCosmosKeysClient(s)), keysCommand("Solana", NewSolanaKeysClient(s)), keysCommand("StarkNet", NewStarkNetKeysClient(s)), + keysCommand("Aptos", NewAptosKeysClient(s)), keysCommand("DKGSign", NewDKGSignKeysClient(s)), keysCommand("DKGEncrypt", NewDKGEncryptKeysClient(s)), diff --git a/core/cmd/aptos_keys_commands.go b/core/cmd/aptos_keys_commands.go new file mode 100644 index 0000000000..cabad34751 --- /dev/null +++ b/core/cmd/aptos_keys_commands.go @@ -0,0 +1,57 @@ +package cmd + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +type AptosKeyPresenter struct { + JAID + presenters.AptosKeyResource +} + +// RenderTable implements TableRenderer +func (p AptosKeyPresenter) RenderTable(rt RendererTable) error { + headers := []string{"ID", "Aptos Public Key"} + rows := [][]string{p.ToRow()} + + if _, err := rt.Write([]byte("🔑 Aptos Keys\n")); err != nil { + return err + } + renderList(headers, rows, rt.Writer) + + return utils.JustError(rt.Write([]byte("\n"))) +} + +func (p *AptosKeyPresenter) ToRow() []string { + row := []string{ + p.ID, + p.PubKey, + } + + return row +} + +type AptosKeyPresenters []AptosKeyPresenter + +// RenderTable implements TableRenderer +func (ps AptosKeyPresenters) RenderTable(rt RendererTable) error { + headers := []string{"ID", "Aptos Public Key"} + rows := [][]string{} + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + if _, err := rt.Write([]byte("🔑 Aptos Keys\n")); err != nil { + return err + } + renderList(headers, rows, rt.Writer) + + return utils.JustError(rt.Write([]byte("\n"))) +} + +func NewAptosKeysClient(s *Shell) KeysClient { + return newKeysClient[aptoskey.Key, AptosKeyPresenter, AptosKeyPresenters]("Aptos", s) +} diff --git a/core/cmd/aptos_keys_commands_test.go b/core/cmd/aptos_keys_commands_test.go new file mode 100644 index 0000000000..c88a8e539a --- /dev/null +++ b/core/cmd/aptos_keys_commands_test.go @@ -0,0 +1,175 @@ +package cmd_test + +import ( + "bytes" + "context" + "flag" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/urfave/cli" + + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func TestAptosKeyPresenter_RenderTable(t *testing.T) { + t.Parallel() + + var ( + id = "1" + pubKey = "somepubkey" + buffer = bytes.NewBufferString("") + r = cmd.RendererTable{Writer: buffer} + ) + + p := cmd.AptosKeyPresenter{ + JAID: cmd.JAID{ID: id}, + AptosKeyResource: presenters.AptosKeyResource{ + JAID: presenters.NewJAID(id), + PubKey: pubKey, + }, + } + + // Render a single resource + require.NoError(t, p.RenderTable(r)) + + output := buffer.String() + assert.Contains(t, output, id) + assert.Contains(t, output, pubKey) + + // Render many resources + buffer.Reset() + ps := cmd.AptosKeyPresenters{p} + require.NoError(t, ps.RenderTable(r)) + + output = buffer.String() + assert.Contains(t, output, id) + assert.Contains(t, output, pubKey) +} + +func TestShell_AptosKeys(t *testing.T) { + app := startNewApplicationV2(t, nil) + ks := app.GetKeyStore().Aptos() + cleanup := func() { + ctx := context.Background() + keys, err := ks.GetAll() + require.NoError(t, err) + for _, key := range keys { + require.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) + } + requireAptosKeyCount(t, app, 0) + } + + t.Run("ListAptosKeys", func(tt *testing.T) { + defer cleanup() + ctx := testutils.Context(t) + client, r := app.NewShellAndRenderer() + key, err := app.GetKeyStore().Aptos().Create(ctx) + require.NoError(t, err) + requireAptosKeyCount(t, app, 1) + assert.Nil(t, cmd.NewAptosKeysClient(client).ListKeys(cltest.EmptyCLIContext())) + require.Equal(t, 1, len(r.Renders)) + keys := *r.Renders[0].(*cmd.AptosKeyPresenters) + assert.True(t, key.PublicKeyStr() == keys[0].PubKey) + }) + + t.Run("CreateAptosKey", func(tt *testing.T) { + defer cleanup() + client, _ := app.NewShellAndRenderer() + require.NoError(t, cmd.NewAptosKeysClient(client).CreateKey(nilContext)) + keys, err := app.GetKeyStore().Aptos().GetAll() + require.NoError(t, err) + require.Len(t, keys, 1) + }) + + t.Run("DeleteAptosKey", func(tt *testing.T) { + defer cleanup() + ctx := testutils.Context(t) + client, _ := app.NewShellAndRenderer() + key, err := app.GetKeyStore().Aptos().Create(ctx) + require.NoError(t, err) + requireAptosKeyCount(t, app, 1) + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(cmd.NewAptosKeysClient(client).DeleteKey, set, "aptos") + + require.NoError(tt, set.Set("yes", "true")) + + strID := key.ID() + err = set.Parse([]string{strID}) + require.NoError(t, err) + c := cli.NewContext(nil, set, nil) + err = cmd.NewAptosKeysClient(client).DeleteKey(c) + require.NoError(t, err) + requireAptosKeyCount(t, app, 0) + }) + + t.Run("ImportExportAptosKey", func(tt *testing.T) { + defer cleanup() + defer deleteKeyExportFile(t) + ctx := testutils.Context(t) + client, _ := app.NewShellAndRenderer() + + _, err := app.GetKeyStore().Aptos().Create(ctx) + require.NoError(t, err) + + keys := requireAptosKeyCount(t, app, 1) + key := keys[0] + keyName := keyNameForTest(t) + + // Export test invalid id + set := flag.NewFlagSet("test Aptos export", 0) + flagSetApplyFromAction(cmd.NewAptosKeysClient(client).ExportKey, set, "aptos") + + require.NoError(tt, set.Parse([]string{"0"})) + require.NoError(tt, set.Set("new-password", "../internal/fixtures/incorrect_password.txt")) + require.NoError(tt, set.Set("output", keyName)) + + c := cli.NewContext(nil, set, nil) + err = cmd.NewAptosKeysClient(client).ExportKey(c) + require.Error(t, err, "Error exporting") + require.Error(t, utils.JustError(os.Stat(keyName))) + + // Export test + set = flag.NewFlagSet("test Aptos export", 0) + flagSetApplyFromAction(cmd.NewAptosKeysClient(client).ExportKey, set, "aptos") + + require.NoError(tt, set.Parse([]string{fmt.Sprint(key.ID())})) + require.NoError(tt, set.Set("new-password", "../internal/fixtures/incorrect_password.txt")) + require.NoError(tt, set.Set("output", keyName)) + + c = cli.NewContext(nil, set, nil) + + require.NoError(t, cmd.NewAptosKeysClient(client).ExportKey(c)) + require.NoError(t, utils.JustError(os.Stat(keyName))) + + require.NoError(t, utils.JustError(app.GetKeyStore().Aptos().Delete(ctx, key.ID()))) + requireAptosKeyCount(t, app, 0) + + set = flag.NewFlagSet("test Aptos import", 0) + flagSetApplyFromAction(cmd.NewAptosKeysClient(client).ImportKey, set, "aptos") + + require.NoError(tt, set.Parse([]string{keyName})) + require.NoError(tt, set.Set("old-password", "../internal/fixtures/incorrect_password.txt")) + c = cli.NewContext(nil, set, nil) + require.NoError(t, cmd.NewAptosKeysClient(client).ImportKey(c)) + + requireAptosKeyCount(t, app, 1) + }) +} + +func requireAptosKeyCount(t *testing.T, app chainlink.Application, length int) []aptoskey.Key { + t.Helper() + keys, err := app.GetKeyStore().Aptos().GetAll() + require.NoError(t, err) + require.Len(t, keys, length) + return keys +} diff --git a/core/config/app_config.go b/core/config/app_config.go index 869477218d..112e242636 100644 --- a/core/config/app_config.go +++ b/core/config/app_config.go @@ -25,6 +25,7 @@ type AppConfig interface { CosmosEnabled() bool SolanaEnabled() bool StarkNetEnabled() bool + AptosEnabled() bool Validate() error ValidateDB() error diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index e86394d82f..724af71b4a 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -66,6 +66,7 @@ import ( "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/keys/aptoskey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey" @@ -126,6 +127,7 @@ var ( DefaultP2PKey = p2pkey.MustNewV2XXXTestingOnly(big.NewInt(KeyBigIntSeed)) DefaultSolanaKey = solkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultStarkNetKey = starkkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) + DefaultAptosKey = aptoskey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultVRFKey = vrfkey.MustNewV2XXXTestingOnly(big.NewInt(KeyBigIntSeed)) DefaultDKGSignKey = dkgsignkey.MustNewXXXTestingOnly(big.NewInt(KeyBigIntSeed)) DefaultDKGEncryptKey = dkgencryptkey.MustNewXXXTestingOnly(big.NewInt(KeyBigIntSeed)) diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go index 200d4973ed..dc301c0967 100644 --- a/core/services/chainlink/config.go +++ b/core/services/chainlink/config.go @@ -42,6 +42,32 @@ type Config struct { Solana solcfg.TOMLConfigs `toml:",omitempty"` Starknet stkcfg.TOMLConfigs `toml:",omitempty"` + + Aptos RawConfigs `toml:",omitempty"` +} + +// RawConfigs is a list of RawConfig. +type RawConfigs []RawConfig + +// RawConfig is the config used for chains that are not embedded. +type RawConfig map[string]any + +// ValidateConfig returns an error if the Config is not valid for use, as-is. +func (c *RawConfig) ValidateConfig() (err error) { + if v, ok := (*c)["Enabled"]; ok { + if _, ok := v.(*bool); !ok { + err = multierr.Append(err, commonconfig.ErrInvalid{Name: "Enabled", Value: v, Msg: "expected *bool"}) + } + } + return err +} + +func (c *RawConfig) IsEnabled() bool { + if c == nil { + return false + } + + return (*c)["Enabled"] == nil || *(*c)["Enabled"].(*bool) } // TOMLString returns a TOML encoded string. diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go index 5b4a6271d5..5b6b839fb5 100644 --- a/core/services/chainlink/config_general.go +++ b/core/services/chainlink/config_general.go @@ -345,6 +345,15 @@ func (g *generalConfig) StarkNetEnabled() bool { return false } +func (g *generalConfig) AptosEnabled() bool { + for _, c := range g.c.Aptos { + if c.IsEnabled() { + return true + } + } + return false +} + func (g *generalConfig) WebServer() config.WebServer { return &webServerConfig{c: g.c.WebServer, s: g.secrets.WebServer, rootDir: g.RootDir} } diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 4db8fbc948..576a932e3c 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -1264,7 +1264,7 @@ func TestConfig_Validate(t *testing.T) { toml string exp string }{ - {name: "invalid", toml: invalidTOML, exp: `invalid configuration: 7 errors: + {name: "invalid", toml: invalidTOML, exp: `invalid configuration: 8 errors: - P2P.V2.Enabled: invalid value (false): P2P required for OCR or OCR2. Please enable P2P or disable OCR/OCR2. - Database.Lock.LeaseRefreshInterval: invalid value (6s): must be less than or equal to half of LeaseDuration (10s) - WebServer: 8 errors: @@ -1357,7 +1357,8 @@ func TestConfig_Validate(t *testing.T) { - 0.ChainID: missing: required for all chains - 1: 2 errors: - ChainID: missing: required for all chains - - Nodes: missing: must have at least one node`}, + - Nodes: missing: must have at least one node + - Aptos.0.Enabled: invalid value (1): expected *bool`}, } { t.Run(tt.name, func(t *testing.T) { var c Config diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go index 50a4478d7c..6c11a1fe3a 100644 --- a/core/services/chainlink/mocks/general_config.go +++ b/core/services/chainlink/mocks/general_config.go @@ -46,6 +46,24 @@ func (_m *GeneralConfig) AppID() uuid.UUID { return r0 } +// AptosEnabled provides a mock function with given fields: +func (_m *GeneralConfig) AptosEnabled() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for AptosEnabled") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // AuditLogger provides a mock function with given fields: func (_m *GeneralConfig) AuditLogger() config.AuditLogger { ret := _m.Called() diff --git a/core/services/chainlink/testdata/config-invalid.toml b/core/services/chainlink/testdata/config-invalid.toml index 30fbfff472..ca22e68c22 100644 --- a/core/services/chainlink/testdata/config-invalid.toml +++ b/core/services/chainlink/testdata/config-invalid.toml @@ -159,6 +159,9 @@ APIKey = 'key' [[Starknet]] +[[Aptos]] +Enabled = 1 + [OCR2] Enabled = true diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 764c517e8e..6defdeeb61 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -997,6 +997,18 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { require.NoError(t, err) }) + t.Run(("test Aptos key validation"), func(t *testing.T) { + ctx := testutils.Context(t) + jb.OCR2OracleSpec.Relay = relay.NetworkAptos + err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") + require.EqualError(t, err, "no Aptos key matching: \"bad key\"") + + aptosKey, err := keyStore.Aptos().Create(ctx) + require.NoError(t, err) + err = job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, aptosKey.ID()) + require.NoError(t, err) + }) + t.Run("test Mercury ETH key validation", func(t *testing.T) { ctx := testutils.Context(t) jb.OCR2OracleSpec.PluginType = types.Mercury diff --git a/core/services/job/orm.go b/core/services/job/orm.go index de53198546..3f2d5c237d 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -602,8 +602,10 @@ func validateKeyStoreMatchForRelay(ctx context.Context, network string, keyStore return errors.Errorf("no Starknet key matching: %q", key) } case relay.NetworkAptos: - // TODO BCI-2953 - return nil + _, err := keyStore.Aptos().Get(key) + if err != nil { + return errors.Errorf("no Aptos key matching: %q", key) + } } return nil } diff --git a/core/services/keystore/aptos.go b/core/services/keystore/aptos.go new file mode 100644 index 0000000000..4a40033ae0 --- /dev/null +++ b/core/services/keystore/aptos.go @@ -0,0 +1,182 @@ +package keystore + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" +) + +//go:generate mockery --quiet --name Aptos --output ./mocks/ --case=underscore --filename aptos.go + +type Aptos interface { + Get(id string) (aptoskey.Key, error) + GetAll() ([]aptoskey.Key, error) + Create(ctx context.Context) (aptoskey.Key, error) + Add(ctx context.Context, key aptoskey.Key) error + Delete(ctx context.Context, id string) (aptoskey.Key, error) + Import(ctx context.Context, keyJSON []byte, password string) (aptoskey.Key, error) + Export(id string, password string) ([]byte, error) + EnsureKey(ctx context.Context) error + Sign(ctx context.Context, id string, msg []byte) (signature []byte, err error) +} + +type aptos struct { + *keyManager +} + +var _ Aptos = &aptos{} + +func newAptosKeyStore(km *keyManager) *aptos { + return &aptos{ + km, + } +} + +func (ks *aptos) Get(id string) (aptoskey.Key, error) { + ks.lock.RLock() + defer ks.lock.RUnlock() + if ks.isLocked() { + return aptoskey.Key{}, ErrLocked + } + return ks.getByID(id) +} + +func (ks *aptos) GetAll() (keys []aptoskey.Key, _ error) { + ks.lock.RLock() + defer ks.lock.RUnlock() + if ks.isLocked() { + return nil, ErrLocked + } + for _, key := range ks.keyRing.Aptos { + keys = append(keys, key) + } + return keys, nil +} + +func (ks *aptos) Create(ctx context.Context) (aptoskey.Key, error) { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return aptoskey.Key{}, ErrLocked + } + key, err := aptoskey.New() + if err != nil { + return aptoskey.Key{}, err + } + return key, ks.safeAddKey(ctx, key) +} + +func (ks *aptos) Add(ctx context.Context, key aptoskey.Key) error { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return ErrLocked + } + if _, found := ks.keyRing.Aptos[key.ID()]; found { + return fmt.Errorf("key with ID %s already exists", key.ID()) + } + return ks.safeAddKey(ctx, key) +} + +func (ks *aptos) Delete(ctx context.Context, id string) (aptoskey.Key, error) { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return aptoskey.Key{}, ErrLocked + } + key, err := ks.getByID(id) + if err != nil { + return aptoskey.Key{}, err + } + err = ks.safeRemoveKey(ctx, key) + return key, err +} + +func (ks *aptos) Import(ctx context.Context, keyJSON []byte, password string) (aptoskey.Key, error) { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return aptoskey.Key{}, ErrLocked + } + key, err := aptoskey.FromEncryptedJSON(keyJSON, password) + if err != nil { + return aptoskey.Key{}, errors.Wrap(err, "AptosKeyStore#ImportKey failed to decrypt key") + } + if _, found := ks.keyRing.Aptos[key.ID()]; found { + return aptoskey.Key{}, fmt.Errorf("key with ID %s already exists", key.ID()) + } + return key, ks.keyManager.safeAddKey(ctx, key) +} + +func (ks *aptos) Export(id string, password string) ([]byte, error) { + ks.lock.RLock() + defer ks.lock.RUnlock() + if ks.isLocked() { + return nil, ErrLocked + } + key, err := ks.getByID(id) + if err != nil { + return nil, err + } + return key.ToEncryptedJSON(password, ks.scryptParams) +} + +func (ks *aptos) EnsureKey(ctx context.Context) error { + ks.lock.Lock() + defer ks.lock.Unlock() + if ks.isLocked() { + return ErrLocked + } + if len(ks.keyRing.Aptos) > 0 { + return nil + } + + key, err := aptoskey.New() + if err != nil { + return err + } + + ks.logger.Infof("Created Aptos key with ID %s", key.ID()) + + return ks.safeAddKey(ctx, key) +} + +func (ks *aptos) Sign(_ context.Context, id string, msg []byte) (signature []byte, err error) { + k, err := ks.Get(id) + if err != nil { + return nil, err + } + return k.Sign(msg) +} + +func (ks *aptos) getByID(id string) (aptoskey.Key, error) { + key, found := ks.keyRing.Aptos[id] + if !found { + return aptoskey.Key{}, KeyNotFoundError{ID: id, KeyType: "Aptos"} + } + return key, nil +} + +// AptosSigner implements [github.com/smartcontractkit/chainlink-common/pkg/loop.Keystore] interface and the requirements +// Handles signing for Apots Messages +type AptosLooppSigner struct { + Aptos +} + +var _ loop.Keystore = &AptosLooppSigner{} + +// Returns a list of Aptos Public Keys +func (s *AptosLooppSigner) Accounts(ctx context.Context) (accounts []string, err error) { + ks, err := s.GetAll() + if err != nil { + return nil, err + } + for _, k := range ks { + accounts = append(accounts, k.ID()) + } + return +} diff --git a/core/services/keystore/aptos_test.go b/core/services/keystore/aptos_test.go new file mode 100644 index 0000000000..9a2764adff --- /dev/null +++ b/core/services/keystore/aptos_test.go @@ -0,0 +1,138 @@ +package keystore_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "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/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" +) + +func Test_AptosKeyStore_E2E(t *testing.T) { + db := pgtest.NewSqlxDB(t) + + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) + ks := keyStore.Aptos() + reset := func() { + ctx := context.Background() // Executed on cleanup + require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) + keyStore.ResetXXXTestOnly() + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) + } + + t.Run("initializes with an empty state", func(t *testing.T) { + defer reset() + keys, err := ks.GetAll() + require.NoError(t, err) + require.Equal(t, 0, len(keys)) + }) + + t.Run("errors when getting non-existent ID", func(t *testing.T) { + defer reset() + _, err := ks.Get("non-existent-id") + require.Error(t, err) + }) + + t.Run("creates a key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) + require.NoError(t, err) + retrievedKey, err := ks.Get(key.ID()) + require.NoError(t, err) + require.Equal(t, key, retrievedKey) + }) + + t.Run("imports and exports a key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) + require.NoError(t, err) + exportJSON, err := ks.Export(key.ID(), cltest.Password) + require.NoError(t, err) + _, err = ks.Export("non-existent", cltest.Password) + assert.Error(t, err) + _, err = ks.Delete(ctx, key.ID()) + require.NoError(t, err) + _, err = ks.Get(key.ID()) + require.Error(t, err) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) + require.NoError(t, err) + _, err = ks.Import(ctx, exportJSON, cltest.Password) + assert.Error(t, err) + _, err = ks.Import(ctx, []byte(""), cltest.Password) + assert.Error(t, err) + require.Equal(t, key.ID(), importedKey.ID()) + retrievedKey, err := ks.Get(key.ID()) + require.NoError(t, err) + require.Equal(t, importedKey, retrievedKey) + }) + + t.Run("adds an externally created key / deletes a key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + newKey, err := aptoskey.New() + require.NoError(t, err) + err = ks.Add(ctx, newKey) + require.NoError(t, err) + err = ks.Add(ctx, newKey) + assert.Error(t, err) + keys, err := ks.GetAll() + require.NoError(t, err) + require.Equal(t, 1, len(keys)) + _, err = ks.Delete(ctx, newKey.ID()) + require.NoError(t, err) + _, err = ks.Delete(ctx, newKey.ID()) + assert.Error(t, err) + keys, err = ks.GetAll() + require.NoError(t, err) + require.Equal(t, 0, len(keys)) + _, err = ks.Get(newKey.ID()) + require.Error(t, err) + }) + + t.Run("ensures key", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + err := ks.EnsureKey(ctx) + assert.NoError(t, err) + + err = ks.EnsureKey(ctx) + assert.NoError(t, err) + + keys, err := ks.GetAll() + require.NoError(t, err) + require.Equal(t, 1, len(keys)) + }) + + t.Run("sign tx", func(t *testing.T) { + defer reset() + ctx := testutils.Context(t) + newKey, err := aptoskey.New() + require.NoError(t, err) + require.NoError(t, ks.Add(ctx, newKey)) + + // sign unknown ID + _, err = ks.Sign(testutils.Context(t), "not-real", nil) + assert.Error(t, err) + + // sign known key + payload := []byte{1} + sig, err := ks.Sign(testutils.Context(t), newKey.ID(), payload) + require.NoError(t, err) + + directSig, err := newKey.Sign(payload) + require.NoError(t, err) + + // signatures should match using keystore sign or key sign + assert.Equal(t, directSig, sig) + }) +} diff --git a/core/services/keystore/chaintype/chaintype.go b/core/services/keystore/chaintype/chaintype.go index cd149e390e..8a12322ebf 100644 --- a/core/services/keystore/chaintype/chaintype.go +++ b/core/services/keystore/chaintype/chaintype.go @@ -19,6 +19,8 @@ const ( Solana ChainType = "solana" // StarkNet for the StarkNet chain StarkNet ChainType = "starknet" + // Aptos for the Aptos chain + Aptos ChainType = "aptos" ) type ChainTypes []ChainType @@ -35,7 +37,7 @@ func (c ChainTypes) String() (out string) { } // SupportedChainTypes contain all chains that are supported -var SupportedChainTypes = ChainTypes{EVM, Cosmos, Solana, StarkNet} +var SupportedChainTypes = ChainTypes{EVM, Cosmos, Solana, StarkNet, Aptos} // ErrInvalidChainType is an error to indicate an unsupported chain type var ErrInvalidChainType error diff --git a/core/services/keystore/keys/aptoskey/account.go b/core/services/keystore/keys/aptoskey/account.go new file mode 100644 index 0000000000..89f62d3301 --- /dev/null +++ b/core/services/keystore/keys/aptoskey/account.go @@ -0,0 +1,72 @@ +package aptoskey + +import ( + "encoding/hex" + "errors" + "fmt" + "strings" +) + +// AccountAddress is a 32 byte address on the Aptos blockchain +// It can represent an Object, an Account, and much more. +// +// AccountAddress is copied from the aptos sdk because: +// 1. There are still breaking changes in sdk and we don't want the dependency. +// 2. AccountAddress is just a wrapper and can be easily extracted out. +// +// https://github.com/aptos-labs/aptos-go-sdk/blob/main/internal/types/account.go +type AccountAddress [32]byte + +// IsSpecial Returns whether the address is a "special" address. Addresses are considered +// special if the first 63 characters of the hex string are zero. In other words, +// an address is special if the first 31 bytes are zero and the last byte is +// smaller than `0b10000` (16). In other words, special is defined as an address +// that matches the following regex: `^0x0{63}[0-9a-f]$`. In short form this means +// the addresses in the range from `0x0` to `0xf` (inclusive) are special. +// For more details see the v1 address standard defined as part of AIP-40: +// https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-40.md +func (aa *AccountAddress) IsSpecial() bool { + for _, b := range aa[:31] { + if b != 0 { + return false + } + } + return aa[31] < 0x10 +} + +// String Returns the canonical string representation of the AccountAddress +func (aa *AccountAddress) String() string { + if aa.IsSpecial() { + return fmt.Sprintf("0x%x", aa[31]) + } + return BytesToHex(aa[:]) +} + +// ParseStringRelaxed parses a string into an AccountAddress +func (aa *AccountAddress) ParseStringRelaxed(x string) error { + x = strings.TrimPrefix(x, "0x") + if len(x) < 1 { + return ErrAddressTooShort + } + if len(x) > 64 { + return ErrAddressTooLong + } + if len(x)%2 != 0 { + x = "0" + x + } + bytes, err := hex.DecodeString(x) + if err != nil { + return err + } + // zero-prefix/right-align what bytes we got + copy((*aa)[32-len(bytes):], bytes) + + return nil +} + +var ErrAddressTooShort = errors.New("AccountAddress too short") +var ErrAddressTooLong = errors.New("AccountAddress too long") + +func BytesToHex(bytes []byte) string { + return "0x" + hex.EncodeToString(bytes) +} diff --git a/core/services/keystore/keys/aptoskey/account_test.go b/core/services/keystore/keys/aptoskey/account_test.go new file mode 100644 index 0000000000..b9ed4ea04a --- /dev/null +++ b/core/services/keystore/keys/aptoskey/account_test.go @@ -0,0 +1,141 @@ +package aptoskey + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// Tests extracted from +// https://github.com/aptos-labs/aptos-go-sdk/blob/5ee5ac308e5881b508c0a5124f5e0b8df27a4d40/internal/types/account_test.go + +func TestStringOutput(t *testing.T) { + inputs := [][]byte{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F}, + {0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + {0x02, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + {0x00, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + {0x00, 0x04, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + {0x00, 0x00, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + } + expected := []string{ + "0x0", + "0x1", + "0xf", + "0x1234123412341234123412341234123412341234123412340123456789abcdef", + "0x0234123412341234123412341234123412341234123412340123456789abcdef", + "0x0034123412341234123412341234123412341234123412340123456789abcdef", + "0x0004123412341234123412341234123412341234123412340123456789abcdef", + "0x0000123412341234123412341234123412341234123412340123456789abcdef", + } + + for i := 0; i < len(inputs); i++ { + addr := AccountAddress(inputs[i]) + assert.Equal(t, expected[i], addr.String()) + } +} + +func TestAccountAddress_ParseStringRelaxed_Error(t *testing.T) { + var owner AccountAddress + err := owner.ParseStringRelaxed("0x") + assert.Error(t, err) + err = owner.ParseStringRelaxed("0xF1234567812345678123456781234567812345678123456781234567812345678") + assert.Error(t, err) + err = owner.ParseStringRelaxed("NotHex") + assert.Error(t, err) +} + +func TestAccountAddress_String(t *testing.T) { + testCases := []struct { + name string + address AccountAddress + expected string + }{ + { + name: "Special address", + address: AccountAddress{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + expected: "0x1", + }, + { + name: "Non-special address", + address: AccountAddress{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, + expected: "0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expected, tc.address.String()) + }) + } +} + +func TestAccountAddress_IsSpecial(t *testing.T) { + testCases := []struct { + name string + address AccountAddress + expected bool + }{ + { + name: "Special address", + address: AccountAddress{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + expected: true, + }, + { + name: "Non-special address", + address: AccountAddress{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, + expected: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expected, tc.address.IsSpecial()) + }) + } +} + +func TestBytesToHex(t *testing.T) { + testCases := []struct { + name string + bytes []byte + expected string + }{ + { + name: "Empty bytes", + bytes: []byte{}, + expected: "0x", + }, + { + name: "Non-empty bytes", + bytes: []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, + expected: "0x123456789abcdef0", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expected, BytesToHex(tc.bytes)) + }) + } +} + +func TestAccountSpecialString(t *testing.T) { + var aa AccountAddress + aa[31] = 3 + aas := aa.String() + if aas != "0x3" { + t.Errorf("wanted 0x3 got %s", aas) + } + + var aa2 AccountAddress + err := aa2.ParseStringRelaxed("0x3") + if err != nil { + t.Errorf("unexpected err %s", err) + } + if aa2 != aa { + t.Errorf("aa2 != aa") + } +} diff --git a/core/services/keystore/keys/aptoskey/export.go b/core/services/keystore/keys/aptoskey/export.go new file mode 100644 index 0000000000..23553ef9dc --- /dev/null +++ b/core/services/keystore/keys/aptoskey/export.go @@ -0,0 +1,48 @@ +package aptoskey + +import ( + "encoding/hex" + + "github.com/ethereum/go-ethereum/accounts/keystore" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys" + "github.com/smartcontractkit/chainlink/v2/core/utils" +) + +const keyTypeIdentifier = "Aptos" + +// FromEncryptedJSON gets key from json and password +func FromEncryptedJSON(keyJSON []byte, password string) (Key, error) { + return keys.FromEncryptedJSON( + keyTypeIdentifier, + keyJSON, + password, + adulteratedPassword, + func(_ keys.EncryptedKeyExport, rawPrivKey []byte) (Key, error) { + return Raw(rawPrivKey).Key(), nil + }, + ) +} + +// ToEncryptedJSON returns encrypted JSON representing key +func (key Key) ToEncryptedJSON(password string, scryptParams utils.ScryptParams) (export []byte, err error) { + return keys.ToEncryptedJSON( + keyTypeIdentifier, + key.Raw(), + key, + password, + scryptParams, + adulteratedPassword, + func(id string, key Key, cryptoJSON keystore.CryptoJSON) keys.EncryptedKeyExport { + return keys.EncryptedKeyExport{ + KeyType: id, + PublicKey: hex.EncodeToString(key.pubKey), + Crypto: cryptoJSON, + } + }, + ) +} + +func adulteratedPassword(password string) string { + return "aptoskey" + password +} diff --git a/core/services/keystore/keys/aptoskey/export_test.go b/core/services/keystore/keys/aptoskey/export_test.go new file mode 100644 index 0000000000..a920e43229 --- /dev/null +++ b/core/services/keystore/keys/aptoskey/export_test.go @@ -0,0 +1,19 @@ +package aptoskey + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys" +) + +func TestAptosKeys_ExportImport(t *testing.T) { + keys.RunKeyExportImportTestcase(t, createKey, decryptKey) +} + +func createKey() (keys.KeyType, error) { + return New() +} + +func decryptKey(keyJSON []byte, password string) (keys.KeyType, error) { + return FromEncryptedJSON(keyJSON, password) +} diff --git a/core/services/keystore/keys/aptoskey/key.go b/core/services/keystore/keys/aptoskey/key.go new file mode 100644 index 0000000000..ec9b27a359 --- /dev/null +++ b/core/services/keystore/keys/aptoskey/key.go @@ -0,0 +1,103 @@ +package aptoskey + +import ( + "crypto" + "crypto/ed25519" + crypto_rand "crypto/rand" + "fmt" + "io" + + "github.com/mr-tron/base58" +) + +// Raw represents the Aptos private key +type Raw []byte + +// Key gets the Key +func (raw Raw) Key() Key { + privKey := ed25519.NewKeyFromSeed(raw) + pubKey := privKey.Public().(ed25519.PublicKey) + return Key{ + privkey: privKey, + pubKey: pubKey, + } +} + +// String returns description +func (raw Raw) String() string { + return "" +} + +// GoString wraps String() +func (raw Raw) GoString() string { + return raw.String() +} + +var _ fmt.GoStringer = &Key{} + +// Key represents Aptos key +type Key struct { + privkey ed25519.PrivateKey + pubKey ed25519.PublicKey +} + +// New creates new Key +func New() (Key, error) { + return newFrom(crypto_rand.Reader) +} + +// MustNewInsecure return Key if no error +func MustNewInsecure(reader io.Reader) Key { + key, err := newFrom(reader) + if err != nil { + panic(err) + } + return key +} + +// newFrom creates new Key from a provided random reader +func newFrom(reader io.Reader) (Key, error) { + pub, priv, err := ed25519.GenerateKey(reader) + if err != nil { + return Key{}, err + } + return Key{ + privkey: priv, + pubKey: pub, + }, nil +} + +// ID gets Key ID +func (key Key) ID() string { + return key.PublicKeyStr() +} + +// GetPublic get Key's public key +func (key Key) GetPublic() ed25519.PublicKey { + return key.pubKey +} + +// PublicKeyStr return base58 encoded public key +func (key Key) PublicKeyStr() string { + return base58.Encode(key.pubKey) +} + +// Raw returns the seed from private key +func (key Key) Raw() Raw { + return key.privkey.Seed() +} + +// String is the print-friendly format of the Key +func (key Key) String() string { + return fmt.Sprintf("AptosKey{PrivateKey: , Public Key: %s}", key.PublicKeyStr()) +} + +// GoString wraps String() +func (key Key) GoString() string { + return key.String() +} + +// Sign is used to sign a message +func (key Key) Sign(msg []byte) ([]byte, error) { + return key.privkey.Sign(crypto_rand.Reader, msg, crypto.Hash(0)) // no specific hash function used +} diff --git a/core/services/keystore/keys/ocr2key/aptos_keyring.go b/core/services/keystore/keys/ocr2key/aptos_keyring.go new file mode 100644 index 0000000000..51e6c3a9c8 --- /dev/null +++ b/core/services/keystore/keys/ocr2key/aptos_keyring.go @@ -0,0 +1,118 @@ +package ocr2key + +import ( + "crypto/ed25519" + "encoding/binary" + "io" + + "github.com/hdevalence/ed25519consensus" + "github.com/pkg/errors" + "golang.org/x/crypto/blake2s" + + "github.com/smartcontractkit/chainlink/v2/core/utils" + + "github.com/smartcontractkit/libocr/offchainreporting2/types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +var _ ocrtypes.OnchainKeyring = &aptosKeyring{} + +type aptosKeyring struct { + privKey ed25519.PrivateKey + pubKey ed25519.PublicKey +} + +func newAptosKeyring(material io.Reader) (*aptosKeyring, error) { + pubKey, privKey, err := ed25519.GenerateKey(material) + if err != nil { + return nil, err + } + return &aptosKeyring{pubKey: pubKey, privKey: privKey}, nil +} + +func (akr *aptosKeyring) PublicKey() ocrtypes.OnchainPublicKey { + return []byte(akr.pubKey) +} + +func (akr *aptosKeyring) reportToSigData(reportCtx ocrtypes.ReportContext, report ocrtypes.Report) ([]byte, error) { + rawReportContext := evmutil.RawReportContext(reportCtx) + h, err := blake2s.New256(nil) + if err != nil { + return nil, err + } + reportLen := make([]byte, 4) + binary.BigEndian.PutUint32(reportLen[0:], uint32(len(report))) + h.Write(reportLen[:]) + h.Write(report) + h.Write(rawReportContext[0][:]) + h.Write(rawReportContext[1][:]) + h.Write(rawReportContext[2][:]) + return h.Sum(nil), nil +} + +func (akr *aptosKeyring) Sign(reportCtx ocrtypes.ReportContext, report ocrtypes.Report) ([]byte, error) { + sigData, err := akr.reportToSigData(reportCtx, report) + if err != nil { + return nil, err + } + return akr.signBlob(sigData) +} + +func (akr *aptosKeyring) Sign3(digest types.ConfigDigest, seqNr uint64, r ocrtypes.Report) (signature []byte, err error) { + return nil, errors.New("not implemented") +} + +func (akr *aptosKeyring) signBlob(b []byte) ([]byte, error) { + signedMsg := ed25519.Sign(akr.privKey, b) + // match on-chain parsing (first 32 bytes are for pubkey, remaining are for signature) + return utils.ConcatBytes(akr.PublicKey(), signedMsg), nil +} + +func (akr *aptosKeyring) Verify(publicKey ocrtypes.OnchainPublicKey, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signature []byte) bool { + hash, err := akr.reportToSigData(reportCtx, report) + if err != nil { + return false + } + return akr.verifyBlob(publicKey, hash, signature) +} + +func (akr *aptosKeyring) Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { + return false +} + +func (akr *aptosKeyring) verifyBlob(pubkey ocrtypes.OnchainPublicKey, b, sig []byte) bool { + // Ed25519 signatures are always 64 bytes and the + // public key (always prefixed, see Sign above) is always, + // 32 bytes, so we always require the max signature length. + if len(sig) != akr.MaxSignatureLength() { + return false + } + if len(pubkey) != ed25519.PublicKeySize { + return false + } + return ed25519consensus.Verify(ed25519.PublicKey(pubkey), b, sig[32:]) +} + +func (akr *aptosKeyring) MaxSignatureLength() int { + // Reference: https://pkg.go.dev/crypto/ed25519 + return ed25519.PublicKeySize + ed25519.SignatureSize // 32 + 64 +} + +func (akr *aptosKeyring) Marshal() ([]byte, error) { + return akr.privKey.Seed(), nil +} + +func (akr *aptosKeyring) Unmarshal(in []byte) error { + if len(in) != ed25519.SeedSize { + return errors.Errorf("unexpected seed size, got %d want %d", len(in), ed25519.SeedSize) + } + privKey := ed25519.NewKeyFromSeed(in) + akr.privKey = privKey + pubKey, ok := privKey.Public().(ed25519.PublicKey) + if !ok { + return errors.New("failed to cast public key to ed25519.PublicKey") + } + akr.pubKey = pubKey + return nil +} diff --git a/core/services/keystore/keys/ocr2key/aptos_keyring_test.go b/core/services/keystore/keys/ocr2key/aptos_keyring_test.go new file mode 100644 index 0000000000..2b88d61065 --- /dev/null +++ b/core/services/keystore/keys/ocr2key/aptos_keyring_test.go @@ -0,0 +1,58 @@ +package ocr2key + +import ( + "bytes" + cryptorand "crypto/rand" + "testing" + + "github.com/stretchr/testify/assert" + + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/stretchr/testify/require" +) + +func TestAptosKeyRing_Sign_Verify(t *testing.T) { + kr1, err := newAptosKeyring(cryptorand.Reader) + require.NoError(t, err) + kr2, err := newAptosKeyring(cryptorand.Reader) + require.NoError(t, err) + ctx := ocrtypes.ReportContext{} + + t.Run("can verify", func(t *testing.T) { + report := ocrtypes.Report{} + sig, err := kr1.Sign(ctx, report) + require.NoError(t, err) + t.Log(len(sig)) + result := kr2.Verify(kr1.PublicKey(), ctx, report, sig) + require.True(t, result) + }) + + t.Run("invalid sig", func(t *testing.T) { + report := ocrtypes.Report{} + result := kr2.Verify(kr1.PublicKey(), ctx, report, []byte{0x01}) + require.False(t, result) + }) + + t.Run("invalid pubkey", func(t *testing.T) { + report := ocrtypes.Report{} + sig, err := kr1.Sign(ctx, report) + require.NoError(t, err) + result := kr2.Verify([]byte{0x01}, ctx, report, sig) + require.False(t, result) + }) +} + +func TestAptosKeyRing_Marshalling(t *testing.T) { + kr1, err := newAptosKeyring(cryptorand.Reader) + require.NoError(t, err) + m, err := kr1.Marshal() + require.NoError(t, err) + kr2 := aptosKeyring{} + err = kr2.Unmarshal(m) + require.NoError(t, err) + assert.True(t, bytes.Equal(kr1.pubKey, kr2.pubKey)) + assert.True(t, bytes.Equal(kr1.privKey, kr2.privKey)) + + // Invalid seed size should error + require.Error(t, kr2.Unmarshal([]byte{0x01})) +} diff --git a/core/services/keystore/keys/ocr2key/cosmos_keyring.go b/core/services/keystore/keys/ocr2key/cosmos_keyring.go index 5f1b9b9819..1d1a477f2d 100644 --- a/core/services/keystore/keys/ocr2key/cosmos_keyring.go +++ b/core/services/keystore/keys/ocr2key/cosmos_keyring.go @@ -7,12 +7,13 @@ import ( "github.com/hdevalence/ed25519consensus" "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/offchainreporting2/types" - "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "golang.org/x/crypto/blake2s" "github.com/smartcontractkit/chainlink/v2/core/utils" + + "github.com/smartcontractkit/libocr/offchainreporting2/types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ) var _ ocrtypes.OnchainKeyring = &cosmosKeyring{} @@ -108,6 +109,10 @@ func (ckr *cosmosKeyring) Unmarshal(in []byte) error { } privKey := ed25519.NewKeyFromSeed(in) ckr.privKey = privKey - ckr.pubKey = privKey.Public().(ed25519.PublicKey) + pubKey, ok := privKey.Public().(ed25519.PublicKey) + if !ok { + return errors.New("failed to cast public key to ed25519.PublicKey") + } + ckr.pubKey = pubKey return nil } diff --git a/core/services/keystore/keys/ocr2key/export.go b/core/services/keystore/keys/ocr2key/export.go index 5487e31046..8fa5ffedfe 100644 --- a/core/services/keystore/keys/ocr2key/export.go +++ b/core/services/keystore/keys/ocr2key/export.go @@ -46,6 +46,8 @@ func FromEncryptedJSON(keyJSON []byte, password string) (KeyBundle, error) { kb = newKeyBundle(new(solanaKeyring)) case chaintype.StarkNet: kb = newKeyBundle(new(starkkey.OCR2Key)) + case chaintype.Aptos: + kb = newKeyBundle(new(aptosKeyring)) default: return nil, chaintype.NewErrInvalidChainType(export.ChainType) } diff --git a/core/services/keystore/keys/ocr2key/export_test.go b/core/services/keystore/keys/ocr2key/export_test.go index dfa820eb2b..b0ffa2db00 100644 --- a/core/services/keystore/keys/ocr2key/export_test.go +++ b/core/services/keystore/keys/ocr2key/export_test.go @@ -18,6 +18,7 @@ func TestExport(t *testing.T) { {chain: chaintype.Cosmos}, {chain: chaintype.Solana}, {chain: chaintype.StarkNet}, + {chain: chaintype.Aptos}, } for _, tc := range tt { tc := tc diff --git a/core/services/keystore/keys/ocr2key/key_bundle.go b/core/services/keystore/keys/ocr2key/key_bundle.go index 2c3a4bebeb..2c25a159fe 100644 --- a/core/services/keystore/keys/ocr2key/key_bundle.go +++ b/core/services/keystore/keys/ocr2key/key_bundle.go @@ -43,6 +43,7 @@ var _ KeyBundle = &keyBundle[*evmKeyring]{} var _ KeyBundle = &keyBundle[*cosmosKeyring]{} var _ KeyBundle = &keyBundle[*solanaKeyring]{} var _ KeyBundle = &keyBundle[*starkkey.OCR2Key]{} +var _ KeyBundle = &keyBundle[*aptosKeyring]{} var curve = secp256k1.S256() @@ -57,6 +58,8 @@ func New(chainType chaintype.ChainType) (KeyBundle, error) { return newKeyBundleRand(chaintype.Solana, newSolanaKeyring) case chaintype.StarkNet: return newKeyBundleRand(chaintype.StarkNet, starkkey.NewOCR2Key) + case chaintype.Aptos: + return newKeyBundleRand(chaintype.Aptos, newAptosKeyring) } return nil, chaintype.NewErrInvalidChainType(chainType) } @@ -72,6 +75,8 @@ func MustNewInsecure(reader io.Reader, chainType chaintype.ChainType) KeyBundle return mustNewKeyBundleInsecure(chaintype.Solana, newSolanaKeyring, reader) case chaintype.StarkNet: return mustNewKeyBundleInsecure(chaintype.StarkNet, starkkey.NewOCR2Key, reader) + case chaintype.Aptos: + return mustNewKeyBundleInsecure(chaintype.Aptos, newAptosKeyring, reader) } panic(chaintype.NewErrInvalidChainType(chainType)) } @@ -121,6 +126,8 @@ func (raw Raw) Key() (kb KeyBundle) { kb = newKeyBundle(new(solanaKeyring)) case chaintype.StarkNet: kb = newKeyBundle(new(starkkey.OCR2Key)) + case chaintype.Aptos: + kb = newKeyBundle(new(aptosKeyring)) default: return nil } diff --git a/core/services/keystore/keys/solkey/key.go b/core/services/keystore/keys/solkey/key.go index bcec5e8940..c6cdd62d3b 100644 --- a/core/services/keystore/keys/solkey/key.go +++ b/core/services/keystore/keys/solkey/key.go @@ -11,7 +11,7 @@ import ( "github.com/mr-tron/base58" ) -// Raw represents the ETH private key +// Raw represents the Solana private key type Raw []byte // Key gets the Key diff --git a/core/services/keystore/keystoretest.go b/core/services/keystore/keystoretest.go index 91dc87ffe9..990f06c91a 100644 --- a/core/services/keystore/keystoretest.go +++ b/core/services/keystore/keystoretest.go @@ -73,6 +73,7 @@ func NewInMemory(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr lo p2p: newP2PKeyStore(km), solana: newSolanaKeyStore(km), starknet: newStarkNetKeyStore(km), + aptos: newAptosKeyStore(km), vrf: newVRFKeyStore(km), dkgSign: newDKGSignKeyStore(km), dkgEncrypt: newDKGEncryptKeyStore(km), diff --git a/core/services/keystore/master.go b/core/services/keystore/master.go index bb5b21a96f..da42f5368c 100644 --- a/core/services/keystore/master.go +++ b/core/services/keystore/master.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey" @@ -48,6 +49,7 @@ type Master interface { Solana() Solana Cosmos() Cosmos StarkNet() StarkNet + Aptos() Aptos VRF() VRF Unlock(ctx context.Context, password string) error IsEmpty(ctx context.Context) (bool, error) @@ -63,6 +65,7 @@ type master struct { p2p *p2p solana *solana starknet *starknet + aptos *aptos vrf *vrf dkgSign *dkgSign dkgEncrypt *dkgEncrypt @@ -92,6 +95,7 @@ func newMaster(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr logg p2p: newP2PKeyStore(km), solana: newSolanaKeyStore(km), starknet: newStarkNetKeyStore(km), + aptos: newAptosKeyStore(km), vrf: newVRFKeyStore(km), dkgSign: newDKGSignKeyStore(km), dkgEncrypt: newDKGEncryptKeyStore(km), @@ -138,6 +142,10 @@ func (ks *master) StarkNet() StarkNet { return ks.starknet } +func (ks *master) Aptos() Aptos { + return ks.aptos +} + func (ks *master) VRF() VRF { return ks.vrf } @@ -273,6 +281,8 @@ func GetFieldNameForKey(unknownKey Key) (string, error) { return "Solana", nil case starkkey.Key: return "StarkNet", nil + case aptoskey.Key: + return "Aptos", nil case vrfkey.KeyV2: return "VRF", nil case dkgsignkey.Key: diff --git a/core/services/keystore/mocks/aptos.go b/core/services/keystore/mocks/aptos.go new file mode 100644 index 0000000000..476112149b --- /dev/null +++ b/core/services/keystore/mocks/aptos.go @@ -0,0 +1,268 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + aptoskey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" + + mock "github.com/stretchr/testify/mock" +) + +// Aptos is an autogenerated mock type for the Aptos type +type Aptos struct { + mock.Mock +} + +// Add provides a mock function with given fields: ctx, key +func (_m *Aptos) Add(ctx context.Context, key aptoskey.Key) error { + ret := _m.Called(ctx, key) + + if len(ret) == 0 { + panic("no return value specified for Add") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, aptoskey.Key) error); ok { + r0 = rf(ctx, key) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Create provides a mock function with given fields: ctx +func (_m *Aptos) Create(ctx context.Context) (aptoskey.Key, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 aptoskey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (aptoskey.Key, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) aptoskey.Key); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(aptoskey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Delete provides a mock function with given fields: ctx, id +func (_m *Aptos) Delete(ctx context.Context, id string) (aptoskey.Key, error) { + ret := _m.Called(ctx, id) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 aptoskey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (aptoskey.Key, error)); ok { + return rf(ctx, id) + } + if rf, ok := ret.Get(0).(func(context.Context, string) aptoskey.Key); ok { + r0 = rf(ctx, id) + } else { + r0 = ret.Get(0).(aptoskey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EnsureKey provides a mock function with given fields: ctx +func (_m *Aptos) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for EnsureKey") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Export provides a mock function with given fields: id, password +func (_m *Aptos) Export(id string, password string) ([]byte, error) { + ret := _m.Called(id, password) + + if len(ret) == 0 { + panic("no return value specified for Export") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(string, string) ([]byte, error)); ok { + return rf(id, password) + } + if rf, ok := ret.Get(0).(func(string, string) []byte); ok { + r0 = rf(id, password) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(id, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Get provides a mock function with given fields: id +func (_m *Aptos) Get(id string) (aptoskey.Key, error) { + ret := _m.Called(id) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 aptoskey.Key + var r1 error + if rf, ok := ret.Get(0).(func(string) (aptoskey.Key, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(string) aptoskey.Key); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(aptoskey.Key) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetAll provides a mock function with given fields: +func (_m *Aptos) GetAll() ([]aptoskey.Key, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetAll") + } + + var r0 []aptoskey.Key + var r1 error + if rf, ok := ret.Get(0).(func() ([]aptoskey.Key, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []aptoskey.Key); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]aptoskey.Key) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *Aptos) Import(ctx context.Context, keyJSON []byte, password string) (aptoskey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) + + if len(ret) == 0 { + panic("no return value specified for Import") + } + + var r0 aptoskey.Key + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (aptoskey.Key, error)); ok { + return rf(ctx, keyJSON, password) + } + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) aptoskey.Key); ok { + r0 = rf(ctx, keyJSON, password) + } else { + r0 = ret.Get(0).(aptoskey.Key) + } + + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Sign provides a mock function with given fields: ctx, id, msg +func (_m *Aptos) Sign(ctx context.Context, id string, msg []byte) ([]byte, error) { + ret := _m.Called(ctx, id, msg) + + if len(ret) == 0 { + panic("no return value specified for Sign") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []byte) ([]byte, error)); ok { + return rf(ctx, id, msg) + } + if rf, ok := ret.Get(0).(func(context.Context, string, []byte) []byte); ok { + r0 = rf(ctx, id, msg) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, []byte) error); ok { + r1 = rf(ctx, id, msg) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewAptos creates a new instance of Aptos. 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 NewAptos(t interface { + mock.TestingT + Cleanup(func()) +}) *Aptos { + mock := &Aptos{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/keystore/mocks/master.go b/core/services/keystore/mocks/master.go index 7c9b51c723..0e70614170 100644 --- a/core/services/keystore/mocks/master.go +++ b/core/services/keystore/mocks/master.go @@ -14,6 +14,26 @@ type Master struct { mock.Mock } +// Aptos provides a mock function with given fields: +func (_m *Master) Aptos() keystore.Aptos { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Aptos") + } + + var r0 keystore.Aptos + if rf, ok := ret.Get(0).(func() keystore.Aptos); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(keystore.Aptos) + } + } + + return r0 +} + // CSA provides a mock function with given fields: func (_m *Master) CSA() keystore.CSA { ret := _m.Called() diff --git a/core/services/keystore/models.go b/core/services/keystore/models.go index bb84efdd02..3c4efdf269 100644 --- a/core/services/keystore/models.go +++ b/core/services/keystore/models.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey" @@ -157,6 +158,7 @@ type keyRing struct { Cosmos map[string]cosmoskey.Key Solana map[string]solkey.Key StarkNet map[string]starkkey.Key + Aptos map[string]aptoskey.Key VRF map[string]vrfkey.KeyV2 DKGSign map[string]dkgsignkey.Key DKGEncrypt map[string]dkgencryptkey.Key @@ -173,6 +175,7 @@ func newKeyRing() *keyRing { Cosmos: make(map[string]cosmoskey.Key), Solana: make(map[string]solkey.Key), StarkNet: make(map[string]starkkey.Key), + Aptos: make(map[string]aptoskey.Key), VRF: make(map[string]vrfkey.KeyV2), DKGSign: make(map[string]dkgsignkey.Key), DKGEncrypt: make(map[string]dkgencryptkey.Key), @@ -233,6 +236,9 @@ func (kr *keyRing) raw() (rawKeys rawKeyRing) { for _, starkkey := range kr.StarkNet { rawKeys.StarkNet = append(rawKeys.StarkNet, starkkey.Raw()) } + for _, aptoskey := range kr.Aptos { + rawKeys.Aptos = append(rawKeys.Aptos, aptoskey.Raw()) + } for _, vrfKey := range kr.VRF { rawKeys.VRF = append(rawKeys.VRF, vrfKey.Raw()) } @@ -279,6 +285,10 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { for _, starkkey := range kr.StarkNet { starknetIDs = append(starknetIDs, starkkey.ID()) } + var aptosIDs []string + for _, aptosKey := range kr.Aptos { + aptosIDs = append(aptosIDs, aptosKey.ID()) + } var vrfIDs []string for _, VRFKey := range kr.VRF { vrfIDs = append(vrfIDs, VRFKey.ID()) @@ -315,6 +325,9 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { if len(starknetIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d StarkNet keys", len(starknetIDs)), "keys", starknetIDs) } + if len(aptosIDs) > 0 { + lggr.Infow(fmt.Sprintf("Unlocked %d Aptos keys", len(aptosIDs)), "keys", aptosIDs) + } if len(vrfIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d VRF keys", len(vrfIDs)), "keys", vrfIDs) } @@ -341,6 +354,7 @@ type rawKeyRing struct { Cosmos []cosmoskey.Raw Solana []solkey.Raw StarkNet []starkkey.Raw + Aptos []aptoskey.Raw VRF []vrfkey.Raw DKGSign []dkgsignkey.Raw DKGEncrypt []dkgencryptkey.Raw @@ -382,6 +396,10 @@ func (rawKeys rawKeyRing) keys() (*keyRing, error) { starkKey := rawStarkNetKey.Key() keyRing.StarkNet[starkKey.ID()] = starkKey } + for _, rawAptosKey := range rawKeys.Aptos { + aptosKey := rawAptosKey.Key() + keyRing.Aptos[aptosKey.ID()] = aptosKey + } for _, rawVRFKey := range rawKeys.VRF { vrfKey := rawVRFKey.Key() keyRing.VRF[vrfKey.ID()] = vrfKey diff --git a/core/services/keystore/solana.go b/core/services/keystore/solana.go index e95af37a7f..ba4031b64c 100644 --- a/core/services/keystore/solana.go +++ b/core/services/keystore/solana.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" ) @@ -28,6 +29,8 @@ type SolanaSigner struct { Solana } +var _ loop.Keystore = &SolanaSigner{} + func (s *SolanaSigner) Accounts(ctx context.Context) (accounts []string, err error) { ks, err := s.GetAll() if err != nil { diff --git a/core/web/aptos_keys_controller.go b/core/web/aptos_keys_controller.go new file mode 100644 index 0000000000..5be4b81577 --- /dev/null +++ b/core/web/aptos_keys_controller.go @@ -0,0 +1,12 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func NewAptosKeysController(app chainlink.Application) KeysController { + return NewKeysController[aptoskey.Key, presenters.AptosKeyResource](app.GetKeyStore().Aptos(), app.GetLogger(), app.GetAuditLogger(), + "aptosKey", presenters.NewAptosKeyResource, presenters.NewAptosKeyResources) +} diff --git a/core/web/aptos_keys_controller_test.go b/core/web/aptos_keys_controller_test.go new file mode 100644 index 0000000000..c5de75a510 --- /dev/null +++ b/core/web/aptos_keys_controller_test.go @@ -0,0 +1,109 @@ +package web_test + +import ( + "fmt" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/web" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func TestAptosKeysController_Index_HappyPath(t *testing.T) { + t.Parallel() + + client, keyStore := setupAptosKeysControllerTests(t) + keys, _ := keyStore.Aptos().GetAll() + + response, cleanup := client.Get("/v2/keys/aptos") + t.Cleanup(cleanup) + cltest.AssertServerResponse(t, response, http.StatusOK) + + resources := []presenters.AptosKeyResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, response), &resources) + assert.NoError(t, err) + + require.Len(t, resources, len(keys)) + + assert.Equal(t, keys[0].ID(), resources[0].ID) + assert.Equal(t, keys[0].PublicKeyStr(), resources[0].PubKey) +} + +func TestAptosKeysController_Create_HappyPath(t *testing.T) { + t.Parallel() + + app := cltest.NewApplicationEVMDisabled(t) + require.NoError(t, app.Start(testutils.Context(t))) + client := app.NewHTTPClient(nil) + keyStore := app.GetKeyStore() + + response, cleanup := client.Post("/v2/keys/aptos", nil) + t.Cleanup(cleanup) + cltest.AssertServerResponse(t, response, http.StatusOK) + + keys, _ := keyStore.Aptos().GetAll() + require.Len(t, keys, 1) + + resource := presenters.AptosKeyResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, response), &resource) + assert.NoError(t, err) + + assert.Equal(t, keys[0].ID(), resource.ID) + assert.Equal(t, keys[0].PublicKeyStr(), resource.PubKey) + + _, err = keyStore.Aptos().Get(resource.ID) + require.NoError(t, err) +} + +func TestAptosKeysController_Delete_NonExistentAptosKeyID(t *testing.T) { + t.Parallel() + + client, _ := setupAptosKeysControllerTests(t) + + nonExistentAptosKeyID := "foobar" + response, cleanup := client.Delete("/v2/keys/aptos/" + nonExistentAptosKeyID) + t.Cleanup(cleanup) + assert.Equal(t, http.StatusNotFound, response.StatusCode) +} + +func TestAptosKeysController_Delete_HappyPath(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + + client, keyStore := setupAptosKeysControllerTests(t) + + keys, _ := keyStore.Aptos().GetAll() + initialLength := len(keys) + key, _ := keyStore.Aptos().Create(ctx) + + response, cleanup := client.Delete(fmt.Sprintf("/v2/keys/aptos/%s", key.ID())) + t.Cleanup(cleanup) + assert.Equal(t, http.StatusOK, response.StatusCode) + assert.Error(t, utils.JustError(keyStore.Aptos().Get(key.ID()))) + + keys, _ = keyStore.Aptos().GetAll() + assert.Equal(t, initialLength, len(keys)) +} + +func setupAptosKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { + t.Helper() + ctx := testutils.Context(t) + + app := cltest.NewApplication(t) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + aptosKeyStore := app.GetKeyStore().Aptos() + require.NotNil(t, aptosKeyStore) + require.NoError(t, aptosKeyStore.Add(ctx, cltest.DefaultAptosKey)) + + client := app.NewHTTPClient(nil) + + return client, app.GetKeyStore() +} diff --git a/core/web/auth/auth_test.go b/core/web/auth/auth_test.go index 9896a2e359..632527ac76 100644 --- a/core/web/auth/auth_test.go +++ b/core/web/auth/auth_test.go @@ -274,18 +274,28 @@ var routesRolesMap = [...]routeRules{ {"POST", "/v2/keys/p2p/export/MOCK", false, false, false}, {"GET", "/v2/keys/solana", true, true, true}, {"GET", "/v2/keys/cosmos", true, true, true}, + {"GET", "/v2/keys/starknet", true, true, true}, + {"GET", "/v2/keys/aptos", true, true, true}, {"GET", "/v2/keys/dkgsign", true, true, true}, {"POST", "/v2/keys/solana", false, false, true}, {"POST", "/v2/keys/cosmos", false, false, true}, + {"POST", "/v2/keys/starknet", false, false, true}, + {"POST", "/v2/keys/aptos", false, false, true}, {"POST", "/v2/keys/dkgsign", false, false, true}, {"DELETE", "/v2/keys/solana/MOCK", false, false, false}, {"DELETE", "/v2/keys/cosmos/MOCK", false, false, false}, + {"DELETE", "/v2/keys/starknet/MOCK", false, false, false}, + {"DELETE", "/v2/keys/aptos/MOCK", false, false, false}, {"DELETE", "/v2/keys/dkgsign/MOCK", false, false, false}, {"POST", "/v2/keys/solana/import", false, false, false}, {"POST", "/v2/keys/cosmos/import", false, false, false}, + {"POST", "/v2/keys/starknet/import", false, false, false}, + {"POST", "/v2/keys/aptos/import", false, false, false}, {"POST", "/v2/keys/dkgsign/import", false, false, false}, {"POST", "/v2/keys/solana/export/MOCK", false, false, false}, {"POST", "/v2/keys/cosmos/export/MOCK", false, false, false}, + {"POST", "/v2/keys/starknet/export/MOCK", false, false, false}, + {"POST", "/v2/keys/aptos/export/MOCK", false, false, false}, {"POST", "/v2/keys/dkgsign/export/MOCK", false, false, false}, {"GET", "/v2/keys/vrf", true, true, true}, {"POST", "/v2/keys/vrf", false, false, true}, diff --git a/core/web/presenters/aptos_key.go b/core/web/presenters/aptos_key.go new file mode 100644 index 0000000000..6460c325f9 --- /dev/null +++ b/core/web/presenters/aptos_key.go @@ -0,0 +1,32 @@ +package presenters + +import "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" + +// AptosKeyResource represents a Aptos key JSONAPI resource. +type AptosKeyResource struct { + JAID + PubKey string `json:"publicKey"` +} + +// GetName implements the api2go EntityNamer interface +func (AptosKeyResource) GetName() string { + return "encryptedAptosKeys" +} + +func NewAptosKeyResource(key aptoskey.Key) *AptosKeyResource { + r := &AptosKeyResource{ + JAID: JAID{ID: key.ID()}, + PubKey: key.PublicKeyStr(), + } + + return r +} + +func NewAptosKeyResources(keys []aptoskey.Key) []AptosKeyResource { + rs := []AptosKeyResource{} + for _, key := range keys { + rs = append(rs, *NewAptosKeyResource(key)) + } + + return rs +} diff --git a/core/web/resolver/ocr2_keys.go b/core/web/resolver/ocr2_keys.go index df18410933..d04ebbd0e2 100644 --- a/core/web/resolver/ocr2_keys.go +++ b/core/web/resolver/ocr2_keys.go @@ -25,6 +25,8 @@ const ( OCR2ChainTypeSolana = "SOLANA" // OCR2ChainTypeStarkNet defines OCR2 StarkNet Chain Type OCR2ChainTypeStarkNet = "STARKNET" + // OCRChainTypeAptos defines OCR Aptos Chain Type + OCRChainTypeAptos = "APTOS" ) // ToOCR2ChainType turns a valid string into a OCR2ChainType @@ -38,6 +40,8 @@ func ToOCR2ChainType(s string) (OCR2ChainType, error) { return OCR2ChainTypeSolana, nil case string(chaintype.StarkNet): return OCR2ChainTypeStarkNet, nil + case string(chaintype.Aptos): + return OCRChainTypeAptos, nil default: return "", errors.New("unknown ocr2 chain type") } @@ -54,6 +58,8 @@ func FromOCR2ChainType(ct OCR2ChainType) string { return string(chaintype.Solana) case OCR2ChainTypeStarkNet: return string(chaintype.StarkNet) + case OCRChainTypeAptos: + return string(chaintype.Aptos) default: return strings.ToLower(string(ct)) } diff --git a/core/web/resolver/ocr2_keys_test.go b/core/web/resolver/ocr2_keys_test.go index 2269149bc3..033d22799b 100644 --- a/core/web/resolver/ocr2_keys_test.go +++ b/core/web/resolver/ocr2_keys_test.go @@ -41,6 +41,7 @@ func TestResolver_GetOCR2KeyBundles(t *testing.T) { ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "cosmos"), ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "solana"), ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "starknet"), + ocr2key.MustNewInsecure(keystest.NewRandReaderFromSeed(1), "aptos"), } expectedBundles := []map[string]interface{}{} for _, k := range fakeKeys { diff --git a/core/web/router.go b/core/web/router.go index 5e90cea237..a220df220c 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -350,6 +350,7 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { {"solana", NewSolanaKeysController(app)}, {"cosmos", NewCosmosKeysController(app)}, {"starknet", NewStarkNetKeysController(app)}, + {"aptos", NewAptosKeysController(app)}, {"dkgsign", NewDKGSignKeysController(app)}, {"dkgencrypt", NewDKGEncryptKeysController(app)}, } { diff --git a/core/web/schema/type/ocr2_keys.graphql b/core/web/schema/type/ocr2_keys.graphql index 95da9acf71..c25148c686 100644 --- a/core/web/schema/type/ocr2_keys.graphql +++ b/core/web/schema/type/ocr2_keys.graphql @@ -3,6 +3,7 @@ enum OCR2ChainType { COSMOS SOLANA STARKNET + APTOS } type OCR2KeyBundle { diff --git a/testdata/scripts/help-all/help-all.txtar b/testdata/scripts/help-all/help-all.txtar index e111295abb..93b24580e3 100644 --- a/testdata/scripts/help-all/help-all.txtar +++ b/testdata/scripts/help-all/help-all.txtar @@ -55,6 +55,12 @@ jobs list # List all jobs jobs run # Trigger a job run jobs show # Show a job keys # Commands for managing various types of keys used by the Chainlink node +keys aptos # Remote commands for administering the node's Aptos keys +keys aptos create # Create a Aptos key +keys aptos delete # Delete Aptos key if present +keys aptos export # Export Aptos key to keyfile +keys aptos import # Import Aptos key from keyfile +keys aptos list # List the Aptos keys keys cosmos # Remote commands for administering the node's Cosmos keys keys cosmos create # Create a Cosmos key keys cosmos delete # Delete Cosmos key if present diff --git a/testdata/scripts/keys/aptos/help.txtar b/testdata/scripts/keys/aptos/help.txtar new file mode 100644 index 0000000000..94f0c7db8c --- /dev/null +++ b/testdata/scripts/keys/aptos/help.txtar @@ -0,0 +1,20 @@ +exec chainlink keys aptos --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink keys aptos - Remote commands for administering the node's Aptos keys + +USAGE: + chainlink keys aptos command [command options] [arguments...] + +COMMANDS: + create Create a Aptos key + import Import Aptos key from keyfile + export Export Aptos key to keyfile + delete Delete Aptos key if present + list List the Aptos keys + +OPTIONS: + --help, -h show help + diff --git a/testdata/scripts/keys/help.txtar b/testdata/scripts/keys/help.txtar index a54002e272..5c144017c6 100644 --- a/testdata/scripts/keys/help.txtar +++ b/testdata/scripts/keys/help.txtar @@ -17,6 +17,7 @@ COMMANDS: cosmos Remote commands for administering the node's Cosmos keys solana Remote commands for administering the node's Solana keys starknet Remote commands for administering the node's StarkNet keys + aptos Remote commands for administering the node's Aptos keys dkgsign Remote commands for administering the node's DKGSign keys dkgencrypt Remote commands for administering the node's DKGEncrypt keys vrf Remote commands for administering the node's vrf keys From e71ea7b5153c3c74637823e5d21842d402f61938 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:56:38 +0530 Subject: [PATCH 36/61] fix benchmark test namespace name (#13729) --- integration-tests/benchmark/keeper_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index 7cee5d18a8..177b352101 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -308,7 +308,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.KeeperBenc TTL: time.Hour * 720, // 30 days, NamespacePrefix: fmt.Sprintf( "automation-%s-%s-%s", - strings.ToLower(strings.Join(keeperTestConfig.GetConfigurationNames(), "_")), + strings.ToLower(strings.Join(keeperTestConfig.GetConfigurationNames(), "")), strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), strings.ReplaceAll(strings.ToLower(*keeperTestConfig.GetKeeperConfig().Common.RegistryToTest), "_", "-"), ), From bb784acd117c9952565fde1ba4507308939fd03e Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Tue, 2 Jul 2024 13:07:28 +0200 Subject: [PATCH 37/61] run tests only if there's > 1 eth implementations or base64 input is not empty (#13738) --- .../workflows/client-compatibility-tests.yml | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index 7555341272..b3bbc115de 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -157,7 +157,11 @@ jobs: fi IFS=',' eth_implementations="${implementations_arr[*]}" - echo "Found new releases for: $eth_implementations" + if [ -n "$eth_implementations" ]; then + echo "Found new releases for: $eth_implementations" + else + echo "No new releases found" + fi echo "evm_implementations=$eth_implementations" >> $GITHUB_OUTPUT elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then if [ -n "${{ github.event.inputs.base64TestList }}" ]; then @@ -229,7 +233,7 @@ jobs: check-ecr-images-exist: name: Check images used as test dependencies exist in ECR - if: always() && needs.should-run.outputs.should_run == 'true' + if: always() && needs.should-run.outputs.should_run == 'true' && (needs.select-versions.outputs.evm_implementations != '' || github.event.inputs.base64TestList != '') environment: integration permissions: id-token: write @@ -263,7 +267,7 @@ jobs: page_size: ${{matrix.mirror.page_size}} build-chainlink: - if: always() && needs.should-run.outputs.should_run == 'true' + if: always() && needs.should-run.outputs.should_run == 'true' && (needs.select-versions.outputs.evm_implementations != '' || github.event.inputs.base64TestList != '') environment: integration permissions: id-token: write @@ -298,7 +302,7 @@ jobs: get-latest-available-images: name: Get Latest EVM Implementation's Images - if: always() && needs.should-run.outputs.should_run == 'true' + if: always() && needs.should-run.outputs.should_run == 'true' && (needs.select-versions.outputs.evm_implementations != '' || github.event.inputs.base64TestList != '') environment: integration runs-on: ubuntu-latest needs: [check-ecr-images-exist, should-run, select-versions] @@ -371,7 +375,7 @@ jobs: prepare-compatibility-matrix: name: Prepare Compatibility Matrix - if: always() && needs.should-run.outputs.should_run == 'true' + if: always() && needs.should-run.outputs.should_run == 'true' && (needs.select-versions.outputs.evm_implementations != '' || github.event.inputs.base64TestList != '') environment: integration permissions: checks: write @@ -501,7 +505,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' + if: always() && needs.should-run.outputs.should_run == 'true' && needs.build-chainlink.result == 'success' && needs.prepare-compatibility-matrix.outputs.matrix != '' environment: integration permissions: checks: write @@ -605,7 +609,7 @@ jobs: start-slack-thread: name: Start Slack Thread - if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' + if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' && (needs.select-versions.outputs.evm_implementations != '' || github.event.inputs.base64TestList != '') environment: integration outputs: thread_ts: ${{ steps.slack.outputs.thread_ts }} @@ -664,7 +668,7 @@ jobs: parse-test-results: name: Parse Test Results - if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' + if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' && (needs.select-versions.outputs.evm_implementations != '' || github.event.inputs.base64TestList != '') environment: integration permissions: checks: write @@ -750,7 +754,7 @@ jobs: post-test-results-to-slack: name: Post Test Results for ${{matrix.product}} - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' }} + if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' && needs.parse-test-results.result == 'success' environment: integration permissions: checks: write From fea276ca74dfb1982525bd401d6ecfb79f17a453 Mon Sep 17 00:00:00 2001 From: Sneha Agnihotri <180277+snehaagni@users.noreply.github.com> Date: Tue, 2 Jul 2024 18:24:04 +0530 Subject: [PATCH 38/61] [RE-2665] chore/release 2.13.0 to develop (#13737) * Bump version and update CHANGELOG for core v2.13.0 Signed-off-by: Sneha Agnihotri * Curate changelog, remove #internal changesets Signed-off-by: Sneha Agnihotri * Finalize date on changelog for 2.13.0 Signed-off-by: Sneha Agnihotri --------- Signed-off-by: Sneha Agnihotri --- .changeset/curly-crabs-doubt.md | 5 -- .changeset/honest-avocados-heal.md | 5 -- CHANGELOG.md | 125 +---------------------------- 3 files changed, 1 insertion(+), 134 deletions(-) delete mode 100644 .changeset/curly-crabs-doubt.md delete mode 100644 .changeset/honest-avocados-heal.md diff --git a/.changeset/curly-crabs-doubt.md b/.changeset/curly-crabs-doubt.md deleted file mode 100644 index 0408383bd0..0000000000 --- a/.changeset/curly-crabs-doubt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/honest-avocados-heal.md b/.changeset/honest-avocados-heal.md deleted file mode 100644 index a28c08fde8..0000000000 --- a/.changeset/honest-avocados-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -add test for v23 #added diff --git a/CHANGELOG.md b/CHANGELOG.md index 7662247a36..be5d8d1c0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,33 +1,14 @@ # Changelog Chainlink Core -## 2.13.0 - UNRELEASED +## 2.13.0 - 2024-07-01 ### Minor Changes -- [#13235](https://github.com/smartcontractkit/chainlink/pull/13235) [`5374a577dd`](https://github.com/smartcontractkit/chainlink/commit/5374a577dd6396e149c26168a2f093b3204dfddb) Thanks [@krehermann](https://github.com/krehermann)! - #internal move workflow validation to common repo - -- [#12970](https://github.com/smartcontractkit/chainlink/pull/12970) [`1eb7180205`](https://github.com/smartcontractkit/chainlink/commit/1eb71802053fcde7e809ef58918110cf03046f3a) Thanks [@dimriou](https://github.com/dimriou)! - Decouple client tests from core #internal - - [#13354](https://github.com/smartcontractkit/chainlink/pull/13354) [`58d73ecf61`](https://github.com/smartcontractkit/chainlink/commit/58d73ecf618ac39c37f767e70c4e6d6a51eaba59) Thanks [@friedemannf](https://github.com/friedemannf)! - #breaking_change Remove the `xdai` `ChainType` config option. Moving forward, only `gnosis` can be used. -- [#12971](https://github.com/smartcontractkit/chainlink/pull/12971) [`a2441ba8cc`](https://github.com/smartcontractkit/chainlink/commit/a2441ba8cc44b6455338410b739d394a3bf3557e) Thanks [@dimriou](https://github.com/dimriou)! - Decouple evm config tests from core #internal - -- [#13396](https://github.com/smartcontractkit/chainlink/pull/13396) [`5ff32bde25`](https://github.com/smartcontractkit/chainlink/commit/5ff32bde2575d2b2ef626a69d54b9f6eed0d21c5) Thanks [@ettec](https://github.com/ettec)! - #internal keystone: handle local target transmission logic in capability wrapper - -- [#13357](https://github.com/smartcontractkit/chainlink/pull/13357) [`21f38e52d1`](https://github.com/smartcontractkit/chainlink/commit/21f38e52d1d2401f58da83f143043e3f4561e21c) Thanks [@ettec](https://github.com/ettec)! - #internal remote target capability and transmission protocol - -- [#13397](https://github.com/smartcontractkit/chainlink/pull/13397) [`daf8cf6cfe`](https://github.com/smartcontractkit/chainlink/commit/daf8cf6cfe1c0b8d2a70fb476a4e815af5025ebe) Thanks [@dimriou](https://github.com/dimriou)! - Remove multiple core dependencies from evm head tracker tests #internal" - -- [#13312](https://github.com/smartcontractkit/chainlink/pull/13312) [`c3829cac20`](https://github.com/smartcontractkit/chainlink/commit/c3829cac20e158f805d0efb9a8a2183e8d7b0515) Thanks [@amit-momin](https://github.com/amit-momin)! - #internal Added new Geth InsufficientEth client error for internal TXM classification - -- [#13381](https://github.com/smartcontractkit/chainlink/pull/13381) [`0a62f024e1`](https://github.com/smartcontractkit/chainlink/commit/0a62f024e10398cdd6451ef0d15db2501de11538) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal Pre-process contract abis in the evm chainwriter. - [#13221](https://github.com/smartcontractkit/chainlink/pull/13221) [`0b100ad3db`](https://github.com/smartcontractkit/chainlink/commit/0b100ad3dbf0a3c2fbd6e55c539046f6f3c9e5f6) Thanks [@ilija42](https://github.com/ilija42)! - Added a mechanism to validate forwarders for OCR2 and fallback to EOA if necessary #added -- [#13416](https://github.com/smartcontractkit/chainlink/pull/13416) [`68e00b3abf`](https://github.com/smartcontractkit/chainlink/commit/68e00b3abf566a222ff6775b0fb2575ff73f735e) Thanks [@ettec](https://github.com/ettec)! - #internal fix for workflow step persistence - -- [#13259](https://github.com/smartcontractkit/chainlink/pull/13259) [`76dbe19282`](https://github.com/smartcontractkit/chainlink/commit/76dbe192822c7e9f289c98e33ebb6693a07046a0) Thanks [@archseer](https://github.com/archseer)! - #internal Added a configuration option to chain writer to set the tx send strategy. - - [#13384](https://github.com/smartcontractkit/chainlink/pull/13384) [`bc087f1de2`](https://github.com/smartcontractkit/chainlink/commit/bc087f1de2014cce1027341d14e0917c4351fb21) Thanks [@augustbleeds](https://github.com/augustbleeds)! - bump chainlink-starknet so it builds reports with median gas price #updated - [#13353](https://github.com/smartcontractkit/chainlink/pull/13353) [`7a86103474`](https://github.com/smartcontractkit/chainlink/commit/7a861034740a44ebb5d3f1da2d271637691c0bd3) Thanks [@pavel-raykov](https://github.com/pavel-raykov)! - #updated Remove deprecated app.shortcut links @@ -36,64 +17,25 @@ - [#13455](https://github.com/smartcontractkit/chainlink/pull/13455) [`066afc0877`](https://github.com/smartcontractkit/chainlink/commit/066afc0877a9e953bbda25a4ff09009d7f1c1e2d) Thanks [@krehermann](https://github.com/krehermann)! - #bugfix use correct internal id in workflow auto-approval -- [#13259](https://github.com/smartcontractkit/chainlink/pull/13259) [`76dbe19282`](https://github.com/smartcontractkit/chainlink/commit/76dbe192822c7e9f289c98e33ebb6693a07046a0) Thanks [@archseer](https://github.com/archseer)! - #internal added tests for Chainwriter - - [#12881](https://github.com/smartcontractkit/chainlink/pull/12881) [`d675d864f0`](https://github.com/smartcontractkit/chainlink/commit/d675d864f0e6f33c783bfed17fe31b2c127eb51d) Thanks [@amit-momin](https://github.com/amit-momin)! - #added Added an auto-purge feature to the EVM TXM that identifies terminally stuck transactions either through a chain specific method or heurisitic then purges them to unblock the nonce. Included 4 new toml configs under Transactions.AutoPurge to configure this new feature: Enabled, Threshold, MinAttempts, and DetectionApiUrl. - [#13401](https://github.com/smartcontractkit/chainlink/pull/13401) [`905830c3ff`](https://github.com/smartcontractkit/chainlink/commit/905830c3ff16c670c3fbf3d83a0c2ca3a15e83a8) Thanks [@krehermann](https://github.com/krehermann)! - #db_update add persistence for DON-2-DON discovery announcements -- [#13466](https://github.com/smartcontractkit/chainlink/pull/13466) [`4fdfffdb4c`](https://github.com/smartcontractkit/chainlink/commit/4fdfffdb4c4a6f16fcdb388fe38642398ce130da) Thanks [@dimriou](https://github.com/dimriou)! - Move chaintype #internal - - [#13200](https://github.com/smartcontractkit/chainlink/pull/13200) [`4718aa7ec2`](https://github.com/smartcontractkit/chainlink/commit/4718aa7ec20e2ef70dff7fb72095d357f3725a80) Thanks [@augustbleeds](https://github.com/augustbleeds)! - Add option to include GasPriceSubunits pipeline to include gasPriceSubunits in median ocr2 transmission (only to be used with Starknet chain for now) #added #nops #updated - -- [#13215](https://github.com/smartcontractkit/chainlink/pull/13215) [`66d8d16638`](https://github.com/smartcontractkit/chainlink/commit/66d8d16638f16dc863cbc6d24356c3cf3c9724f0) Thanks [@ettec](https://github.com/ettec)! - #internal standard capability support - -- [#12995](https://github.com/smartcontractkit/chainlink/pull/12995) [`322f3b9616`](https://github.com/smartcontractkit/chainlink/commit/322f3b96162a4e0738d76ba00f949c5b19d09909) Thanks [@dimriou](https://github.com/dimriou)! - Decouple monitoring tests from core #internal - -- [#12972](https://github.com/smartcontractkit/chainlink/pull/12972) [`1196df4684`](https://github.com/smartcontractkit/chainlink/commit/1196df4684c812361b8f0994ade6414a1f214c2c) Thanks [@dimriou](https://github.com/dimriou)! - Decouple gas tests from core #internal - -- [#12993](https://github.com/smartcontractkit/chainlink/pull/12993) [`2a8d1b150a`](https://github.com/smartcontractkit/chainlink/commit/2a8d1b150a07c5dfd036559a35c8f83bb3e4f757) Thanks [@dimriou](https://github.com/dimriou)! - Decouple utils tests from core #internal - -- [#13445](https://github.com/smartcontractkit/chainlink/pull/13445) [`3ff5128026`](https://github.com/smartcontractkit/chainlink/commit/3ff51280266dd979cbe2a8fe779c669a4e12fe22) Thanks [@ettec](https://github.com/ettec)! - #internal update operator ui versioun - - [#13259](https://github.com/smartcontractkit/chainlink/pull/13259) [`76dbe19282`](https://github.com/smartcontractkit/chainlink/commit/76dbe192822c7e9f289c98e33ebb6693a07046a0) Thanks [@archseer](https://github.com/archseer)! - #added A ChainWriter implementation in the EVM relay. - [#13265](https://github.com/smartcontractkit/chainlink/pull/13265) [`5db47b63b3`](https://github.com/smartcontractkit/chainlink/commit/5db47b63b3f2d0addf521904940d780caf9f57eb) Thanks [@krehermann](https://github.com/krehermann)! - #db_update Add name to workflow spec. Add unique constraint to (owner,name) for workflow spec -- [#13089](https://github.com/smartcontractkit/chainlink/pull/13089) [`b00ad69095`](https://github.com/smartcontractkit/chainlink/commit/b00ad6909571042947f615b8740c31c304bbf7ec) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #internal Switched finality check in HeadTracker to use the underlying finality type - ### Patch Changes -- [#13377](https://github.com/smartcontractkit/chainlink/pull/13377) [`390ee1990e`](https://github.com/smartcontractkit/chainlink/commit/390ee1990e2545d4f47e64a521ee61ee0b200786) Thanks [@bolekk](https://github.com/bolekk)! - #internal handle new metadata fields - [#13315](https://github.com/smartcontractkit/chainlink/pull/13315) [`3af83ed014`](https://github.com/smartcontractkit/chainlink/commit/3af83ed01439648354ac6b348d61b0f9594b99ec) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Reducing the scope of 0233 migration to include only 5th word index which is required for CCIP #db_update -- [#13139](https://github.com/smartcontractkit/chainlink/pull/13139) [`15fab1daa8`](https://github.com/smartcontractkit/chainlink/commit/15fab1daa84348e96a7895280209cb73e456a1c5) Thanks [@jmank88](https://github.com/jmank88)! - core/services: fix ocrWrapper saveError contexts #internal - - [#13144](https://github.com/smartcontractkit/chainlink/pull/13144) [`49f1bf3ba2`](https://github.com/smartcontractkit/chainlink/commit/49f1bf3ba296f0e3dfc01d5a3d371f82f159dc4a) Thanks [@jmank88](https://github.com/jmank88)! - improve handling of postgres connection settings and driver versions #db - [#13286](https://github.com/smartcontractkit/chainlink/pull/13286) [`6139126034`](https://github.com/smartcontractkit/chainlink/commit/61391260340ba74f3510e6ded4fdace6829630b7) Thanks [@EasterTheBunny](https://github.com/EasterTheBunny)! - enforce proper result indexing on pipeline results #breaking_change - [#13279](https://github.com/smartcontractkit/chainlink/pull/13279) [`5a87f4a59e`](https://github.com/smartcontractkit/chainlink/commit/5a87f4a59e3c6c92b08ebefc5090017693785729) Thanks [@DylanTinianov](https://github.com/DylanTinianov)! - #changed Remove ClientErrors interface from common - -- [#13190](https://github.com/smartcontractkit/chainlink/pull/13190) [`c93e83ab99`](https://github.com/smartcontractkit/chainlink/commit/c93e83ab992c5238ec79f9581f2eb370d9862492) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Add Keystone CRIB Provisioning - -- [#13008](https://github.com/smartcontractkit/chainlink/pull/13008) [`841fe61daa`](https://github.com/smartcontractkit/chainlink/commit/841fe61daa90b980f1e1622d2f7bd8f850b55462) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Keystone - rename type -> id - -- [#13436](https://github.com/smartcontractkit/chainlink/pull/13436) [`f37afb9eba`](https://github.com/smartcontractkit/chainlink/commit/f37afb9ebaeda10f8b3873b069b8a824e60a81c3) Thanks [@bolekk](https://github.com/bolekk)! - #internal #bugfix keystone bugfixes - -- [#13214](https://github.com/smartcontractkit/chainlink/pull/13214) [`921a015792`](https://github.com/smartcontractkit/chainlink/commit/921a015792570ad3fa3b7700bdd3ec8f0590b383) Thanks [@momentmaker](https://github.com/momentmaker)! - Add to CI changeset workflow an additional step to update the Jira issue associated with this PR and set the `fixVersions` for the issue with the upcoming core release version. #internal #wip - -- [#13449](https://github.com/smartcontractkit/chainlink/pull/13449) [`69a95d8262`](https://github.com/smartcontractkit/chainlink/commit/69a95d82626290858219250e746fd51c8c7c4093) Thanks [@dimriou](https://github.com/dimriou)! - Cleanup txm tests #internal - -- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`96304756a7`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - #internal add modify DON function to capability registry - -- [#13453](https://github.com/smartcontractkit/chainlink/pull/13453) [`8c98c80376`](https://github.com/smartcontractkit/chainlink/commit/8c98c80376c3b6d72bffeab62ee45a74449b6ef5) Thanks [@cds95](https://github.com/cds95)! - #internal return hashed capability ids - -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal remove update capabilities from capability registry - -- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`96304756a7`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - #internal add getters in capability registry - - [#13230](https://github.com/smartcontractkit/chainlink/pull/13230) [`6f1ebca197`](https://github.com/smartcontractkit/chainlink/commit/6f1ebca1970d4a970be64c581800ab781c6c3c7c) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Fixed CPU usage issues caused by inefficiencies in HeadTracker. HeadTracker's support of finality tags caused a drastic increase in the number of tracked blocks on the Arbitrum chain (from 50 to 12,000), which has led to a 30% increase in CPU usage. @@ -106,15 +48,6 @@ - [#13364](https://github.com/smartcontractkit/chainlink/pull/13364) [`fc007a9484`](https://github.com/smartcontractkit/chainlink/commit/fc007a94846c178bc9d5203dbff6b6b8c7546a71) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #bugfix fix a funding bug in LinkAvailableBalanceMonitor -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal capability registry informational findings - -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal return don capability config contract config from capability registry - -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal add capability registry comment explaining why we do not validate node operator name - -- [#13425](https://github.com/smartcontractkit/chainlink/pull/13425) [`eeb363f123`](https://github.com/smartcontractkit/chainlink/commit/eeb363f1230415dde573607a095b177c612d3bef) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal - -- [#13328](https://github.com/smartcontractkit/chainlink/pull/13328) [`0d95942ad4`](https://github.com/smartcontractkit/chainlink/commit/0d95942ad414a3ecefb17bd8166fe28f474018d0) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal [Keystone] Merge version field with ID - [#13174](https://github.com/smartcontractkit/chainlink/pull/13174) [`e778a3202b`](https://github.com/smartcontractkit/chainlink/commit/e778a3202b4d8761ffc44b790196d9a580fede1c) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #changed: AUTO-10539: adjust logging for offchain config and gas control @@ -122,50 +55,27 @@ - [#12952](https://github.com/smartcontractkit/chainlink/pull/12952) [`7572a50a78`](https://github.com/smartcontractkit/chainlink/commit/7572a50a78a270188344786937f68233df82f65b) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #added compare user-defined max gas price with current gas price in automation simulation pipeline -- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`96304756a7`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - #internal update ICapabilityConfiguration interface - [#13216](https://github.com/smartcontractkit/chainlink/pull/13216) [`6099abbdbf`](https://github.com/smartcontractkit/chainlink/commit/6099abbdbfb3ad396ca1ed5138ecd7a13159de19) Thanks [@ibrajer](https://github.com/ibrajer)! - Added Base Sepolia to ChainUtils #changed - [#13177](https://github.com/smartcontractkit/chainlink/pull/13177) [`0d58a8d5db`](https://github.com/smartcontractkit/chainlink/commit/0d58a8d5db24f42720226e73328e501637ba59c5) Thanks [@shileiwill](https://github.com/shileiwill)! - link transfer status check #bugfix -- [#13118](https://github.com/smartcontractkit/chainlink/pull/13118) [`6008d730bf`](https://github.com/smartcontractkit/chainlink/commit/6008d730bf1fcfc4a9dd1e46497c3db75cf390fe) Thanks [@bolekk](https://github.com/bolekk)! - #internal Pass MercuryTriggerService to Mercury Transmitter - - [#13058](https://github.com/smartcontractkit/chainlink/pull/13058) [`a34a17ae9d`](https://github.com/smartcontractkit/chainlink/commit/a34a17ae9d62679a1ff15a7703f5cbcf6dfd1d0f) Thanks [@shileiwill](https://github.com/shileiwill)! - withdraw in offchain mode #bugfix -- [#13328](https://github.com/smartcontractkit/chainlink/pull/13328) [`0d95942ad4`](https://github.com/smartcontractkit/chainlink/commit/0d95942ad414a3ecefb17bd8166fe28f474018d0) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Add workflow validation - -- [#13456](https://github.com/smartcontractkit/chainlink/pull/13456) [`b09c14d0ca`](https://github.com/smartcontractkit/chainlink/commit/b09c14d0ca85678799cb108500687d0e8456205a) Thanks [@bolekk](https://github.com/bolekk)! - #internal [Keystone] Add remote target to syncer - -- [#13176](https://github.com/smartcontractkit/chainlink/pull/13176) [`d2cd916e46`](https://github.com/smartcontractkit/chainlink/commit/d2cd916e46c51d76f7e1ea61a0cc86b1415f4036) Thanks [@ferglor](https://github.com/ferglor)! - Add logs for when the assumptions of how the log buffer will be used are violated #internal - - [#13213](https://github.com/smartcontractkit/chainlink/pull/13213) [`1b1e31ebfc`](https://github.com/smartcontractkit/chainlink/commit/1b1e31ebfc5198ab7e43291110b6f5d54e467a01) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #bugfix fix an automation smoke test flake -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal verify valid node operator when adding nodes to capability registry - -- [#13218](https://github.com/smartcontractkit/chainlink/pull/13218) [`4938ef3961`](https://github.com/smartcontractkit/chainlink/commit/4938ef396112a6de6f9822cfcc116fd5cdfb92be) Thanks [@bolekk](https://github.com/bolekk)! - #internal ReportCodec for Streams trigger - -- [#13094](https://github.com/smartcontractkit/chainlink/pull/13094) [`a0d1ce5e9c`](https://github.com/smartcontractkit/chainlink/commit/a0d1ce5e9cddc540bba8eb193865646cf0ebc0a8) Thanks [@momentmaker](https://github.com/momentmaker)! - Refactor changesets release preview workflow #internal - -- [#13175](https://github.com/smartcontractkit/chainlink/pull/13175) [`fbd94c4351`](https://github.com/smartcontractkit/chainlink/commit/fbd94c43511dabd272d7fd990dfb76de66c30a16) Thanks [@erikburt](https://github.com/erikburt)! - bump chainlink-solana dependency #internal - -- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`96304756a7`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - #internal implement remove DONs in capability registry - [#12813](https://github.com/smartcontractkit/chainlink/pull/12813) [`ac893364e6`](https://github.com/smartcontractkit/chainlink/commit/ac893364e6c6ede08e9bf04da7dc64e0da94ab6e) Thanks [@matYang](https://github.com/matYang)! - #db_update created 2 new CCIP tables in migration 0236, one for observed gas prices, one for observed token prices; setup indexing for these tables. #added ORM for CCIP gas prices and token prices -- [#13080](https://github.com/smartcontractkit/chainlink/pull/13080) [`36cc95f625`](https://github.com/smartcontractkit/chainlink/commit/36cc95f6256b5ba418a916de2c9dc9597508147a) Thanks [@cds95](https://github.com/cds95)! - #internal Generate gethwrappers for capability registry changes - [#13173](https://github.com/smartcontractkit/chainlink/pull/13173) [`a9717f05e9`](https://github.com/smartcontractkit/chainlink/commit/a9717f05e9af0fa07746c6b95b7f1625089a860f) Thanks [@ferglor](https://github.com/ferglor)! - Revert block number tracking #changed -- [#13453](https://github.com/smartcontractkit/chainlink/pull/13453) [`8c98c80376`](https://github.com/smartcontractkit/chainlink/commit/8c98c80376c3b6d72bffeab62ee45a74449b6ef5) Thanks [@cds95](https://github.com/cds95)! - #internal update error message when node does not exist - - [#12952](https://github.com/smartcontractkit/chainlink/pull/12952) [`7572a50a78`](https://github.com/smartcontractkit/chainlink/commit/7572a50a78a270188344786937f68233df82f65b) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #added pass a gas estimator to registry 2.1 pipeline -- [#13128](https://github.com/smartcontractkit/chainlink/pull/13128) [`a0e7b7cdd6`](https://github.com/smartcontractkit/chainlink/commit/a0e7b7cdd63ecb3f4d8e0ca3f5a4111703760c9b) Thanks [@samsondav](https://github.com/samsondav)! - #internal improve mercury tranmission debugging - - [#13132](https://github.com/smartcontractkit/chainlink/pull/13132) [`eed5668e3c`](https://github.com/smartcontractkit/chainlink/commit/eed5668e3c83cb680d2915f89d097fcb1b74a4f9) Thanks [@akuzni2](https://github.com/akuzni2)! - #nops fix metric description on mercury_transmit_queue_load - [#13084](https://github.com/smartcontractkit/chainlink/pull/13084) [`d79bdf16c5`](https://github.com/smartcontractkit/chainlink/commit/d79bdf16c5129cf7bc7cc5114f92eb07fd3fbf02) Thanks [@austinborn](https://github.com/austinborn)! - #updated Add gethwrappers for operatorforwarder contracts @@ -176,27 +86,15 @@ - [#13133](https://github.com/smartcontractkit/chainlink/pull/13133) [`2e668372ac`](https://github.com/smartcontractkit/chainlink/commit/2e668372ac54e71fd357feba427ffacf0613bda2) Thanks [@matYang](https://github.com/matYang)! - #changed CCIP price cache to use DB timestamp -- [#13380](https://github.com/smartcontractkit/chainlink/pull/13380) [`21c4cde066`](https://github.com/smartcontractkit/chainlink/commit/21c4cde066f3d6a49072ca338c966265b910583e) Thanks [@dimriou](https://github.com/dimriou)! - Removed deprecated evm client code #internal - - [#13096](https://github.com/smartcontractkit/chainlink/pull/13096) [`2c08c8c1a5`](https://github.com/smartcontractkit/chainlink/commit/2c08c8c1a58ea4b7c09b0d5a5ca3b8a677beb9f4) Thanks [@shileiwill](https://github.com/shileiwill)! - add upkeepCharged event #bugfix -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal verify that node is not part of a DON when removing - -- [#13202](https://github.com/smartcontractkit/chainlink/pull/13202) [`eb6b50d313`](https://github.com/smartcontractkit/chainlink/commit/eb6b50d31323c324aaa2bf8d1cf465f97a7893fd) Thanks [@bolekk](https://github.com/bolekk)! - #internal [Keystone] EVM encoder support for tuples - [#13078](https://github.com/smartcontractkit/chainlink/pull/13078) [`0917394a46`](https://github.com/smartcontractkit/chainlink/commit/0917394a4625c3e97b17e348dd473199a15402bf) Thanks [@finleydecker](https://github.com/finleydecker)! - bumpThreshold config setting for chains using suggestPrice estimator #updated -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal remove tracking deprecated arrays - -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal capability registry internal review - - [#13336](https://github.com/smartcontractkit/chainlink/pull/13336) [`4c7e5a0efa`](https://github.com/smartcontractkit/chainlink/commit/4c7e5a0efa90aed5d5454b5a68753076eea67f55) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Added config option `HeadTracker.FinalityTagBypass` to force `HeadTracker` to track blocks up to `FinalityDepth` even if `FinalityTagsEnabled = true`. This option is a temporary measure to address high CPU usage on chains with extremely large actual finality depth (gap between the current head and the latest finalized block). #added Added config option `HeadTracker.MaxAllowedFinalityDepth` maximum gap between current head to the latest finalized block that `HeadTracker` considers healthy. #added -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal internal-review-fixes-for-capability-registry - -- [#13199](https://github.com/smartcontractkit/chainlink/pull/13199) [`4f502c9fd0`](https://github.com/smartcontractkit/chainlink/commit/4f502c9fd0fea458647bb345f5c0da995f3b6cb1) Thanks [@bolekk](https://github.com/bolekk)! - #internal Use Aggregator factory for OCR capability - [#13263](https://github.com/smartcontractkit/chainlink/pull/13263) [`14ec6c4a91`](https://github.com/smartcontractkit/chainlink/commit/14ec6c4a912eeb65753703c363d1e90cbcf88328) Thanks [@shileiwill](https://github.com/shileiwill)! - tune debugging script #bugfix @@ -204,27 +102,6 @@ - [#13165](https://github.com/smartcontractkit/chainlink/pull/13165) [`143741012c`](https://github.com/smartcontractkit/chainlink/commit/143741012c4d0b148ada9d5aa237ff932cd3005b) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - #db_update Add ON DELETE CASCADE to workflow tables -- [#13103](https://github.com/smartcontractkit/chainlink/pull/13103) [`54f7c9c8f5`](https://github.com/smartcontractkit/chainlink/commit/54f7c9c8f5508d0d0a063eb435404b4164723300) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal regen geth wrappers for capability registry - -- [#13112](https://github.com/smartcontractkit/chainlink/pull/13112) [`80590662bd`](https://github.com/smartcontractkit/chainlink/commit/80590662bd9956d3c93449ca4703a2430e0613b7) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Normalize keystone workflow ref regex property to match id regex - -- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`96304756a7`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - #internal track config count in DON struct - -- [#13102](https://github.com/smartcontractkit/chainlink/pull/13102) [`700a827194`](https://github.com/smartcontractkit/chainlink/commit/700a82719451611381ab5dbb94fe00547660440b) Thanks [@cds95](https://github.com/cds95)! - #internal generate geth wrappers for capability registry remove nodes - -- [#13406](https://github.com/smartcontractkit/chainlink/pull/13406) [`a63569c9a3`](https://github.com/smartcontractkit/chainlink/commit/a63569c9a3893a7dc431459e08a4b08bb3a91231) Thanks [@bolekk](https://github.com/bolekk)! - #internal #bugfix Fix target wrapper init problems - -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal allow updating capabilities and to add/remove multiple capabilities at once from the capability registry - -- [#13189](https://github.com/smartcontractkit/chainlink/pull/13189) [`1451b2b632`](https://github.com/smartcontractkit/chainlink/commit/1451b2b6321f997c2df2c0b7fd05d6ba1eac30e4) Thanks [@samsondav](https://github.com/samsondav)! - Performance improvements for mercury single insert for multiple mercury servers #internal - -- [#13366](https://github.com/smartcontractkit/chainlink/pull/13366) [`d53d6d08da`](https://github.com/smartcontractkit/chainlink/commit/d53d6d08dac5d3ee27ae89012669c6c2455295c8) Thanks [@bolekk](https://github.com/bolekk)! - #internal keystone report context - -- [#13389](https://github.com/smartcontractkit/chainlink/pull/13389) [`3959091d4f`](https://github.com/smartcontractkit/chainlink/commit/3959091d4f3925b64cb6b0b55b7f7c72a4f924b9) Thanks [@bolekk](https://github.com/bolekk)! - #internal Update metadata passed to Forwarder and Receiver - -- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`96304756a7`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - #internal update node signer type - -- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb36b`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal update uint256 to uint32 for donId declaration in capability config interface - [#12952](https://github.com/smartcontractkit/chainlink/pull/12952) [`7572a50a78`](https://github.com/smartcontractkit/chainlink/commit/7572a50a78a270188344786937f68233df82f65b) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #added an integration test for max gas price check From 2ecf45d381b98714f4f673221bfc74577fcfeb04 Mon Sep 17 00:00:00 2001 From: ferglor Date: Tue, 2 Jul 2024 14:21:40 +0100 Subject: [PATCH 39/61] Only encode non nil block numbers (#13726) * WIP specify block 0 * Remove 0 block check * Add changeset * Tweak changeset * Only set non nil block numbers * Lint --- .changeset/curvy-months-change.md | 5 ++ .../ocr2keeper/evmregistry/v20/registry.go | 57 ++++++++++++------- .../v21/registry_check_pipeline.go | 43 ++++++++------ 3 files changed, 68 insertions(+), 37 deletions(-) create mode 100644 .changeset/curvy-months-change.md diff --git a/.changeset/curvy-months-change.md b/.changeset/curvy-months-change.md new file mode 100644 index 0000000000..1a3b1b3ce9 --- /dev/null +++ b/.changeset/curvy-months-change.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Only encode non nil block numbers for eth_call #changed diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go index ce7325a96b..0cddd43448 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go @@ -594,16 +594,21 @@ func (r *EvmRegistry) checkUpkeeps(ctx context.Context, keys []ocr2keepers.Upkee return nil, err } + args := []interface{}{ + map[string]interface{}{ + "to": r.addr.Hex(), + "data": hexutil.Bytes(payload), + }, + } + + if opts.BlockNumber != nil { + args = append(args, hexutil.EncodeBig(opts.BlockNumber)) + } + var result string checkReqs[i] = rpc.BatchElem{ Method: "eth_call", - Args: []interface{}{ - map[string]interface{}{ - "to": r.addr.Hex(), - "data": hexutil.Bytes(payload), - }, - hexutil.EncodeBig(opts.BlockNumber), - }, + Args: args, Result: &result, } @@ -660,16 +665,21 @@ func (r *EvmRegistry) simulatePerformUpkeeps(ctx context.Context, checkResults [ return nil, err } + args := []interface{}{ + map[string]interface{}{ + "to": r.addr.Hex(), + "data": hexutil.Bytes(payload), + }, + } + + if opts.BlockNumber != nil { + args = append(args, hexutil.EncodeBig(opts.BlockNumber)) + } + var result string performReqs = append(performReqs, rpc.BatchElem{ Method: "eth_call", - Args: []interface{}{ - map[string]interface{}{ - "to": r.addr.Hex(), - "data": hexutil.Bytes(payload), - }, - hexutil.EncodeBig(opts.BlockNumber), - }, + Args: args, Result: &result, }) @@ -726,16 +736,21 @@ func (r *EvmRegistry) getUpkeepConfigs(ctx context.Context, ids []*big.Int) ([]a return nil, fmt.Errorf("failed to pack id with abi: %s", err) } + args := []interface{}{ + map[string]interface{}{ + "to": r.addr.Hex(), + "data": hexutil.Bytes(payload), + }, + } + + if opts.BlockNumber != nil { + args = append(args, hexutil.EncodeBig(opts.BlockNumber)) + } + var result string uReqs[i] = rpc.BatchElem{ Method: "eth_call", - Args: []interface{}{ - map[string]interface{}{ - "to": r.addr.Hex(), - "data": hexutil.Bytes(payload), - }, - hexutil.EncodeBig(opts.BlockNumber), - }, + Args: args, Result: &result, } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go index f14c9865c3..6927f5ba4c 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go @@ -233,17 +233,22 @@ func (r *EvmRegistry) checkUpkeeps(ctx context.Context, payloads []ocr2keepers.U indices[len(checkReqs)] = i results[i] = encoding.GetIneligibleCheckResultWithoutPerformData(p, encoding.UpkeepFailureReasonNone, encoding.NoPipelineError, false) + args := []interface{}{ + map[string]interface{}{ + "from": zeroAddress, + "to": r.addr.Hex(), + "data": hexutil.Bytes(payload), + }, + } + + if opts.BlockNumber != nil { + args = append(args, hexutil.EncodeBig(opts.BlockNumber)) + } + var result string checkReqs = append(checkReqs, rpc.BatchElem{ Method: "eth_call", - Args: []interface{}{ - map[string]interface{}{ - "from": zeroAddress, - "to": r.addr.Hex(), - "data": hexutil.Bytes(payload), - }, - hexutil.EncodeBig(opts.BlockNumber), - }, + Args: args, Result: &result, }) @@ -334,17 +339,23 @@ func (r *EvmRegistry) simulatePerformUpkeeps(ctx context.Context, checkResults [ } opts := r.buildCallOpts(ctx, block) + + args := []interface{}{ + map[string]interface{}{ + "from": zeroAddress, + "to": r.addr.Hex(), + "data": hexutil.Bytes(payload), + }, + } + + if opts.BlockNumber != nil { + args = append(args, hexutil.EncodeBig(opts.BlockNumber)) + } + var result string performReqs = append(performReqs, rpc.BatchElem{ Method: "eth_call", - Args: []interface{}{ - map[string]interface{}{ - "from": zeroAddress, - "to": r.addr.Hex(), - "data": hexutil.Bytes(payload), - }, - hexutil.EncodeBig(opts.BlockNumber), - }, + Args: args, Result: &result, }) From 0efeed64556d6e1477fdb369c00d0ed5e8ee44bc Mon Sep 17 00:00:00 2001 From: Cedric Date: Tue, 2 Jul 2024 16:21:23 +0100 Subject: [PATCH 40/61] [KS-285] Update DON struct; pass through DON Config Version (#13739) * Convert donID string -> uint32 to match capabilities registry * Fix launcher tests * Pass through ConfigVersion * Update tests * bump common --- core/capabilities/launcher.go | 19 +-- core/capabilities/launcher_test.go | 20 +-- core/capabilities/remote/dispatcher.go | 10 +- .../capabilities/remote/target/client_test.go | 6 +- .../remote/target/endtoend_test.go | 10 +- .../target/request/client_request_test.go | 8 +- .../remote/target/request/server_request.go | 4 +- .../target/request/server_request_test.go | 36 ++--- core/capabilities/remote/target/server.go | 4 +- .../capabilities/remote/target/server_test.go | 10 +- core/capabilities/remote/trigger_publisher.go | 6 +- .../remote/trigger_publisher_test.go | 6 +- .../remote/trigger_subscriber_test.go | 4 +- core/capabilities/remote/types/messages.pb.go | 143 +++++++++--------- core/capabilities/remote/types/messages.proto | 5 +- .../remote/types/mocks/dispatcher.go | 6 +- core/capabilities/remote/types/types.go | 4 +- core/capabilities/remote/utils_test.go | 4 +- .../transmission/local_target_capability.go | 2 +- .../local_target_capability_test.go | 2 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- core/services/relay/evm/cap_encoder.go | 6 +- core/services/relay/evm/cap_encoder_test.go | 5 +- core/services/workflows/engine.go | 29 ++-- core/services/workflows/engine_test.go | 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 +- 32 files changed, 192 insertions(+), 185 deletions(-) diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go index e4f7f480f3..c6846ecd5a 100644 --- a/core/capabilities/launcher.go +++ b/core/capabilities/launcher.go @@ -97,7 +97,7 @@ func (w *launcher) LocalNode(ctx context.Context) (capabilities.Node, error) { return w.localNode, errors.New("unable to get local node: peerWrapper hasn't started yet") } - if w.localNode.WorkflowDON.ID == "" { + if w.localNode.WorkflowDON.ID == 0 { return w.localNode, errors.New("unable to get local node: waiting for initial call from syncer") } @@ -113,7 +113,7 @@ func (w *launcher) updateLocalNode(state registrysyncer.State) { for _, p := range d.NodeP2PIds { if p == pid { if d.AcceptsWorkflows { - if workflowDON.ID == "" { + if workflowDON.ID == 0 { workflowDON = *toDONInfo(d) w.lggr.Debug("Workflow DON identified: %+v", workflowDON) } else { @@ -353,7 +353,7 @@ func (w *launcher) addToRegistryAndSetDispatcher(ctx context.Context, capability err = w.dispatcher.SetReceiver( fullCapID, - fmt.Sprint(don.Id), + don.Id, capability, ) if err != nil { @@ -373,9 +373,9 @@ var ( ) func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.PeerID, don kcr.CapabilitiesRegistryDONInfo, state registrysyncer.State, remoteWorkflowDONs []kcr.CapabilitiesRegistryDONInfo) error { - idsToDONs := map[string]capabilities.DON{} + idsToDONs := map[uint32]capabilities.DON{} for _, d := range remoteWorkflowDONs { - idsToDONs[fmt.Sprint(d.Id)] = *toDONInfo(d) + idsToDONs[d.Id] = *toDONInfo(d) } for _, c := range don.CapabilityConfigurations { @@ -465,7 +465,7 @@ func (w *launcher) addReceiver(ctx context.Context, capability kcr.CapabilitiesR } w.lggr.Debugw("Enabling external access for capability", "id", fullCapID, "donID", don.Id) - err = w.dispatcher.SetReceiver(fullCapID, fmt.Sprint(don.Id), receiver) + err = w.dispatcher.SetReceiver(fullCapID, don.Id, receiver) if err != nil { return fmt.Errorf("failed to set receiver: %w", err) } @@ -502,9 +502,10 @@ func toDONInfo(don kcr.CapabilitiesRegistryDONInfo) *capabilities.DON { } return &capabilities.DON{ - ID: fmt.Sprint(don.Id), - Members: peerIDs, - F: don.F, + ID: don.Id, + ConfigVersion: don.ConfigCount, + Members: peerIDs, + F: don.F, } } diff --git a/core/capabilities/launcher_test.go b/core/capabilities/launcher_test.go index c29e5ebf38..a2d1c60169 100644 --- a/core/capabilities/launcher_test.go +++ b/core/capabilities/launcher_test.go @@ -3,7 +3,6 @@ package capabilities import ( "context" "crypto/rand" - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -178,8 +177,8 @@ func TestLauncher_WiresUpExternalCapabilities(t *testing.T) { registry, ) - dispatcher.On("SetReceiver", fullTriggerCapID, fmt.Sprint(dID), mock.AnythingOfType("*remote.triggerPublisher")).Return(nil) - dispatcher.On("SetReceiver", fullTargetID, fmt.Sprint(dID), mock.AnythingOfType("*target.server")).Return(nil) + dispatcher.On("SetReceiver", fullTriggerCapID, dID, mock.AnythingOfType("*remote.triggerPublisher")).Return(nil) + dispatcher.On("SetReceiver", fullTargetID, dID, mock.AnythingOfType("*target.server")).Return(nil) err = launcher.Launch(ctx, state) require.NoError(t, err) @@ -428,8 +427,8 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDON(t *testing.T) { registry, ) - dispatcher.On("SetReceiver", fullTriggerCapID, fmt.Sprint(capDonID), mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) - dispatcher.On("SetReceiver", fullTargetID, fmt.Sprint(capDonID), mock.AnythingOfType("*target.client")).Return(nil) + dispatcher.On("SetReceiver", fullTriggerCapID, capDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) + dispatcher.On("SetReceiver", fullTargetID, capDonID, mock.AnythingOfType("*target.client")).Return(nil) err = launcher.Launch(ctx, state) require.NoError(t, err) @@ -586,7 +585,7 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie registry, ) - dispatcher.On("SetReceiver", fullTriggerCapID, fmt.Sprint(triggerCapDonID), mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) + dispatcher.On("SetReceiver", fullTriggerCapID, triggerCapDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) err = launcher.Launch(ctx, state) require.NoError(t, err) @@ -634,7 +633,7 @@ func TestLauncher_LocalNode(t *testing.T) { IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ registrysyncer.DonID(dID): { Id: dID, - ConfigCount: uint32(0), + ConfigCount: uint32(2), F: uint8(1), IsPublic: true, AcceptsWorkflows: true, @@ -680,9 +679,10 @@ func TestLauncher_LocalNode(t *testing.T) { require.NoError(t, err) don := capabilities.DON{ - ID: fmt.Sprintf("%d", dID), - Members: toPeerIDs(workflowDonNodes), - F: 1, + ID: dID, + ConfigVersion: 2, + Members: toPeerIDs(workflowDonNodes), + F: 1, } expectedNode := capabilities.Node{ PeerID: &pid, diff --git a/core/capabilities/remote/dispatcher.go b/core/capabilities/remote/dispatcher.go index b91211b5bf..90fca50b22 100644 --- a/core/capabilities/remote/dispatcher.go +++ b/core/capabilities/remote/dispatcher.go @@ -35,7 +35,7 @@ type dispatcher struct { type key struct { capId string - donId string + donId uint32 } var _ services.Service = &dispatcher{} @@ -88,13 +88,13 @@ type receiver struct { ch chan *remotetypes.MessageBody } -func (d *dispatcher) SetReceiver(capabilityId string, donId string, rec remotetypes.Receiver) error { +func (d *dispatcher) SetReceiver(capabilityId string, donId uint32, rec remotetypes.Receiver) error { d.mu.Lock() defer d.mu.Unlock() k := key{capabilityId, donId} _, ok := d.receivers[k] if ok { - return fmt.Errorf("receiver already exists for capability %s and don %s", capabilityId, donId) + return fmt.Errorf("receiver already exists for capability %s and don %d", capabilityId, donId) } receiverCh := make(chan *remotetypes.MessageBody, receiverBufferSize) @@ -123,7 +123,7 @@ func (d *dispatcher) SetReceiver(capabilityId string, donId string, rec remotety return nil } -func (d *dispatcher) RemoveReceiver(capabilityId string, donId string) { +func (d *dispatcher) RemoveReceiver(capabilityId string, donId uint32) { d.mu.Lock() defer d.mu.Unlock() @@ -181,7 +181,7 @@ func (d *dispatcher) receive() { } receiverQueueUsage := float64(len(receiver.ch)) / receiverBufferSize - capReceiveChannelUsage.WithLabelValues(k.capId, k.donId).Set(receiverQueueUsage) + capReceiveChannelUsage.WithLabelValues(k.capId, fmt.Sprint(k.donId)).Set(receiverQueueUsage) select { case receiver.ch <- body: default: diff --git a/core/capabilities/remote/target/client_test.go b/core/capabilities/remote/target/client_test.go index aa4a645df9..6d26b51b8a 100644 --- a/core/capabilities/remote/target/client_test.go +++ b/core/capabilities/remote/target/client_test.go @@ -130,7 +130,7 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo } capDonInfo := commoncap.DON{ - ID: "capability-don", + ID: 1, Members: capabilityPeers, F: capabilityDonF, } @@ -149,7 +149,7 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo workflowDonInfo := commoncap.DON{ Members: workflowPeers, - ID: "workflow-don", + ID: 2, } broker := newTestAsyncMessageBroker(t, 100) @@ -259,7 +259,7 @@ func (t *clientTestServer) Receive(_ context.Context, msg *remotetypes.MessageBo for receiver := range t.messageIDToSenders[messageID] { var responseMsg = &remotetypes.MessageBody{ CapabilityId: "cap_id@1.0.0", - CapabilityDonId: "capability-don", + CapabilityDonId: 1, CallerDonId: t.workflowDonInfo.ID, Method: remotetypes.MethodExecute, MessageId: []byte(messageID), diff --git a/core/capabilities/remote/target/endtoend_test.go b/core/capabilities/remote/target/endtoend_test.go index f7cc9e04bf..c01b8d99a4 100644 --- a/core/capabilities/remote/target/endtoend_test.go +++ b/core/capabilities/remote/target/endtoend_test.go @@ -191,7 +191,7 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta require.NoError(t, capabilityPeerID.UnmarshalText([]byte(NewPeerID()))) capDonInfo := commoncap.DON{ - ID: "capability-don", + ID: 2, Members: capabilityPeers, F: capabilityDonF, } @@ -212,13 +212,13 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta workflowDonInfo := commoncap.DON{ Members: workflowPeers, - ID: "workflow-don", + ID: 1, F: workflowDonF, } broker := newTestAsyncMessageBroker(t, 1000) - workflowDONs := map[string]commoncap.DON{ + workflowDONs := map[uint32]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } @@ -380,10 +380,10 @@ func (t *nodeDispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.Messa return nil } -func (t *nodeDispatcher) SetReceiver(capabilityId string, donId string, receiver remotetypes.Receiver) error { +func (t *nodeDispatcher) SetReceiver(capabilityId string, donId uint32, receiver remotetypes.Receiver) error { return nil } -func (t *nodeDispatcher) RemoveReceiver(capabilityId string, donId string) {} +func (t *nodeDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} type abstractTestCapability struct { } diff --git a/core/capabilities/remote/target/request/client_request_test.go b/core/capabilities/remote/target/request/client_request_test.go index 52e324a654..c20c24a550 100644 --- a/core/capabilities/remote/target/request/client_request_test.go +++ b/core/capabilities/remote/target/request/client_request_test.go @@ -30,7 +30,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { } capDonInfo := commoncap.DON{ - ID: "capability-don", + ID: 1, Members: capabilityPeers, F: 1, } @@ -50,7 +50,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { workflowDonInfo := commoncap.DON{ Members: workflowPeers, - ID: "workflow-don", + ID: 2, } executeInputs, err := values.NewMap( @@ -311,11 +311,11 @@ type clientRequestTestDispatcher struct { msgs chan *types.MessageBody } -func (t *clientRequestTestDispatcher) SetReceiver(capabilityId string, donId string, receiver types.Receiver) error { +func (t *clientRequestTestDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { return nil } -func (t *clientRequestTestDispatcher) RemoveReceiver(capabilityId string, donId string) {} +func (t *clientRequestTestDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} func (t *clientRequestTestDispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { t.msgs <- msgBody diff --git a/core/capabilities/remote/target/request/server_request.go b/core/capabilities/remote/target/request/server_request.go index bb84fda4ac..25d88d2192 100644 --- a/core/capabilities/remote/target/request/server_request.go +++ b/core/capabilities/remote/target/request/server_request.go @@ -27,7 +27,7 @@ type ServerRequest struct { capabilityPeerId p2ptypes.PeerID capabilityID string - capabilityDonID string + capabilityDonID uint32 dispatcher types.Dispatcher @@ -47,7 +47,7 @@ type ServerRequest struct { lggr logger.Logger } -func NewServerRequest(capability capabilities.TargetCapability, capabilityID string, capabilityDonID string, capabilityPeerId p2ptypes.PeerID, +func NewServerRequest(capability capabilities.TargetCapability, capabilityID string, capabilityDonID uint32, capabilityPeerId p2ptypes.PeerID, callingDon commoncap.DON, requestMessageID string, dispatcher types.Dispatcher, requestTimeout time.Duration, lggr logger.Logger) *ServerRequest { return &ServerRequest{ diff --git a/core/capabilities/remote/target/request/server_request_test.go b/core/capabilities/remote/target/request/server_request_test.go index d5ed471c95..053cba7064 100644 --- a/core/capabilities/remote/target/request/server_request_test.go +++ b/core/capabilities/remote/target/request/server_request_test.go @@ -33,7 +33,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { callingDon := commoncap.DON{ Members: workflowPeers, - ID: "workflow-don", + ID: 1, F: 1, } @@ -58,7 +58,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { require.NoError(t, err) t.Run("Send duplicate message", func(t *testing.T) { - req := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", + req := request.NewServerRequest(capability, "capabilityID", 2, capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) @@ -68,7 +68,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { }) t.Run("Send message with non calling don peer", func(t *testing.T) { - req := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", + req := request.NewServerRequest(capability, "capabilityID", 2, capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) @@ -81,8 +81,8 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { Receiver: capabilityPeerID[:], MessageId: []byte("workflowID" + "workflowExecutionID"), CapabilityId: "capabilityID", - CapabilityDonId: "capabilityDonID", - CallerDonId: "workflow-don", + CapabilityDonId: 2, + CallerDonId: 1, Method: types.MethodExecute, Payload: rawRequest, }) @@ -91,7 +91,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { }) t.Run("Send message invalid payload", func(t *testing.T) { - req := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", + req := request.NewServerRequest(capability, "capabilityID", 2, capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) @@ -103,8 +103,8 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { Receiver: capabilityPeerID[:], MessageId: []byte("workflowID" + "workflowExecutionID"), CapabilityId: "capabilityID", - CapabilityDonId: "capabilityDonID", - CallerDonId: "workflow-don", + CapabilityDonId: 2, + CallerDonId: 1, Method: types.MethodExecute, Payload: append(rawRequest, []byte("asdf")...), }) @@ -116,7 +116,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { t.Run("Send second valid request when capability errors", func(t *testing.T) { dispatcher := &testDispatcher{} - req := request.NewServerRequest(TestErrorCapability{}, "capabilityID", "capabilityDonID", + req := request.NewServerRequest(TestErrorCapability{}, "capabilityID", 2, capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) @@ -128,8 +128,8 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { Receiver: capabilityPeerID[:], MessageId: []byte("workflowID" + "workflowExecutionID"), CapabilityId: "capabilityID", - CapabilityDonId: "capabilityDonID", - CallerDonId: "workflow-don", + CapabilityDonId: 2, + CallerDonId: 1, Method: types.MethodExecute, Payload: rawRequest, }) @@ -143,7 +143,7 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { t.Run("Send second valid request", func(t *testing.T) { dispatcher := &testDispatcher{} - request := request.NewServerRequest(capability, "capabilityID", "capabilityDonID", + request := request.NewServerRequest(capability, "capabilityID", 2, capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) err := sendValidRequest(request, workflowPeers, capabilityPeerID, rawRequest) @@ -155,8 +155,8 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { Receiver: capabilityPeerID[:], MessageId: []byte("workflowID" + "workflowExecutionID"), CapabilityId: "capabilityID", - CapabilityDonId: "capabilityDonID", - CallerDonId: "workflow-don", + CapabilityDonId: 2, + CallerDonId: 1, Method: types.MethodExecute, Payload: rawRequest, }) @@ -179,8 +179,8 @@ func sendValidRequest(request serverRequest, workflowPeers []p2ptypes.PeerID, ca Receiver: capabilityPeerID[:], MessageId: []byte("workflowID" + "workflowExecutionID"), CapabilityId: "capabilityID", - CapabilityDonId: "capabilityDonID", - CallerDonId: "workflow-don", + CapabilityDonId: 2, + CallerDonId: 1, Method: types.MethodExecute, Payload: rawRequest, }) @@ -190,11 +190,11 @@ type testDispatcher struct { msgs []*types.MessageBody } -func (t *testDispatcher) SetReceiver(capabilityId string, donId string, receiver types.Receiver) error { +func (t *testDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { return nil } -func (t *testDispatcher) RemoveReceiver(capabilityId string, donId string) {} +func (t *testDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} func (t *testDispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { t.msgs = append(t.msgs, msgBody) diff --git a/core/capabilities/remote/target/server.go b/core/capabilities/remote/target/server.go index a918dd9170..1453cfc377 100644 --- a/core/capabilities/remote/target/server.go +++ b/core/capabilities/remote/target/server.go @@ -29,7 +29,7 @@ type server struct { underlying commoncap.TargetCapability capInfo commoncap.CapabilityInfo localDonInfo commoncap.DON - workflowDONs map[string]commoncap.DON + workflowDONs map[uint32]commoncap.DON dispatcher types.Dispatcher requestIDToRequest map[string]*request.ServerRequest @@ -44,7 +44,7 @@ var _ types.Receiver = &server{} var _ services.Service = &server{} func NewServer(peerID p2ptypes.PeerID, underlying commoncap.TargetCapability, capInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, - workflowDONs map[string]commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration, lggr logger.Logger) *server { + workflowDONs map[uint32]commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration, lggr logger.Logger) *server { return &server{ underlying: underlying, peerID: peerID, diff --git a/core/capabilities/remote/target/server_test.go b/core/capabilities/remote/target/server_test.go index 3c12ce813d..a5aa45efd0 100644 --- a/core/capabilities/remote/target/server_test.go +++ b/core/capabilities/remote/target/server_test.go @@ -112,7 +112,7 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, } capDonInfo := commoncap.DON{ - ID: "capability-don", + ID: 1, Members: capabilityPeers, F: capabilityDonF, } @@ -131,7 +131,7 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, workflowDonInfo := commoncap.DON{ Members: workflowPeers, - ID: "workflow-don", + ID: 2, F: workflowDonF, } @@ -141,7 +141,7 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, require.NoError(t, err) srvcs = append(srvcs, broker) - workflowDONs := map[string]commoncap.DON{ + workflowDONs := map[uint32]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } @@ -219,8 +219,8 @@ func (r *serverTestClient) Execute(ctx context.Context, req commoncap.Capability for _, node := range r.capabilityDonInfo.Members { message := &remotetypes.MessageBody{ CapabilityId: "capability-id", - CapabilityDonId: "capability-don", - CallerDonId: "workflow-don", + CapabilityDonId: 1, + CallerDonId: 2, Method: remotetypes.MethodExecute, Payload: rawRequest, MessageId: []byte(messageID), diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index 9e7fc89352..d559dc36d4 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -25,7 +25,7 @@ type triggerPublisher struct { underlying commoncap.TriggerCapability capInfo commoncap.CapabilityInfo capDonInfo commoncap.DON - workflowDONs map[string]commoncap.DON + workflowDONs map[uint32]commoncap.DON dispatcher types.Dispatcher messageCache *messageCache[registrationKey, p2ptypes.PeerID] registrations map[registrationKey]*pubRegState @@ -36,7 +36,7 @@ type triggerPublisher struct { } type registrationKey struct { - callerDonId string + callerDonId uint32 workflowId string } @@ -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[string]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *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 { config.ApplyDefaults() return &triggerPublisher{ config: config, diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index db792fb506..ec38b962ce 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -29,12 +29,12 @@ func TestTriggerPublisher_Register(t *testing.T) { p2 := p2ptypes.PeerID{} require.NoError(t, p2.UnmarshalText([]byte(peerID2))) capDonInfo := commoncap.DON{ - ID: "capability-don", + ID: 1, Members: []p2ptypes.PeerID{p1}, F: 0, } workflowDonInfo := commoncap.DON{ - ID: "workflow-don", + ID: 2, Members: []p2ptypes.PeerID{p2}, F: 0, } @@ -46,7 +46,7 @@ func TestTriggerPublisher_Register(t *testing.T) { MinResponsesToAggregate: 1, MessageExpiryMs: 100_000, } - workflowDONs := map[string]commoncap.DON{ + workflowDONs := map[uint32]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } underlying := &testTrigger{ diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index 4750430951..782b29d41f 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -41,12 +41,12 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { p2 := p2ptypes.PeerID{} require.NoError(t, p2.UnmarshalText([]byte(peerID2))) capDonInfo := commoncap.DON{ - ID: "capability-don", + ID: 1, Members: []p2ptypes.PeerID{p1}, F: 0, } workflowDonInfo := commoncap.DON{ - ID: "workflow-don", + ID: 2, Members: []p2ptypes.PeerID{p2}, F: 0, } diff --git a/core/capabilities/remote/types/messages.pb.go b/core/capabilities/remote/types/messages.pb.go index 0e51b39599..d1b86d9feb 100644 --- a/core/capabilities/remote/types/messages.pb.go +++ b/core/capabilities/remote/types/messages.pb.go @@ -138,24 +138,24 @@ type MessageBody struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - Receiver []byte `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` - Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - MessageId []byte `protobuf:"bytes,5,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` // scoped to sender - CapabilityId string `protobuf:"bytes,6,opt,name=capability_id,json=capabilityId,proto3" json:"capability_id,omitempty"` - CapabilityDonId string `protobuf:"bytes,7,opt,name=capability_don_id,json=capabilityDonId,proto3" json:"capability_don_id,omitempty"` - CallerDonId string `protobuf:"bytes,8,opt,name=caller_don_id,json=callerDonId,proto3" json:"caller_don_id,omitempty"` - Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"` - Error Error `protobuf:"varint,10,opt,name=error,proto3,enum=remote.Error" json:"error,omitempty"` - ErrorMsg string `protobuf:"bytes,11,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"` + Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + Receiver []byte `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` + Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + MessageId []byte `protobuf:"bytes,5,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` // scoped to sender + CapabilityId string `protobuf:"bytes,6,opt,name=capability_id,json=capabilityId,proto3" json:"capability_id,omitempty"` + Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"` + Error Error `protobuf:"varint,10,opt,name=error,proto3,enum=remote.Error" json:"error,omitempty"` + ErrorMsg string `protobuf:"bytes,11,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"` // payload contains a CapabilityRequest or CapabilityResponse Payload []byte `protobuf:"bytes,12,opt,name=payload,proto3" json:"payload,omitempty"` // Types that are assignable to Metadata: // // *MessageBody_TriggerRegistrationMetadata // *MessageBody_TriggerEventMetadata - Metadata isMessageBody_Metadata `protobuf_oneof:"metadata"` + Metadata isMessageBody_Metadata `protobuf_oneof:"metadata"` + CapabilityDonId uint32 `protobuf:"varint,15,opt,name=capability_don_id,json=capabilityDonId,proto3" json:"capability_don_id,omitempty"` + CallerDonId uint32 `protobuf:"varint,16,opt,name=caller_don_id,json=callerDonId,proto3" json:"caller_don_id,omitempty"` } func (x *MessageBody) Reset() { @@ -232,20 +232,6 @@ func (x *MessageBody) GetCapabilityId() string { return "" } -func (x *MessageBody) GetCapabilityDonId() string { - if x != nil { - return x.CapabilityDonId - } - return "" -} - -func (x *MessageBody) GetCallerDonId() string { - if x != nil { - return x.CallerDonId - } - return "" -} - func (x *MessageBody) GetMethod() string { if x != nil { return x.Method @@ -295,6 +281,20 @@ func (x *MessageBody) GetTriggerEventMetadata() *TriggerEventMetadata { return nil } +func (x *MessageBody) GetCapabilityDonId() uint32 { + if x != nil { + return x.CapabilityDonId + } + return 0 +} + +func (x *MessageBody) GetCallerDonId() uint32 { + if x != nil { + return x.CallerDonId + } + return 0 +} + type isMessageBody_Metadata interface { isMessageBody_Metadata() } @@ -494,7 +494,7 @@ var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{ 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x22, 0xcd, 0x04, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x62, 0x6f, 0x64, 0x79, 0x22, 0xd9, 0x04, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, @@ -506,12 +506,7 @@ var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x5f, 0x64, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x44, - 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x09, + 0x74, 0x79, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x23, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, @@ -530,44 +525,50 @@ var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x14, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x22, 0x52, 0x0a, 0x1b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x63, 0x0a, 0x14, 0x54, 0x72, 0x69, 0x67, - 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x28, 0x0a, 0x10, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x69, 0x64, 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, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x61, 0x70, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x64, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x61, 0x6c, + 0x6c, 0x65, 0x72, 0x44, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, + 0x22, 0x52, 0x0a, 0x1b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x33, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, + 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x13, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x49, 0x64, 0x22, 0x63, 0x0a, 0x14, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x10, + 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 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, } var ( diff --git a/core/capabilities/remote/types/messages.proto b/core/capabilities/remote/types/messages.proto index a576e0e5fa..4855892f9f 100644 --- a/core/capabilities/remote/types/messages.proto +++ b/core/capabilities/remote/types/messages.proto @@ -19,14 +19,13 @@ message Message { } message MessageBody { + reserved 7, 8; uint32 version = 1; bytes sender = 2; bytes receiver = 3; int64 timestamp = 4; bytes message_id = 5; // scoped to sender string capability_id = 6; - string capability_don_id = 7; - string caller_don_id = 8; string method = 9; Error error = 10; string errorMsg = 11; @@ -38,6 +37,8 @@ message MessageBody { TriggerEventMetadata trigger_event_metadata = 14; } + uint32 capability_don_id = 15; + uint32 caller_don_id = 16; } message TriggerRegistrationMetadata { diff --git a/core/capabilities/remote/types/mocks/dispatcher.go b/core/capabilities/remote/types/mocks/dispatcher.go index f36515f4fe..35905dbd0a 100644 --- a/core/capabilities/remote/types/mocks/dispatcher.go +++ b/core/capabilities/remote/types/mocks/dispatcher.go @@ -14,7 +14,7 @@ type Dispatcher struct { } // RemoveReceiver provides a mock function with given fields: capabilityId, donId -func (_m *Dispatcher) RemoveReceiver(capabilityId string, donId string) { +func (_m *Dispatcher) RemoveReceiver(capabilityId string, donId uint32) { _m.Called(capabilityId, donId) } @@ -37,7 +37,7 @@ func (_m *Dispatcher) Send(peerID ragep2ptypes.PeerID, msgBody *types.MessageBod } // SetReceiver provides a mock function with given fields: capabilityId, donId, receiver -func (_m *Dispatcher) SetReceiver(capabilityId string, donId string, receiver types.Receiver) error { +func (_m *Dispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { ret := _m.Called(capabilityId, donId, receiver) if len(ret) == 0 { @@ -45,7 +45,7 @@ func (_m *Dispatcher) SetReceiver(capabilityId string, donId string, receiver ty } var r0 error - if rf, ok := ret.Get(0).(func(string, string, types.Receiver) error); ok { + if rf, ok := ret.Get(0).(func(string, uint32, types.Receiver) error); ok { r0 = rf(capabilityId, donId, receiver) } else { r0 = ret.Error(0) diff --git a/core/capabilities/remote/types/types.go b/core/capabilities/remote/types/types.go index 9c9cf67aa1..1f2527b622 100644 --- a/core/capabilities/remote/types/types.go +++ b/core/capabilities/remote/types/types.go @@ -20,8 +20,8 @@ const ( //go:generate mockery --quiet --name Dispatcher --output ./mocks/ --case=underscore type Dispatcher interface { - SetReceiver(capabilityId string, donId string, receiver Receiver) error - RemoveReceiver(capabilityId string, donId string) + 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/remote/utils_test.go b/core/capabilities/remote/utils_test.go index 0dd91696fb..8bebf71fb6 100644 --- a/core/capabilities/remote/utils_test.go +++ b/core/capabilities/remote/utils_test.go @@ -22,7 +22,7 @@ import ( const ( capId1 = "cap1" capId2 = "cap2" - donId1 = "donA" + donId1 = uint32(1) payload1 = "hello world" payload2 = "goodbye world" ) @@ -58,7 +58,7 @@ func newKeyPair(t *testing.T) (ed25519.PrivateKey, ragetypes.PeerID) { return privKey, peerID } -func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderId p2ptypes.PeerID, receiverId p2ptypes.PeerID, capabilityId string, donId string, payload []byte) p2ptypes.Message { +func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderId p2ptypes.PeerID, receiverId p2ptypes.PeerID, capabilityId string, donId uint32, payload []byte) p2ptypes.Message { body := remotetypes.MessageBody{ Sender: senderId[:], Receiver: receiverId[:], diff --git a/core/capabilities/transmission/local_target_capability.go b/core/capabilities/transmission/local_target_capability.go index 83b5d57613..1240d3a0e7 100644 --- a/core/capabilities/transmission/local_target_capability.go +++ b/core/capabilities/transmission/local_target_capability.go @@ -28,7 +28,7 @@ func NewLocalTargetCapability(lggr logger.Logger, capabilityID string, localDON } func (l *LocalTargetCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { - if l.localNode.PeerID == nil || l.localNode.WorkflowDON.ID == "" { + if l.localNode.PeerID == nil || l.localNode.WorkflowDON.ID == 0 { l.lggr.Debugf("empty DON info, executing immediately") return l.TargetCapability.Execute(ctx, req) } diff --git a/core/capabilities/transmission/local_target_capability_test.go b/core/capabilities/transmission/local_target_capability_test.go index d1ac9b0ead..93bf708cce 100644 --- a/core/capabilities/transmission/local_target_capability_test.go +++ b/core/capabilities/transmission/local_target_capability_test.go @@ -134,7 +134,7 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { } localDON := capabilities.Node{ WorkflowDON: capabilities.DON{ - ID: "1", + ID: 1, Members: ids, }, PeerID: &ids[tc.position], diff --git a/core/scripts/go.mod b/core/scripts/go.mod index b7f5b9ab60..4c813d1b5a 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 196c76cdf3..ed54204e31 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1212,8 +1212,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.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/services/relay/evm/cap_encoder.go b/core/services/relay/evm/cap_encoder.go index ef78cb07b4..790114e4c0 100644 --- a/core/services/relay/evm/cap_encoder.go +++ b/core/services/relay/evm/cap_encoder.go @@ -104,9 +104,9 @@ func prependMetadataFields(meta consensustypes.Metadata, userPayload []byte) ([] result = append(result, tsBytes...) // 4. DON ID (4 bytes) - if result, err = decodeAndAppend(meta.DONID, 4, result, "DONID"); err != nil { - return nil, err - } + donIDBytes := make([]byte, 4) + binary.BigEndian.PutUint32(donIDBytes, meta.DONID) + result = append(result, donIDBytes...) // 5. DON config version (4 bytes) cfgVersionBytes := make([]byte, 4) diff --git a/core/services/relay/evm/cap_encoder_test.go b/core/services/relay/evm/cap_encoder_test.go index b56d3828c4..d290a7fd2b 100644 --- a/core/services/relay/evm/cap_encoder_test.go +++ b/core/services/relay/evm/cap_encoder_test.go @@ -20,7 +20,8 @@ var ( workflowID = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" workflowName = "aabbccddeeaabbccddee" - donID = "00010203" + donID = uint32(2) + donIDHex = "00000002" executionID = "8d4e66421db647dd916d3ec28d56188c8d7dae5f808e03d03339ed2562f13bb0" workflowOwnerID = "0000000000000000000000000000000000000000" reportID = "9988" @@ -217,7 +218,7 @@ func TestEVMEncoder_InvalidIDs(t *testing.T) { } func getHexMetadata() string { - return "01" + executionID + timestampHex + donID + configVersionHex + workflowID + workflowName + workflowOwnerID + reportID + return "01" + executionID + timestampHex + donIDHex + configVersionHex + workflowID + workflowName + workflowOwnerID + reportID } func getMetadata(cid string) consensustypes.Metadata { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 2692b53f5e..54d79697d8 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -329,10 +329,11 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig triggerRegRequest := capabilities.CapabilityRequest{ Metadata: capabilities.RequestMetadata{ - WorkflowID: e.workflow.id, - WorkflowDonID: e.localNode.WorkflowDON.ID, - WorkflowName: e.workflow.name, - WorkflowOwner: e.workflow.owner, + WorkflowID: e.workflow.id, + WorkflowDonID: e.localNode.WorkflowDON.ID, + WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, + WorkflowName: e.workflow.name, + WorkflowOwner: e.workflow.owner, }, Config: tc, Inputs: triggerInputs, @@ -705,11 +706,12 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, Inputs: inputsMap, Config: step.config, Metadata: capabilities.RequestMetadata{ - WorkflowID: msg.state.WorkflowID, - WorkflowExecutionID: msg.state.ExecutionID, - WorkflowOwner: e.workflow.owner, - WorkflowName: e.workflow.name, - WorkflowDonID: e.localNode.WorkflowDON.ID, + WorkflowID: msg.state.WorkflowID, + WorkflowExecutionID: msg.state.ExecutionID, + WorkflowOwner: e.workflow.owner, + WorkflowName: e.workflow.name, + WorkflowDonID: e.localNode.WorkflowDON.ID, + WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, }, } @@ -732,10 +734,11 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, tr } deregRequest := capabilities.CapabilityRequest{ Metadata: capabilities.RequestMetadata{ - WorkflowID: e.workflow.id, - WorkflowDonID: e.localNode.WorkflowDON.ID, - WorkflowName: e.workflow.name, - WorkflowOwner: e.workflow.owner, + WorkflowID: e.workflow.id, + WorkflowDonID: e.localNode.WorkflowDON.ID, + WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, + WorkflowName: e.workflow.name, + WorkflowOwner: e.workflow.owner, }, Inputs: triggerInputs, Config: t.config, diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 6146d1e13d..2c4129dbaf 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -114,7 +114,7 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...fun GetLocalNode: func(ctx context.Context) (capabilities.Node, error) { return capabilities.Node{ WorkflowDON: capabilities.DON{ - ID: "00010203", + ID: 1, }, PeerID: &peerID, }, nil @@ -783,7 +783,7 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { node := capabilities.Node{ PeerID: &peerID, WorkflowDON: capabilities.DON{ - ID: "1", + ID: 1, }, } retryCount := 0 diff --git a/go.mod b/go.mod index 510540ab0e..5ac40c3255 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 diff --git a/go.sum b/go.sum index 75e9455326..d636d2ee77 100644 --- a/go.sum +++ b/go.sum @@ -1169,8 +1169,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.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 897e51240d..76ead3215f 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -28,7 +28,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 5009b6ea85..e438152975 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1513,8 +1513,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.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index e7b879b6a3..101f8a63f2 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.1.7-0.20240701095149-7c11e2c2ce36 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 6b770542b9..3de27ee9cf 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1503,8 +1503,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.1.7-0.20240701095149-7c11e2c2ce36 h1:x9WPqwSWTZXlUPxZUIHIQIjhL1l6dq5KEiB9jIP+KLs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240701095149-7c11e2c2ce36/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From 3a96fa0567ca1b6c63eaf100e1efe1a84a1e0ead Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Tue, 2 Jul 2024 12:36:54 -0500 Subject: [PATCH 41/61] .github/CODEOWNERS: add releng and foundations to go.mod (#13747) --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fbaeeef27f..61e66baf4f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -111,8 +111,8 @@ contracts/scripts/requirements.txt @smartcontractkit/prodsec-public .nvmrc @smartcontractkit/prodsec-public contracts/package.json @smartcontractkit/prodsec-public contracts/pnpm.lock @smartcontractkit/prodsec-public -go.mod @smartcontractkit/prodsec-public -go.sum @smartcontractkit/prodsec-public +go.mod @smartcontractkit/prodsec-public @smartcontractkit/releng @smartcontractkit/foundations +go.sum @smartcontractkit/prodsec-public @smartcontractkit/releng @smartcontractkit/foundations integration-tests/go.mod @smartcontractkit/prodsec-public integration-tests/go.sum @smartcontractkit/prodsec-public flake.nix @smartcontractkit/prodsec-public From 4b19e37553ecf60c9d98209bc29b4079ae64cbe3 Mon Sep 17 00:00:00 2001 From: Lei Date: Tue, 2 Jul 2024 10:43:31 -0700 Subject: [PATCH 42/61] support native token (#13714) * support native token * split the tests and add mercury related tests --- .changeset/shaggy-bananas-do.md | 5 + integration-tests/actions/actions.go | 2 +- .../actions/automation_ocr_helpers.go | 15 ++- .../actions/automationv2/actions.go | 11 +- integration-tests/actions/keeper_helpers.go | 113 +++++++++++------- .../chaos/automation_chaos_test.go | 4 +- .../ethereum_contracts_automation.go | 83 +++++++++++++ .../contracts/ethereum_keeper_contracts.go | 2 + .../reorg/automation_reorg_test.go | 2 + integration-tests/smoke/automation_test.go | 58 ++++++--- .../smoke/automation_test.go_test_list.json | 21 +++- integration-tests/smoke/log_poller_test.go | 2 + .../testsetups/keeper_benchmark.go | 2 +- 13 files changed, 245 insertions(+), 75 deletions(-) create mode 100644 .changeset/shaggy-bananas-do.md diff --git a/.changeset/shaggy-bananas-do.md b/.changeset/shaggy-bananas-do.md new file mode 100644 index 0000000000..b4b8b00e37 --- /dev/null +++ b/.changeset/shaggy-bananas-do.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +add native billing in smoke test #added diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index bdca411c1d..2763141a89 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -5,6 +5,7 @@ import ( "context" "crypto/ecdsa" "fmt" + "math" "math/big" "strings" "sync" @@ -40,7 +41,6 @@ import ( gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/test-go/testify/require" - "math" ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index 22220af9d6..9aa9604025 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -274,9 +274,12 @@ func DeployAutoOCRRegistryAndRegistrar( // DeployConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means // that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. -func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") +func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool, isBillingTokenNative bool, wethToken contracts.WETHToken) ([]contracts.KeeperConsumer, []*big.Int) { + // Fund deployers with LINK, no need to do this for Native token + if !isBillingTokenNative { + err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + } upkeeps := DeployKeeperConsumers(t, chainClient, numberOfUpkeeps, isLogTrigger, isMercury) require.Equal(t, numberOfUpkeeps, len(upkeeps), "Number of upkeeps should match") @@ -285,7 +288,7 @@ func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts. upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } upkeepIds := RegisterUpkeepContracts( - t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, + t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, isBillingTokenNative, wethToken, ) require.Equal(t, numberOfUpkeeps, len(upkeepIds), "Number of upkeepIds should match") return upkeeps, upkeepIds @@ -318,7 +321,7 @@ func DeployPerformanceConsumers( for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false, false, nil) return upkeeps, upkeepIds } @@ -344,7 +347,7 @@ func DeployPerformDataCheckerConsumers( for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false, false, nil) return upkeeps, upkeepIds } diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 1ed4bef141..f7d495bda5 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -565,7 +565,8 @@ func (a *AutomationTest) SetConfigOnRegistry() error { } else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_3 { ocrConfig.TypedOnchainConfig23 = a.RegistrySettings.Create23OnchainConfig(a.Registrar.Address(), a.UpkeepPrivilegeManager, a.Registry.ChainModuleAddress(), a.Registry.ReorgProtectionEnabled()) ocrConfig.BillingTokens = []common.Address{ - common.HexToAddress(a.LinkToken.Address()), // TODO add more billing tokens + common.HexToAddress(a.LinkToken.Address()), + common.HexToAddress(a.WETHToken.Address()), } ocrConfig.BillingConfigs = []i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23BillingConfig{ @@ -577,6 +578,14 @@ func (a *AutomationTest) SetConfigOnRegistry() error { FallbackPrice: big.NewInt(1000), MinSpend: big.NewInt(200), }, + { + GasFeePPB: 100, + FlatFeeMilliCents: big.NewInt(500), + PriceFeed: common.HexToAddress(a.EthUSDFeed.Address()), // ETH/USD feed and LINK/USD feed are the same + Decimals: 18, + FallbackPrice: big.NewInt(1000), + MinSpend: big.NewInt(200), + }, } } err = a.Registry.SetConfigTypeSafe(ocrConfig) diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 7f02f54c75..ee1662cc18 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -8,6 +8,7 @@ import ( "strconv" "testing" + "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" "github.com/pkg/errors" "github.com/smartcontractkit/seth" @@ -115,7 +116,7 @@ func DeployKeeperContracts( } registrar := DeployKeeperRegistrar(t, client, registryVersion, linkToken, registrarSettings, registry) - upkeeps, upkeepIds := DeployConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false) + upkeeps, upkeepIds := DeployConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false, false, nil) return registry, registrar, upkeeps, upkeepIds } @@ -178,7 +179,7 @@ func DeployPerformanceKeeperContracts( upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false, false, nil) return registry, registrar, upkeeps, upkeepIds } @@ -236,7 +237,7 @@ func DeployPerformDataCheckerContracts( upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false, false, nil) return registry, registrar, upkeeps, upkeepIds } @@ -259,14 +260,14 @@ func DeployKeeperRegistrar( return registrar } -func RegisterUpkeepContracts(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool) []*big.Int { +func RegisterUpkeepContracts(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, fundsForEachUpkeep *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool, isBillingTokenNative bool, wethToken contracts.WETHToken) []*big.Int { checkData := make([][]byte, 0) for i := 0; i < numberOfContracts; i++ { checkData = append(checkData, []byte("0")) } return RegisterUpkeepContractsWithCheckData( - t, client, linkToken, linkFunds, upkeepGasLimit, registry, registrar, - numberOfContracts, upkeepAddresses, checkData, isLogTrigger, isMercury) + t, client, linkToken, fundsForEachUpkeep, upkeepGasLimit, registry, registrar, + numberOfContracts, upkeepAddresses, checkData, isLogTrigger, isMercury, isBillingTokenNative, wethToken) } type upkeepRegistrationResult struct { @@ -284,7 +285,7 @@ type upkeepConfig struct { type UpkeepId = *big.Int -func RegisterUpkeepContractsWithCheckData(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool) []*big.Int { +func RegisterUpkeepContractsWithCheckData(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, fundsForEachUpkeep *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool, isBillingTokenNative bool, wethToken contracts.WETHToken) []*big.Int { l := logging.GetTestLogger(t) concurrency, err := GetAndAssertCorrectConcurrency(client, 1) @@ -300,45 +301,69 @@ func RegisterUpkeepContractsWithCheckData(t *testing.T, client *seth.Client, lin var registerUpkeepFn = func(resultCh chan upkeepRegistrationResult, errorCh chan error, executorNum int, config upkeepConfig) { id := uuid.New().String() keyNum := executorNum + 1 // key 0 is the root key + var tx *types.Transaction + + if isBillingTokenNative { + // register upkeep with native token + tx, err = registrar.RegisterUpkeepFromKey( + keyNum, + fmt.Sprintf("upkeep_%s", id), + []byte("test@mail.com"), + config.address, + upkeepGasLimit, + client.MustGetRootKeyAddress().Hex(), // upkeep Admin + config.data, + fundsForEachUpkeep, + wethToken.Address(), + isLogTrigger, + isMercury, + ) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to register upkeep at %s", id, config.address) + return + } + } else { + // register upkeep with LINK + req, err := registrar.EncodeRegisterRequest( + fmt.Sprintf("upkeep_%s", id), + []byte("test@mail.com"), + config.address, + upkeepGasLimit, + client.MustGetRootKeyAddress().Hex(), // upkeep Admin + config.data, + fundsForEachUpkeep, + 0, + client.Addresses[keyNum].Hex(), + isLogTrigger, + isMercury, + linkToken.Address(), + ) + + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to encode register request for upkeep at %s", id, config.address) + return + } - req, err := registrar.EncodeRegisterRequest( - fmt.Sprintf("upkeep_%s", id), - []byte("test@mail.com"), - config.address, - upkeepGasLimit, - client.MustGetRootKeyAddress().Hex(), // upkeep Admin - config.data, - linkFunds, - 0, - client.Addresses[keyNum].Hex(), - isLogTrigger, - isMercury, - linkToken.Address(), - ) - - if err != nil { - errorCh <- errors.Wrapf(err, "[id: %s] Failed to encode register request for upkeep at %s", id, config.address) - return - } - - balance, err := linkToken.BalanceOf(context.Background(), client.Addresses[keyNum].Hex()) - if err != nil { - errorCh <- errors.Wrapf(err, "[id: %s]Failed to get LINK balance of %s", id, client.Addresses[keyNum].Hex()) - return - } + balance, err := linkToken.BalanceOf(context.Background(), client.Addresses[keyNum].Hex()) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s]Failed to get LINK balance of %s", id, client.Addresses[keyNum].Hex()) + return + } - // not stricly necessary, but helps us to avoid an errorless revert if there is not enough LINK - if balance.Cmp(linkFunds) < 0 { - errorCh <- fmt.Errorf("[id: %s] Not enough LINK balance for %s. Has: %s. Needs: %s", id, client.Addresses[keyNum].Hex(), balance.String(), linkFunds.String()) - return - } + // not strictly necessary, but helps us to avoid an errorless revert if there is not enough LINK + if balance.Cmp(fundsForEachUpkeep) < 0 { + errorCh <- fmt.Errorf("[id: %s] Not enough LINK balance for %s. Has: %s. Needs: %s", id, client.Addresses[keyNum].Hex(), balance.String(), fundsForEachUpkeep.String()) + return + } - tx, err := linkToken.TransferAndCallFromKey(registrar.Address(), linkFunds, req, keyNum) - if err != nil { - errorCh <- errors.Wrapf(err, "[id: %s] Failed to register upkeep at %s", id, config.address) - return + tx, err = linkToken.TransferAndCallFromKey(registrar.Address(), fundsForEachUpkeep, req, keyNum) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to register upkeep at %s", id, config.address) + return + } } + // parse txn to get upkeep ID receipt, err := client.Client.TransactionReceipt(context.Background(), tx.Hash()) if err != nil { errorCh <- errors.Wrapf(err, "[id: %s] Failed to get receipt for upkeep at %s and tx hash %s", id, config.address, tx.Hash()) @@ -405,10 +430,10 @@ func DeployKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts // v2.1 only: Conditional based contract with Mercury enabled keeperConsumerInstance, err = contracts.DeployAutomationStreamsLookupUpkeepConsumerFromKey(client, keyNum, big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range } else if isLogTrigger { - // v2.1 only: Log triggered based contract without Mercury + // v2.1+: Log triggered based contract without Mercury keeperConsumerInstance, err = contracts.DeployAutomationLogTriggerConsumerFromKey(client, keyNum, big.NewInt(1000)) // 1000 block test range } else { - // v2.0 and v2.1: Conditional based contract without Mercury + // v2.0+: Conditional based contract without Mercury keeperConsumerInstance, err = contracts.DeployUpkeepCounterFromKey(client, keyNum, big.NewInt(999999), big.NewInt(5)) } @@ -580,7 +605,7 @@ func RegisterNewUpkeeps( err = SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfNewUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - newUpkeepIDs := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false) + newUpkeepIDs := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false, false, nil) return newlyDeployedUpkeeps, newUpkeepIDs } diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index d091522c2c..e14c35ed17 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -286,8 +286,8 @@ func TestAutomationChaos(t *testing.T) { } require.NoError(t, err, "Error setting OCR config") - consumersConditional, upkeepidsConditional := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false) - consumersLogtrigger, upkeepidsLogtrigger := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false) + 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) consumers := append(consumersConditional, consumersLogtrigger...) upkeepIDs := append(upkeepidsConditional, upkeepidsLogtrigger...) diff --git a/integration-tests/contracts/ethereum_contracts_automation.go b/integration-tests/contracts/ethereum_contracts_automation.go index c2c7576e0f..bd0e1aafc8 100644 --- a/integration-tests/contracts/ethereum_contracts_automation.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -1799,6 +1799,87 @@ func (v *EthereumKeeperRegistrar) Fund(_ *big.Float) error { panic("do not use this function, use actions.SendFunds instead") } +// register Upkeep with native token, only available from v2.3 +func (v *EthereumKeeperRegistrar) RegisterUpkeepFromKey(keyNum int, name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, wethTokenAddr string, isLogTrigger bool, isMercury bool) (*types.Transaction, error) { + if v.registrar23 == nil { + return nil, fmt.Errorf("RegisterUpkeepFromKey with native token is only supported in registrar version v2.3") + } + + registrarABI = cltypes.MustGetABI(registrar23.AutomationRegistrarABI) + txOpts := v.client.NewTXKeyOpts(keyNum, seth.WithValue(amount)) + + if isLogTrigger { + var topic0InBytes [32]byte + // bytes representation of 0x0000000000000000000000000000000000000000000000000000000000000000 + bytes0 := [32]byte{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + } + if isMercury { + // bytes representation of 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd + topic0InBytes = [32]byte{209, 255, 233, 228, 85, 129, 193, 29, 125, 159, 46, 213, 247, 82, 23, 205, 75, 233, 248, 183, 238, 230, 175, 15, 109, 3, 244, 109, 229, 57, 86, 205} + } else { + // bytes representation of 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d + topic0InBytes = [32]byte{ + 61, 83, 163, 149, 80, 224, 70, 136, + 6, 88, 39, 243, 187, 134, 88, 76, + 176, 7, 171, 158, 188, 167, 235, + 213, 40, 231, 48, 28, 156, 49, 235, 93, + } + } + + logTriggerConfigStruct := acutils.IAutomationV21PlusCommonLogTriggerConfig{ + ContractAddress: common.HexToAddress(upkeepAddr), + FilterSelector: 0, + Topic0: topic0InBytes, + Topic1: bytes0, + Topic2: bytes0, + Topic3: bytes0, + } + encodedLogTriggerConfig, err := compatibleUtils.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct) + if err != nil { + return nil, err + } + + params := registrar23.AutomationRegistrar23RegistrationParams{ + UpkeepContract: common.HexToAddress(upkeepAddr), + Amount: amount, + AdminAddress: common.HexToAddress(adminAddr), + GasLimit: gasLimit, + TriggerType: uint8(1), // trigger type + BillingToken: common.HexToAddress(wethTokenAddr), // native + Name: name, + EncryptedEmail: email, + CheckData: checkData, + TriggerConfig: encodedLogTriggerConfig, // log trigger upkeep + OffchainConfig: []byte{}, + } + + decodedTx, err := v.client.Decode(v.registrar23.RegisterUpkeep(txOpts, + params, + )) + return decodedTx.Transaction, err + } + + params := registrar23.AutomationRegistrar23RegistrationParams{ + UpkeepContract: common.HexToAddress(upkeepAddr), + Amount: amount, + AdminAddress: common.HexToAddress(adminAddr), + GasLimit: gasLimit, + TriggerType: uint8(0), // trigger type + BillingToken: common.HexToAddress(wethTokenAddr), // native + Name: name, + EncryptedEmail: email, + CheckData: checkData, + TriggerConfig: []byte{}, // conditional upkeep + OffchainConfig: []byte{}, + } + + decodedTx, err := v.client.Decode(v.registrar23.RegisterUpkeep(txOpts, + params, + )) + return decodedTx.Transaction, err +} + // EncodeRegisterRequest encodes register request to call it through link token TransferAndCall func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool, linkTokenAddr string) ([]byte, error) { if v.registrar20 != nil { @@ -2056,9 +2137,11 @@ func DeployKeeperRegistrar(client *seth.Client, registryVersion eth_contracts.Ke billingTokens := []common.Address{ common.HexToAddress(linkAddr), + common.HexToAddress(registrarSettings.WETHTokenAddr), } minRegistrationFees := []*big.Int{ big.NewInt(10), + big.NewInt(10), } data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistrar2_3", *abi, common.FromHex(registrar23.AutomationRegistrarMetaData.Bin), diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 84543627d4..34c78b3fc6 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -27,6 +27,8 @@ type KeeperRegistrar interface { EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool, linkTokenAddr string) ([]byte, error) Fund(ethAmount *big.Float) error + + RegisterUpkeepFromKey(keyNum int, name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, wethTokenAddr string, isLogTrigger bool, isMercury bool) (*types.Transaction, error) } type UpkeepTranscoder interface { diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 5a18bb17c9..2a2350e195 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -229,6 +229,8 @@ func TestAutomationReorg(t *testing.T) { defaultUpkeepGasLimit, isLogTrigger, false, + false, + nil, ) if isLogTrigger { diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 20240351c5..62462d641a 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "strconv" + "strings" "testing" "time" @@ -98,19 +99,25 @@ func TestAutomationBasic(t *testing.T) { func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { t.Parallel() + // native, mercury_v02, mercury_v03 and logtrigger are reserved keywords, use them with caution registryVersions := map[string]ethereum.KeeperRegistryVersion{ - "registry_2_0": ethereum.RegistryVersion_2_0, - "registry_2_1_conditional": ethereum.RegistryVersion_2_1, - "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, - "registry_2_1_with_mercury_v02": ethereum.RegistryVersion_2_1, - "registry_2_1_with_mercury_v03": ethereum.RegistryVersion_2_1, - "registry_2_1_with_logtrigger_and_mercury_v02": ethereum.RegistryVersion_2_1, - "registry_2_2_conditional": ethereum.RegistryVersion_2_2, - "registry_2_2_logtrigger": ethereum.RegistryVersion_2_2, - "registry_2_2_with_mercury_v02": ethereum.RegistryVersion_2_2, - "registry_2_2_with_mercury_v03": ethereum.RegistryVersion_2_2, - "registry_2_2_with_logtrigger_and_mercury_v02": ethereum.RegistryVersion_2_2, - "registry_2_3_conditional": ethereum.RegistryVersion_2_3, + "registry_2_0": ethereum.RegistryVersion_2_0, + "registry_2_1_conditional": ethereum.RegistryVersion_2_1, + "registry_2_1_logtrigger": ethereum.RegistryVersion_2_1, + "registry_2_1_with_mercury_v02": ethereum.RegistryVersion_2_1, + "registry_2_1_with_mercury_v03": ethereum.RegistryVersion_2_1, + "registry_2_1_with_logtrigger_and_mercury_v02": ethereum.RegistryVersion_2_1, + "registry_2_2_conditional": ethereum.RegistryVersion_2_2, + "registry_2_2_logtrigger": ethereum.RegistryVersion_2_2, + "registry_2_2_with_mercury_v02": ethereum.RegistryVersion_2_2, + "registry_2_2_with_mercury_v03": ethereum.RegistryVersion_2_2, + "registry_2_2_with_logtrigger_and_mercury_v02": ethereum.RegistryVersion_2_2, + "registry_2_3_conditional_native": ethereum.RegistryVersion_2_3, + "registry_2_3_conditional_link": ethereum.RegistryVersion_2_3, + "registry_2_3_logtrigger_native": ethereum.RegistryVersion_2_3, + "registry_2_3_logtrigger_link": ethereum.RegistryVersion_2_3, + "registry_2_3_with_mercury_v03_link": ethereum.RegistryVersion_2_3, + "registry_2_3_with_logtrigger_and_mercury_v02_link": ethereum.RegistryVersion_2_3, } for n, rv := range registryVersions { @@ -129,10 +136,11 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { } } - // Use the name to determine if this is a log trigger or mercury - isLogTrigger := name == "registry_2_1_logtrigger" || name == "registry_2_1_with_logtrigger_and_mercury_v02" || name == "registry_2_2_logtrigger" || name == "registry_2_2_with_logtrigger_and_mercury_v02" - isMercuryV02 := name == "registry_2_1_with_mercury_v02" || name == "registry_2_1_with_logtrigger_and_mercury_v02" || name == "registry_2_2_with_mercury_v02" || name == "registry_2_2_with_logtrigger_and_mercury_v02" - isMercuryV03 := name == "registry_2_1_with_mercury_v03" || name == "registry_2_2_with_mercury_v03" + // Use the name to determine if this is a log trigger or mercury or billing token is native + isBillingTokenNative := strings.Contains(name, "native") + isLogTrigger := strings.Contains(name, "logtrigger") + isMercuryV02 := strings.Contains(name, "mercury_v02") + isMercuryV03 := strings.Contains(name, "mercury_v03") isMercury := isMercuryV02 || isMercuryV03 a := setupAutomationTestDocker( @@ -153,6 +161,8 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { automationDefaultUpkeepGasLimit, isLogTrigger, isMercury, + isBillingTokenNative, + a.WETHToken, ) // Do it in two separate loops, so we don't end up setting up one upkeep, but starting the consumer for another one @@ -189,8 +199,6 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) - // TODO Tune this timeout window after stress testing - l.Info().Msg("Waiting 10m for all upkeeps to perform at least 1 upkeep") gom.Eventually(func(g gomega.Gomega) { // Check if the upkeeps are performing multiple times by analyzing their counters for i := 0; i < len(upkeepIDs); i++ { @@ -292,6 +300,8 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { automationDefaultUpkeepGasLimit, true, false, + false, + nil, ) // Start log trigger based upkeeps for all consumers @@ -473,6 +483,8 @@ func TestAutomationAddFunds(t *testing.T) { automationDefaultUpkeepGasLimit, false, false, + false, + nil, ) t.Cleanup(func() { @@ -551,6 +563,8 @@ func TestAutomationPauseUnPause(t *testing.T) { automationDefaultUpkeepGasLimit, false, false, + false, + nil, ) t.Cleanup(func() { @@ -650,6 +664,8 @@ func TestAutomationRegisterUpkeep(t *testing.T) { automationDefaultUpkeepGasLimit, false, false, + false, + nil, ) t.Cleanup(func() { @@ -744,6 +760,8 @@ func TestAutomationPauseRegistry(t *testing.T) { automationDefaultUpkeepGasLimit, false, false, + false, + nil, ) t.Cleanup(func() { @@ -822,6 +840,8 @@ func TestAutomationKeeperNodesDown(t *testing.T) { automationDefaultUpkeepGasLimit, false, false, + false, + nil, ) t.Cleanup(func() { @@ -1235,6 +1255,8 @@ func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { automationDefaultUpkeepGasLimit, false, false, + false, + nil, ) t.Cleanup(func() { diff --git a/integration-tests/smoke/automation_test.go_test_list.json b/integration-tests/smoke/automation_test.go_test_list.json index f0b8a1cb60..1b8477ca28 100644 --- a/integration-tests/smoke/automation_test.go_test_list.json +++ b/integration-tests/smoke/automation_test.go_test_list.json @@ -37,9 +37,26 @@ }, { "name": "TestAutomationBasic", - "nodes": 1, + "nodes": 2, + "run":[ + {"name":"registry_2_3_conditional_native"}, + {"name":"registry_2_3_conditional_link"} + ] + }, + { + "name": "TestAutomationBasic", + "nodes": 2, + "run":[ + {"name":"registry_2_3_logtrigger_native"}, + {"name":"registry_2_3_logtrigger_link"} + ] + }, + { + "name": "TestAutomationBasic", + "nodes": 2, "run":[ - {"name":"registry_2_3_conditional"} + {"name":"registry_2_3_with_mercury_v03_link"}, + {"name":"registry_2_3_with_logtrigger_and_mercury_v02_link"} ] }, { diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index d02daec211..f1a257552a 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -317,6 +317,8 @@ func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfi uint32(2500000), true, false, + false, + nil, ) err = logpoller.AssertUpkeepIdsUniqueness(upkeepIDs) diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index 81f2ce0edf..d50355f39b 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -801,7 +801,7 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { err = actions.DeployMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds) require.NoError(k.t, err, "Sending link funds to deployment addresses shouldn't fail") - upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false) + upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false, false, nil) k.keeperRegistries[index] = registry k.keeperRegistrars[index] = registrar From 595449bf9ed8fe4985d648fc7fdddd150088dfdb Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 2 Jul 2024 13:45:18 -0400 Subject: [PATCH 43/61] Bump chainlink-data-streams to 761f63e7b52700827196b6011401950035317e70 (bid/ask invariant logic on report (#13741) --- 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 4c813d1b5a..6afae7118f 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -275,7 +275,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index ed54204e31..df01c9147a 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1216,8 +1216,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487f github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= diff --git a/go.mod b/go.mod index 5ac40c3255..cbcbc41daf 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba diff --git a/go.sum b/go.sum index d636d2ee77..1d1055fd32 100644 --- a/go.sum +++ b/go.sum @@ -1173,8 +1173,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487f github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 76ead3215f..3d35100d7b 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -379,7 +379,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e438152975..afc07cbe8f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1517,8 +1517,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487f github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 101f8a63f2..26ab9e91f3 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -365,7 +365,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 3de27ee9cf..3a34bc6c0d 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1507,8 +1507,8 @@ github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487f github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527/go.mod h1:KRK7KlAEpmORi+nJgT0vxQVWvlLEBQ6zgzXziZuKvUM= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 h1:MD80ZRCTvxxJ8PBmhtrKoTnky8cVNYrCrIBLVRbrOM0= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917/go.mod h1:jwVxhctE6BgLOSSsVq9wbREpZ8Ev34H+UBxeUhESZRs= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 h1:JkBap2v5AmU4H9LWVDGr6XKnnDwU0OzX4W7u9aq5PQg= From 5bc558f2a38d8b673bb1ab48053d844ff67303f9 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 3 Jul 2024 03:38:02 -0500 Subject: [PATCH 44/61] bump libocr to 063ceef8c42eeadbe94221e55b8892690d36099a (#13746) --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- core/services/ocrcommon/peer_wrapper.go | 4 +++- core/services/relay/evm/functions/offchain_config_digester.go | 2 +- 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, 16 insertions(+), 14 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 6afae7118f..26d5560663 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -27,7 +27,7 @@ require ( github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c + github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e 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 df01c9147a..2e3839561a 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1230,8 +1230,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-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= -github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +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/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/core/services/ocrcommon/peer_wrapper.go b/core/services/ocrcommon/peer_wrapper.go index 762a3d05aa..325311352f 100644 --- a/core/services/ocrcommon/peer_wrapper.go +++ b/core/services/ocrcommon/peer_wrapper.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" + "github.com/smartcontractkit/libocr/networking/rageping" ocrnetworking "github.com/smartcontractkit/libocr/networking" ocr1types "github.com/smartcontractkit/libocr/offchainreporting/types" @@ -135,7 +136,8 @@ func (p *SingletonPeerWrapper) peerConfig() (ocrnetworking.PeerConfig, error) { IncomingMessageBufferSize: config.IncomingMessageBufferSize(), OutgoingMessageBufferSize: config.OutgoingMessageBufferSize(), }, - MetricsRegisterer: prometheus.DefaultRegisterer, + MetricsRegisterer: prometheus.DefaultRegisterer, + LatencyMetricsServiceConfigs: rageping.DefaultConfigs(), } return peerConfig, nil diff --git a/core/services/relay/evm/functions/offchain_config_digester.go b/core/services/relay/evm/functions/offchain_config_digester.go index c53d07e77c..fa8199ec0a 100644 --- a/core/services/relay/evm/functions/offchain_config_digester.go +++ b/core/services/relay/evm/functions/offchain_config_digester.go @@ -17,7 +17,7 @@ import ( var ( _ types.OffchainConfigDigester = &functionsOffchainConfigDigester{} _ evmRelayTypes.RouteUpdateSubscriber = &functionsOffchainConfigDigester{} - FunctionsDigestPrefix = types.ConfigDigestPrefixEVM + FunctionsDigestPrefix = types.ConfigDigestPrefixEVMSimple // In order to support multiple OCR plugins with a single jobspec & OCR2Base contract, each plugin must have a unique config digest. // This is accomplished by overriding the single config digest from the contract with a unique prefix for each plugin via this custom offchain digester & config poller. ThresholdDigestPrefix = types.ConfigDigestPrefix(7) diff --git a/go.mod b/go.mod index cbcbc41daf..6e52bb4e1d 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240701154249-032706dcb7c8 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 - github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c + github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e 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.8.1 diff --git a/go.sum b/go.sum index 1d1055fd32..bbc866e16e 100644 --- a/go.sum +++ b/go.sum @@ -1187,8 +1187,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-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= -github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +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/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 3d35100d7b..e3ad6adfb2 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -34,7 +34,7 @@ require ( github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 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-20240419185742-fd3cab206b2c + github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e github.com/smartcontractkit/seth v1.0.12 github.com/smartcontractkit/wasp v0.4.7 github.com/spf13/cobra v1.8.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index afc07cbe8f..47375e0e9b 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1537,8 +1537,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-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= -github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +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/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 26ab9e91f3..443b67c7f9 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.31.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-20240419185742-fd3cab206b2c + github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e 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 3a34bc6c0d..bb1f41f9be 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1525,8 +1525,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-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= -github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +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/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 d64ba3dafedb21f77e335c056c9a830c5710dba0 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 3 Jul 2024 05:01:59 -0400 Subject: [PATCH 45/61] downgrading wsrpc to v0.7.3 (#13745) * downgrading wsrpc to v0.7.2 * bumping to v0.7.3 --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 6 ++++-- core/services/ocr2/plugins/llo/helpers_test.go | 4 ++-- core/services/ocr2/plugins/mercury/helpers_test.go | 2 +- go.mod | 2 +- go.sum | 6 ++++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 6 ++++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 6 ++++-- 10 files changed, 23 insertions(+), 15 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 26d5560663..723063c4b5 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -281,7 +281,7 @@ require ( github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 + github.com/smartcontractkit/wsrpc v0.7.3 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 2e3839561a..aa1780090f 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -657,6 +657,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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= @@ -1236,8 +1237,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235- 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/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= -github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= +github.com/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= +github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1478,6 +1479,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 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= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= diff --git a/core/services/ocr2/plugins/llo/helpers_test.go b/core/services/ocr2/plugins/llo/helpers_test.go index a29953d5d5..b993ec6dad 100644 --- a/core/services/ocr2/plugins/llo/helpers_test.go +++ b/core/services/ocr2/plugins/llo/helpers_test.go @@ -59,7 +59,7 @@ type request struct { } func (r request) TransmitterID() ocr2types.Account { - return ocr2types.Account(r.pk.String()) + return ocr2types.Account(fmt.Sprintf("%x", r.pk)) } type mercuryServer struct { @@ -114,7 +114,7 @@ func startMercuryServer(t *testing.T, srv *mercuryServer, pubKeys []ed25519.Publ t.Fatalf("[MAIN] failed to listen: %v", err) } serverURL = lis.Addr().String() - s := wsrpc.NewServer(wsrpc.WithCreds(srv.privKey, pubKeys)) + s := wsrpc.NewServer(wsrpc.Creds(srv.privKey, pubKeys)) // Register mercury implementation with the wsrpc server pb.RegisterMercuryServer(s, srv) diff --git a/core/services/ocr2/plugins/mercury/helpers_test.go b/core/services/ocr2/plugins/mercury/helpers_test.go index fbb51557eb..43d709453b 100644 --- a/core/services/ocr2/plugins/mercury/helpers_test.go +++ b/core/services/ocr2/plugins/mercury/helpers_test.go @@ -103,7 +103,7 @@ func startMercuryServer(t *testing.T, srv *mercuryServer, pubKeys []ed25519.Publ t.Fatalf("[MAIN] failed to listen: %v", err) } serverURL = lis.Addr().String() - s := wsrpc.NewServer(wsrpc.WithCreds(srv.privKey, pubKeys)) + s := wsrpc.NewServer(wsrpc.Creds(srv.privKey, pubKeys)) // Register mercury implementation with the wsrpc server pb.RegisterMercuryServer(s, srv) diff --git a/go.mod b/go.mod index 6e52bb4e1d..db79820dfd 100644 --- a/go.mod +++ b/go.mod @@ -82,7 +82,7 @@ require ( github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e 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.8.1 + github.com/smartcontractkit/wsrpc v0.7.3 github.com/spf13/cast v1.6.0 github.com/stretchr/testify v1.9.0 github.com/test-go/testify v1.1.4 diff --git a/go.sum b/go.sum index bbc866e16e..c142992a74 100644 --- a/go.sum +++ b/go.sum @@ -622,6 +622,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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= @@ -1193,8 +1194,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235- 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/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= -github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= +github.com/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= +github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1431,6 +1432,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 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= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index e3ad6adfb2..82b832ed4d 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -385,7 +385,7 @@ require ( github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240625074951-06ab5e670dba // 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 + github.com/smartcontractkit/wsrpc v0.7.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/afero v1.9.5 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 47375e0e9b..fa10b57305 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -820,6 +820,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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= @@ -1547,8 +1548,8 @@ github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:D 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/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= +github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1815,6 +1816,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 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= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 443b67c7f9..4f79098242 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -372,7 +372,7 @@ require ( github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/wsrpc v0.8.1 // indirect + github.com/smartcontractkit/wsrpc v0.7.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/afero v1.9.5 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index bb1f41f9be..81b2b64be2 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -814,6 +814,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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= @@ -1535,8 +1536,8 @@ github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:D 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/smartcontractkit/wsrpc v0.7.3 h1:CKYZfawZShZGfvsQep1F9oBansnFk9ByZPCdTMpLphw= +github.com/smartcontractkit/wsrpc v0.7.3/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1803,6 +1804,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 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= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= From 145fe5e0bd674f7e38d510c6af9c801351d84e94 Mon Sep 17 00:00:00 2001 From: Sneha Agnihotri Date: Wed, 3 Jul 2024 15:21:44 +0530 Subject: [PATCH 46/61] Bump version and update CHANGELOG fore core v2.14.0 Signed-off-by: Sneha Agnihotri --- .changeset/afraid-cups-scream.md | 5 - .changeset/blue-phones-rest.md | 5 - .changeset/chilled-panthers-joke.md | 5 - .changeset/curvy-months-change.md | 5 - .changeset/dull-ants-collect.md | 9 -- .changeset/eleven-buckets-search.md | 5 - .changeset/fair-buttons-judge.md | 5 - .changeset/five-apes-fold.md | 5 - .changeset/funny-snails-shake.md | 5 - .changeset/fuzzy-frogs-live.md | 5 - .changeset/giant-pumpkins-return.md | 5 - .changeset/happy-fans-enjoy.md | 5 - .changeset/healthy-plants-guess.md | 5 - .changeset/lemon-buttons-raise.md | 5 - .changeset/metal-glasses-count.md | 5 - .changeset/ninety-zebras-hammer.md | 5 - .changeset/pink-ants-reply.md | 5 - .changeset/popular-candles-mix.md | 5 - .changeset/pretty-dancers-pull.md | 5 - .changeset/purple-poets-film.md | 5 - .changeset/rare-carpets-cry.md | 5 - .changeset/real-fireants-rule.md | 5 - ...{metal-cars-report.md => red-meals-mix.md} | 0 .changeset/rotten-emus-work.md | 5 - .changeset/shaggy-bananas-do.md | 5 - .changeset/shaggy-ears-share.md | 5 - .changeset/sharp-rabbits-tie.md | 5 - .changeset/shiny-poems-juggle.md | 6 - .changeset/shy-deers-hope.md | 5 - .changeset/sour-pigs-develop.md | 5 - .changeset/stupid-poems-glow.md | 5 - .changeset/tall-walls-agree.md | 5 - .changeset/tall-wombats-deliver.md | 5 - .changeset/ten-falcons-suffer.md | 5 - .changeset/tender-carpets-cry.md | 7 -- .changeset/thick-lemons-beam.md | 5 - .changeset/thick-moles-travel.md | 5 - .changeset/tiny-camels-flow.md | 5 - .changeset/unlucky-pillows-fly.md | 5 - .changeset/warm-cobras-poke.md | 5 - .changeset/wise-wasps-drum.md | 5 - .changeset/young-parrots-peel.md | 5 - CHANGELOG.md | 106 ++++++++++++++++-- package.json | 2 +- 44 files changed, 98 insertions(+), 222 deletions(-) delete mode 100644 .changeset/afraid-cups-scream.md delete mode 100644 .changeset/blue-phones-rest.md delete mode 100644 .changeset/chilled-panthers-joke.md delete mode 100644 .changeset/curvy-months-change.md delete mode 100644 .changeset/dull-ants-collect.md delete mode 100644 .changeset/eleven-buckets-search.md delete mode 100644 .changeset/fair-buttons-judge.md delete mode 100644 .changeset/five-apes-fold.md delete mode 100644 .changeset/funny-snails-shake.md delete mode 100644 .changeset/fuzzy-frogs-live.md delete mode 100644 .changeset/giant-pumpkins-return.md delete mode 100644 .changeset/happy-fans-enjoy.md delete mode 100644 .changeset/healthy-plants-guess.md delete mode 100644 .changeset/lemon-buttons-raise.md delete mode 100644 .changeset/metal-glasses-count.md delete mode 100644 .changeset/ninety-zebras-hammer.md delete mode 100644 .changeset/pink-ants-reply.md delete mode 100644 .changeset/popular-candles-mix.md delete mode 100644 .changeset/pretty-dancers-pull.md delete mode 100644 .changeset/purple-poets-film.md delete mode 100644 .changeset/rare-carpets-cry.md delete mode 100644 .changeset/real-fireants-rule.md rename .changeset/{metal-cars-report.md => red-meals-mix.md} (100%) delete mode 100644 .changeset/rotten-emus-work.md delete mode 100644 .changeset/shaggy-bananas-do.md delete mode 100644 .changeset/shaggy-ears-share.md delete mode 100644 .changeset/sharp-rabbits-tie.md delete mode 100644 .changeset/shiny-poems-juggle.md delete mode 100644 .changeset/shy-deers-hope.md delete mode 100644 .changeset/sour-pigs-develop.md delete mode 100644 .changeset/stupid-poems-glow.md delete mode 100644 .changeset/tall-walls-agree.md delete mode 100644 .changeset/tall-wombats-deliver.md delete mode 100644 .changeset/ten-falcons-suffer.md delete mode 100644 .changeset/tender-carpets-cry.md delete mode 100644 .changeset/thick-lemons-beam.md delete mode 100644 .changeset/thick-moles-travel.md delete mode 100644 .changeset/tiny-camels-flow.md delete mode 100644 .changeset/unlucky-pillows-fly.md delete mode 100644 .changeset/warm-cobras-poke.md delete mode 100644 .changeset/wise-wasps-drum.md delete mode 100644 .changeset/young-parrots-peel.md diff --git a/.changeset/afraid-cups-scream.md b/.changeset/afraid-cups-scream.md deleted file mode 100644 index 37226b8655..0000000000 --- a/.changeset/afraid-cups-scream.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added zkSync L1 GasPrice calculation diff --git a/.changeset/blue-phones-rest.md b/.changeset/blue-phones-rest.md deleted file mode 100644 index 4a427c7835..0000000000 --- a/.changeset/blue-phones-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Use audited version of OCR2Base.sol in OCR3Capability.sol diff --git a/.changeset/chilled-panthers-joke.md b/.changeset/chilled-panthers-joke.md deleted file mode 100644 index 77dc481771..0000000000 --- a/.changeset/chilled-panthers-joke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal bump `chainlink-common` version to commit 6d926be950a6f6ca289a84edad938d4eef2ee337. diff --git a/.changeset/curvy-months-change.md b/.changeset/curvy-months-change.md deleted file mode 100644 index 1a3b1b3ce9..0000000000 --- a/.changeset/curvy-months-change.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Only encode non nil block numbers for eth_call #changed diff --git a/.changeset/dull-ants-collect.md b/.changeset/dull-ants-collect.md deleted file mode 100644 index 78f608e341..0000000000 --- a/.changeset/dull-ants-collect.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"chainlink": patch ---- - -Fixed local finality violation caused by an RPC lagging behind on latest finalized block. - -Added `EVM.FinalizedBlockOffset` and `EVM.NodePool.EnforceRepeatableRead` config options. -With `EnforceRepeatableRead = true`, RPC is considered healthy only if its most recent finalized block is larger or equal to the highest finalized block observed by the Node minus `FinalizedBlockOffset`. -#bugfix diff --git a/.changeset/eleven-buckets-search.md b/.changeset/eleven-buckets-search.md deleted file mode 100644 index 6c68fbcfdc..0000000000 --- a/.changeset/eleven-buckets-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Add Log Poller support to Chain Reader through setting them in config. All filters should be part of the contract wide filter unless an event needs specific polling configuration, which can be set on a per event basis.. diff --git a/.changeset/fair-buttons-judge.md b/.changeset/fair-buttons-judge.md deleted file mode 100644 index 7aacd89787..0000000000 --- a/.changeset/fair-buttons-judge.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Bumped `chainlink-common` package version to commit `1fb0b48758af25d689b6957ebfb76598c9fb27ea`. diff --git a/.changeset/five-apes-fold.md b/.changeset/five-apes-fold.md deleted file mode 100644 index b9f33cbfa1..0000000000 --- a/.changeset/five-apes-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Added a chain writer constructor onto the evm relayer. diff --git a/.changeset/funny-snails-shake.md b/.changeset/funny-snails-shake.md deleted file mode 100644 index dad6c90872..0000000000 --- a/.changeset/funny-snails-shake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added API for products to query a transaction's status in the TXM #internal diff --git a/.changeset/fuzzy-frogs-live.md b/.changeset/fuzzy-frogs-live.md deleted file mode 100644 index 58a9ffd228..0000000000 --- a/.changeset/fuzzy-frogs-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added EVM implementation of GetFeeComponents function for ChainWriter diff --git a/.changeset/giant-pumpkins-return.md b/.changeset/giant-pumpkins-return.md deleted file mode 100644 index c908db198f..0000000000 --- a/.changeset/giant-pumpkins-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal bumped chainlink-common version to commit 1eff5dedc9857ed8811186dd2996603942dc1107 diff --git a/.changeset/happy-fans-enjoy.md b/.changeset/happy-fans-enjoy.md deleted file mode 100644 index a9e878719d..0000000000 --- a/.changeset/happy-fans-enjoy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#db_update ccip capability specs migration diff --git a/.changeset/healthy-plants-guess.md b/.changeset/healthy-plants-guess.md deleted file mode 100644 index 6ec74b5a04..0000000000 --- a/.changeset/healthy-plants-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal removed HistoryDepth to FinalityDepth validation diff --git a/.changeset/lemon-buttons-raise.md b/.changeset/lemon-buttons-raise.md deleted file mode 100644 index 0408383bd0..0000000000 --- a/.changeset/lemon-buttons-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/metal-glasses-count.md b/.changeset/metal-glasses-count.md deleted file mode 100644 index 0408383bd0..0000000000 --- a/.changeset/metal-glasses-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/ninety-zebras-hammer.md b/.changeset/ninety-zebras-hammer.md deleted file mode 100644 index 0408383bd0..0000000000 --- a/.changeset/ninety-zebras-hammer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/pink-ants-reply.md b/.changeset/pink-ants-reply.md deleted file mode 100644 index fab4ef31f7..0000000000 --- a/.changeset/pink-ants-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal remove shared secret from transmission schedule diff --git a/.changeset/popular-candles-mix.md b/.changeset/popular-candles-mix.md deleted file mode 100644 index 4822188582..0000000000 --- a/.changeset/popular-candles-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Clean up workflow engine logging diff --git a/.changeset/pretty-dancers-pull.md b/.changeset/pretty-dancers-pull.md deleted file mode 100644 index af8ec9db0c..0000000000 --- a/.changeset/pretty-dancers-pull.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#changed Expand EVM implementation compatibility pipeline diff --git a/.changeset/purple-poets-film.md b/.changeset/purple-poets-film.md deleted file mode 100644 index cc858c72f0..0000000000 --- a/.changeset/purple-poets-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Implemented the `GetTransactionStatus` method on the EVM implementation of the `ChainWriter`. diff --git a/.changeset/rare-carpets-cry.md b/.changeset/rare-carpets-cry.md deleted file mode 100644 index f096d31885..0000000000 --- a/.changeset/rare-carpets-cry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal capability dispatcher threading and context usage diff --git a/.changeset/real-fireants-rule.md b/.changeset/real-fireants-rule.md deleted file mode 100644 index 4e3e83b484..0000000000 --- a/.changeset/real-fireants-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#changed Added Aptos Keystore to Core. This includes Aptos Key which uses ED25519, Keystore, Relevant tests diff --git a/.changeset/metal-cars-report.md b/.changeset/red-meals-mix.md similarity index 100% rename from .changeset/metal-cars-report.md rename to .changeset/red-meals-mix.md diff --git a/.changeset/rotten-emus-work.md b/.changeset/rotten-emus-work.md deleted file mode 100644 index ecf5ee0b9f..0000000000 --- a/.changeset/rotten-emus-work.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal fixed a bug where we weren't sending the value param to the txm diff --git a/.changeset/shaggy-bananas-do.md b/.changeset/shaggy-bananas-do.md deleted file mode 100644 index b4b8b00e37..0000000000 --- a/.changeset/shaggy-bananas-do.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -add native billing in smoke test #added diff --git a/.changeset/shaggy-ears-share.md b/.changeset/shaggy-ears-share.md deleted file mode 100644 index 5946faf03c..0000000000 --- a/.changeset/shaggy-ears-share.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Add RegistrySyncer diff --git a/.changeset/sharp-rabbits-tie.md b/.changeset/sharp-rabbits-tie.md deleted file mode 100644 index 9daed9f405..0000000000 --- a/.changeset/sharp-rabbits-tie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Updated L1 gas price calculations for Optimism Ecotone and Fjord upgrades #internal diff --git a/.changeset/shiny-poems-juggle.md b/.changeset/shiny-poems-juggle.md deleted file mode 100644 index 32fc2069ee..0000000000 --- a/.changeset/shiny-poems-juggle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -#changed Refactored the BlockHistoryEstimator check to prevent excessively bumping transactions. Check no longer waits for CheckInclusionBlocks to pass before assessing an attempt. -#bugfix Fixed a bug that would use the oldest blocks in the cached history instead of the latest to perform gas estimations. diff --git a/.changeset/shy-deers-hope.md b/.changeset/shy-deers-hope.md deleted file mode 100644 index 0408383bd0..0000000000 --- a/.changeset/shy-deers-hope.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/sour-pigs-develop.md b/.changeset/sour-pigs-develop.md deleted file mode 100644 index 5737b20601..0000000000 --- a/.changeset/sour-pigs-develop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal remote target wait until initiated threads exit on close diff --git a/.changeset/stupid-poems-glow.md b/.changeset/stupid-poems-glow.md deleted file mode 100644 index bdd8acc66d..0000000000 --- a/.changeset/stupid-poems-glow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal rework operator_ui installer diff --git a/.changeset/tall-walls-agree.md b/.changeset/tall-walls-agree.md deleted file mode 100644 index 6f1f5505b6..0000000000 --- a/.changeset/tall-walls-agree.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal upgrade keystone contracts to 0.8.24 diff --git a/.changeset/tall-wombats-deliver.md b/.changeset/tall-wombats-deliver.md deleted file mode 100644 index cb165b999a..0000000000 --- a/.changeset/tall-wombats-deliver.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Allow outputs to be passed directly to the inputs diff --git a/.changeset/ten-falcons-suffer.md b/.changeset/ten-falcons-suffer.md deleted file mode 100644 index e4476b1045..0000000000 --- a/.changeset/ten-falcons-suffer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -move v23 contracts #bugfix diff --git a/.changeset/tender-carpets-cry.md b/.changeset/tender-carpets-cry.md deleted file mode 100644 index 075f769ce0..0000000000 --- a/.changeset/tender-carpets-cry.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"chainlink": patch ---- - -Add new relayer type "dummy" for testing. - -#added diff --git a/.changeset/thick-lemons-beam.md b/.changeset/thick-lemons-beam.md deleted file mode 100644 index 0ce6e04780..0000000000 --- a/.changeset/thick-lemons-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Add script to provision capability registry diff --git a/.changeset/thick-moles-travel.md b/.changeset/thick-moles-travel.md deleted file mode 100644 index 45559e4715..0000000000 --- a/.changeset/thick-moles-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal moves workflow name and owner to the yaml spec diff --git a/.changeset/tiny-camels-flow.md b/.changeset/tiny-camels-flow.md deleted file mode 100644 index 3271bbb4a3..0000000000 --- a/.changeset/tiny-camels-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix fixed ureachable code bug which could result in stuck txns diff --git a/.changeset/unlucky-pillows-fly.md b/.changeset/unlucky-pillows-fly.md deleted file mode 100644 index c8f690eda1..0000000000 --- a/.changeset/unlucky-pillows-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -add events, add getter and add comments #bugfix diff --git a/.changeset/warm-cobras-poke.md b/.changeset/warm-cobras-poke.md deleted file mode 100644 index 0bfb1dd44b..0000000000 --- a/.changeset/warm-cobras-poke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated Fix verb formatting in the log outputs. diff --git a/.changeset/wise-wasps-drum.md b/.changeset/wise-wasps-drum.md deleted file mode 100644 index 0a4a6eaf66..0000000000 --- a/.changeset/wise-wasps-drum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Add loggercheck linter to verify that \*w logging methods have even number of args. diff --git a/.changeset/young-parrots-peel.md b/.changeset/young-parrots-peel.md deleted file mode 100644 index a7b696d14f..0000000000 --- a/.changeset/young-parrots-peel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add registry syncer package #internal diff --git a/CHANGELOG.md b/CHANGELOG.md index be5d8d1c0a..f212445503 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,108 @@ # Changelog Chainlink Core +## 2.14.0 - UNRELEASED + +### Minor Changes + +- [#13356](https://github.com/smartcontractkit/chainlink/pull/13356) [`0228243f20`](https://github.com/smartcontractkit/chainlink/commit/0228243f20bb02d40c7ad2c9cf1002599436ff1d) Thanks [@ilija42](https://github.com/ilija42)! - #internal Add Log Poller support to Chain Reader through setting them in config. All filters should be part of the contract wide filter unless an event needs specific polling configuration, which can be set on a per event basis.. + +- [#13718](https://github.com/smartcontractkit/chainlink/pull/13718) [`f33cd1915c`](https://github.com/smartcontractkit/chainlink/commit/f33cd1915c03bef9bfe110481eb13094c36ce454) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal Added a chain writer constructor onto the evm relayer. + +- [#13040](https://github.com/smartcontractkit/chainlink/pull/13040) [`0ac790b37f`](https://github.com/smartcontractkit/chainlink/commit/0ac790b37fca951dfb4b4093c00c5adbd6987668) Thanks [@amit-momin](https://github.com/amit-momin)! - Added API for products to query a transaction's status in the TXM #internal + +- [#13413](https://github.com/smartcontractkit/chainlink/pull/13413) [`9e733a07fe`](https://github.com/smartcontractkit/chainlink/commit/9e733a07fe2082207e6d7884abee26d82d37e808) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #added EVM implementation of GetFeeComponents function for ChainWriter + +- [#13478](https://github.com/smartcontractkit/chainlink/pull/13478) [`9f6e454bc5`](https://github.com/smartcontractkit/chainlink/commit/9f6e454bc51c07cf817c90a9a11fa44ae3708be5) Thanks [@snehaagni](https://github.com/snehaagni)! - Bump to start the next version + +- [#13501](https://github.com/smartcontractkit/chainlink/pull/13501) [`15f02f65c1`](https://github.com/smartcontractkit/chainlink/commit/15f02f65c1ac3cfc89e726597a981ddf206eea2b) Thanks [@ettec](https://github.com/ettec)! - #internal remove shared secret from transmission schedule + +- [#13691](https://github.com/smartcontractkit/chainlink/pull/13691) [`f2630b280d`](https://github.com/smartcontractkit/chainlink/commit/f2630b280d917313c6d3af468d9a7c039d5e179e) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal Implemented the `GetTransactionStatus` method on the EVM implementation of the `ChainWriter`. + +- [#13551](https://github.com/smartcontractkit/chainlink/pull/13551) [`f7e036244c`](https://github.com/smartcontractkit/chainlink/commit/f7e036244c1bf019964704734a96be5e5699ca2c) Thanks [@ettec](https://github.com/ettec)! - #internal capability dispatcher threading and context usage + +- [#13564](https://github.com/smartcontractkit/chainlink/pull/13564) [`2c2ca6a278`](https://github.com/smartcontractkit/chainlink/commit/2c2ca6a27899295dc87e48e4378671dbbe06ac48) Thanks [@yongkangchia](https://github.com/yongkangchia)! - #changed Added Aptos Keystore to Core. This includes Aptos Key which uses ED25519, Keystore, Relevant tests + +- [#13427](https://github.com/smartcontractkit/chainlink/pull/13427) [`66f154745d`](https://github.com/smartcontractkit/chainlink/commit/66f154745d3d973aa8b629a99a65a660a1d1b3bc) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - #internal Add RegistrySyncer + +- [#13661](https://github.com/smartcontractkit/chainlink/pull/13661) [`363e8290bb`](https://github.com/smartcontractkit/chainlink/commit/363e8290bb5ea2f7bf07528ba19cc64dca8e87a8) Thanks [@amit-momin](https://github.com/amit-momin)! - Updated L1 gas price calculations for Optimism Ecotone and Fjord upgrades #internal + +- [#13297](https://github.com/smartcontractkit/chainlink/pull/13297) [`e55e0424a2`](https://github.com/smartcontractkit/chainlink/commit/e55e0424a276416cf849a83a1488a287872824c5) Thanks [@amit-momin](https://github.com/amit-momin)! - #changed Refactored the BlockHistoryEstimator check to prevent excessively bumping transactions. Check no longer waits for CheckInclusionBlocks to pass before assessing an attempt. + #bugfix Fixed a bug that would use the oldest blocks in the cached history instead of the latest to perform gas estimations. + +- [#13524](https://github.com/smartcontractkit/chainlink/pull/13524) [`d736d9e083`](https://github.com/smartcontractkit/chainlink/commit/d736d9e0838983a021677bc608556b3994f46690) Thanks [@ettec](https://github.com/ettec)! - #internal remote target wait until initiated threads exit on close + +- [#13169](https://github.com/smartcontractkit/chainlink/pull/13169) [`3f56b3eecd`](https://github.com/smartcontractkit/chainlink/commit/3f56b3eecd2d5fd3e325325d9d1e82d8a749d9eb) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal rework operator_ui installer + +- [#13601](https://github.com/smartcontractkit/chainlink/pull/13601) [`c3f6b704f1`](https://github.com/smartcontractkit/chainlink/commit/c3f6b704f1c510dbfb28b421ee3a8f63416b18c1) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - #internal Allow outputs to be passed directly to the inputs + +- [#13621](https://github.com/smartcontractkit/chainlink/pull/13621) [`3eb0a3736f`](https://github.com/smartcontractkit/chainlink/commit/3eb0a3736ff1cc885dd7ff9c978c09218f61e7a6) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - #internal Add script to provision capability registry + +- [#13522](https://github.com/smartcontractkit/chainlink/pull/13522) [`90924dcc26`](https://github.com/smartcontractkit/chainlink/commit/90924dcc2667807f57e31992aac9f674935680b8) Thanks [@krehermann](https://github.com/krehermann)! - #internal moves workflow name and owner to the yaml spec + +- [#13668](https://github.com/smartcontractkit/chainlink/pull/13668) [`e5dc01e844`](https://github.com/smartcontractkit/chainlink/commit/e5dc01e844064e2fdab976369cf83195f9659216) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - Add registry syncer package #internal + +### Patch Changes + +- [#13498](https://github.com/smartcontractkit/chainlink/pull/13498) [`c6f1b30f34`](https://github.com/smartcontractkit/chainlink/commit/c6f1b30f346c0a8a64ed39b8317e247c928a368e) Thanks [@simsonraj](https://github.com/simsonraj)! - #added zkSync L1 GasPrice calculation + +- [#13487](https://github.com/smartcontractkit/chainlink/pull/13487) [`5e27da95f0`](https://github.com/smartcontractkit/chainlink/commit/5e27da95f09f21272e93f086bc2de5a9bc2ae399) Thanks [@bolekk](https://github.com/bolekk)! - #internal Use audited version of OCR2Base.sol in OCR3Capability.sol + +- [#13612](https://github.com/smartcontractkit/chainlink/pull/13612) [`98108568dc`](https://github.com/smartcontractkit/chainlink/commit/98108568dc3ea54537a6867d36f3e48ee456daae) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal bump `chainlink-common` version to commit 6d926be950a6f6ca289a84edad938d4eef2ee337. + +- [#13726](https://github.com/smartcontractkit/chainlink/pull/13726) [`2ecf45d381`](https://github.com/smartcontractkit/chainlink/commit/2ecf45d381b98714f4f673221bfc74577fcfeb04) Thanks [@ferglor](https://github.com/ferglor)! - Only encode non nil block numbers for eth_call #changed + +- [#13048](https://github.com/smartcontractkit/chainlink/pull/13048) [`3f8c00a6f1`](https://github.com/smartcontractkit/chainlink/commit/3f8c00a6f1884f765bbe9e4b70e0dc4fb94a0088) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Fixed local finality violation caused by an RPC lagging behind on latest finalized block. + + Added `EVM.FinalizedBlockOffset` and `EVM.NodePool.EnforceRepeatableRead` config options. + With `EnforceRepeatableRead = true`, RPC is considered healthy only if its most recent finalized block is larger or equal to the highest finalized block observed by the Node minus `FinalizedBlockOffset`. + #bugfix + +- [#13554](https://github.com/smartcontractkit/chainlink/pull/13554) [`22cab6c152`](https://github.com/smartcontractkit/chainlink/commit/22cab6c1526371c898bde52e7836cfd01ba7daf5) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal Bumped `chainlink-common` package version to commit `1fb0b48758af25d689b6957ebfb76598c9fb27ea`. + +- [#13670](https://github.com/smartcontractkit/chainlink/pull/13670) [`253a962fa3`](https://github.com/smartcontractkit/chainlink/commit/253a962fa3997765d5df40cf5ca19f5471ed5976) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal bumped chainlink-common version to commit 1eff5dedc9857ed8811186dd2996603942dc1107 + +- [#13459](https://github.com/smartcontractkit/chainlink/pull/13459) [`8fdc77f6a7`](https://github.com/smartcontractkit/chainlink/commit/8fdc77f6a7c30be5254bd9d0cb75fd6b2736242e) Thanks [@makramkd](https://github.com/makramkd)! - #db_update ccip capability specs migration + +- [#13494](https://github.com/smartcontractkit/chainlink/pull/13494) [`a830fe093f`](https://github.com/smartcontractkit/chainlink/commit/a830fe093f4642236a89ac73bf9eefe5008898bc) Thanks [@HelloKashif](https://github.com/HelloKashif)! - #internal removed HistoryDepth to FinalityDepth validation + +- [#13580](https://github.com/smartcontractkit/chainlink/pull/13580) [`0d4a3b2cd8`](https://github.com/smartcontractkit/chainlink/commit/0d4a3b2cd8ff938ba018d982ef514c754a7df345) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13569](https://github.com/smartcontractkit/chainlink/pull/13569) [`f5a70eb09a`](https://github.com/smartcontractkit/chainlink/commit/f5a70eb09abc9a4d859442c9bd062a74a7ec9c54) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13528](https://github.com/smartcontractkit/chainlink/pull/13528) [`95502ad269`](https://github.com/smartcontractkit/chainlink/commit/95502ad2699d63891662594f70e82e76682f2ed8) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13563](https://github.com/smartcontractkit/chainlink/pull/13563) [`99fa0e68d1`](https://github.com/smartcontractkit/chainlink/commit/99fa0e68d11f4bbc5bc54c6c65edb1db024b21a9) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Clean up workflow engine logging + +- [#13443](https://github.com/smartcontractkit/chainlink/pull/13443) [`955566fb9b`](https://github.com/smartcontractkit/chainlink/commit/955566fb9b9a4f930069d497a81bb6c37fac0125) Thanks [@Tofel](https://github.com/Tofel)! - #changed Expand EVM implementation compatibility pipeline + +- [#13602](https://github.com/smartcontractkit/chainlink/pull/13602) [`fc3a291d6c`](https://github.com/smartcontractkit/chainlink/commit/fc3a291d6c75e8045c3f8e2458ec7513ffdb3882) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal fixed a bug where we weren't sending the value param to the txm + +- [#13714](https://github.com/smartcontractkit/chainlink/pull/13714) [`4b19e37553`](https://github.com/smartcontractkit/chainlink/commit/4b19e37553ecf60c9d98209bc29b4079ae64cbe3) Thanks [@shileiwill](https://github.com/shileiwill)! - add native billing in smoke test #added + +- [#13426](https://github.com/smartcontractkit/chainlink/pull/13426) [`592b2bb5a8`](https://github.com/smartcontractkit/chainlink/commit/592b2bb5a84a0e8858f77c5faa99e881f911878c) Thanks [@archseer](https://github.com/archseer)! - #internal + +- [#13546](https://github.com/smartcontractkit/chainlink/pull/13546) [`10ddafaebe`](https://github.com/smartcontractkit/chainlink/commit/10ddafaebedb94ad5a59968d19256b8c4592857f) Thanks [@cds95](https://github.com/cds95)! - #internal upgrade keystone contracts to 0.8.24 + +- [#13504](https://github.com/smartcontractkit/chainlink/pull/13504) [`815c5ea871`](https://github.com/smartcontractkit/chainlink/commit/815c5ea8715462e00f6ea10cdc0b93ec3e1ba505) Thanks [@shileiwill](https://github.com/shileiwill)! - move v23 contracts #bugfix + +- [#13583](https://github.com/smartcontractkit/chainlink/pull/13583) [`8ccaa140ae`](https://github.com/smartcontractkit/chainlink/commit/8ccaa140aebdafbb760569a1d2b7cabe8ac1bf61) Thanks [@samsondav](https://github.com/samsondav)! - Add new relayer type "dummy" for testing. + + #added + +- [#13671](https://github.com/smartcontractkit/chainlink/pull/13671) [`4493b96f62`](https://github.com/smartcontractkit/chainlink/commit/4493b96f62d18376d89ae152cb0df3eab87ab5fd) Thanks [@poopoothegorilla](https://github.com/poopoothegorilla)! - #bugfix fixed ureachable code bug which could result in stuck txns + +- [#13376](https://github.com/smartcontractkit/chainlink/pull/13376) [`bb40d51502`](https://github.com/smartcontractkit/chainlink/commit/bb40d51502487b010a1d6621db42458356dbbdc0) Thanks [@shileiwill](https://github.com/shileiwill)! - add events, add getter and add comments #bugfix + +- [#13495](https://github.com/smartcontractkit/chainlink/pull/13495) [`483ee6ae06`](https://github.com/smartcontractkit/chainlink/commit/483ee6ae06f608d150ab360e0a3ffe6895b39d52) Thanks [@pavel-raykov](https://github.com/pavel-raykov)! - #updated Fix verb formatting in the log outputs. + +- [#13599](https://github.com/smartcontractkit/chainlink/pull/13599) [`e0ce0795b4`](https://github.com/smartcontractkit/chainlink/commit/e0ce0795b44f27539611327efce7c7c004511daa) Thanks [@pavel-raykov](https://github.com/pavel-raykov)! - #internal Add loggercheck linter to verify that \*w logging methods have even number of args. + ## 2.13.0 - 2024-07-01 ### Minor Changes - [#13354](https://github.com/smartcontractkit/chainlink/pull/13354) [`58d73ecf61`](https://github.com/smartcontractkit/chainlink/commit/58d73ecf618ac39c37f767e70c4e6d6a51eaba59) Thanks [@friedemannf](https://github.com/friedemannf)! - #breaking_change Remove the `xdai` `ChainType` config option. Moving forward, only `gnosis` can be used. - - [#13221](https://github.com/smartcontractkit/chainlink/pull/13221) [`0b100ad3db`](https://github.com/smartcontractkit/chainlink/commit/0b100ad3dbf0a3c2fbd6e55c539046f6f3c9e5f6) Thanks [@ilija42](https://github.com/ilija42)! - Added a mechanism to validate forwarders for OCR2 and fallback to EOA if necessary #added - [#13384](https://github.com/smartcontractkit/chainlink/pull/13384) [`bc087f1de2`](https://github.com/smartcontractkit/chainlink/commit/bc087f1de2014cce1027341d14e0917c4351fb21) Thanks [@augustbleeds](https://github.com/augustbleeds)! - bump chainlink-starknet so it builds reports with median gas price #updated @@ -28,7 +124,6 @@ ### Patch Changes - - [#13315](https://github.com/smartcontractkit/chainlink/pull/13315) [`3af83ed014`](https://github.com/smartcontractkit/chainlink/commit/3af83ed01439648354ac6b348d61b0f9594b99ec) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Reducing the scope of 0233 migration to include only 5th word index which is required for CCIP #db_update - [#13144](https://github.com/smartcontractkit/chainlink/pull/13144) [`49f1bf3ba2`](https://github.com/smartcontractkit/chainlink/commit/49f1bf3ba296f0e3dfc01d5a3d371f82f159dc4a) Thanks [@jmank88](https://github.com/jmank88)! - improve handling of postgres connection settings and driver versions #db @@ -48,14 +143,12 @@ - [#13364](https://github.com/smartcontractkit/chainlink/pull/13364) [`fc007a9484`](https://github.com/smartcontractkit/chainlink/commit/fc007a94846c178bc9d5203dbff6b6b8c7546a71) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #bugfix fix a funding bug in LinkAvailableBalanceMonitor - - [#13174](https://github.com/smartcontractkit/chainlink/pull/13174) [`e778a3202b`](https://github.com/smartcontractkit/chainlink/commit/e778a3202b4d8761ffc44b790196d9a580fede1c) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #changed: AUTO-10539: adjust logging for offchain config and gas control - [#12952](https://github.com/smartcontractkit/chainlink/pull/12952) [`7572a50a78`](https://github.com/smartcontractkit/chainlink/commit/7572a50a78a270188344786937f68233df82f65b) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #added compare user-defined max gas price with current gas price in automation simulation pipeline - - [#13216](https://github.com/smartcontractkit/chainlink/pull/13216) [`6099abbdbf`](https://github.com/smartcontractkit/chainlink/commit/6099abbdbfb3ad396ca1ed5138ecd7a13159de19) Thanks [@ibrajer](https://github.com/ibrajer)! - Added Base Sepolia to ChainUtils #changed - [#13177](https://github.com/smartcontractkit/chainlink/pull/13177) [`0d58a8d5db`](https://github.com/smartcontractkit/chainlink/commit/0d58a8d5db24f42720226e73328e501637ba59c5) Thanks [@shileiwill](https://github.com/shileiwill)! - link transfer status check #bugfix @@ -65,12 +158,10 @@ - [#13213](https://github.com/smartcontractkit/chainlink/pull/13213) [`1b1e31ebfc`](https://github.com/smartcontractkit/chainlink/commit/1b1e31ebfc5198ab7e43291110b6f5d54e467a01) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #bugfix fix an automation smoke test flake - - [#12813](https://github.com/smartcontractkit/chainlink/pull/12813) [`ac893364e6`](https://github.com/smartcontractkit/chainlink/commit/ac893364e6c6ede08e9bf04da7dc64e0da94ab6e) Thanks [@matYang](https://github.com/matYang)! - #db_update created 2 new CCIP tables in migration 0236, one for observed gas prices, one for observed token prices; setup indexing for these tables. #added ORM for CCIP gas prices and token prices - - [#13173](https://github.com/smartcontractkit/chainlink/pull/13173) [`a9717f05e9`](https://github.com/smartcontractkit/chainlink/commit/a9717f05e9af0fa07746c6b95b7f1625089a860f) Thanks [@ferglor](https://github.com/ferglor)! - Revert block number tracking #changed - [#12952](https://github.com/smartcontractkit/chainlink/pull/12952) [`7572a50a78`](https://github.com/smartcontractkit/chainlink/commit/7572a50a78a270188344786937f68233df82f65b) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #added @@ -88,21 +179,18 @@ - [#13096](https://github.com/smartcontractkit/chainlink/pull/13096) [`2c08c8c1a5`](https://github.com/smartcontractkit/chainlink/commit/2c08c8c1a58ea4b7c09b0d5a5ca3b8a677beb9f4) Thanks [@shileiwill](https://github.com/shileiwill)! - add upkeepCharged event #bugfix - - [#13078](https://github.com/smartcontractkit/chainlink/pull/13078) [`0917394a46`](https://github.com/smartcontractkit/chainlink/commit/0917394a4625c3e97b17e348dd473199a15402bf) Thanks [@finleydecker](https://github.com/finleydecker)! - bumpThreshold config setting for chains using suggestPrice estimator #updated - [#13336](https://github.com/smartcontractkit/chainlink/pull/13336) [`4c7e5a0efa`](https://github.com/smartcontractkit/chainlink/commit/4c7e5a0efa90aed5d5454b5a68753076eea67f55) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Added config option `HeadTracker.FinalityTagBypass` to force `HeadTracker` to track blocks up to `FinalityDepth` even if `FinalityTagsEnabled = true`. This option is a temporary measure to address high CPU usage on chains with extremely large actual finality depth (gap between the current head and the latest finalized block). #added Added config option `HeadTracker.MaxAllowedFinalityDepth` maximum gap between current head to the latest finalized block that `HeadTracker` considers healthy. #added - - [#13263](https://github.com/smartcontractkit/chainlink/pull/13263) [`14ec6c4a91`](https://github.com/smartcontractkit/chainlink/commit/14ec6c4a912eeb65753703c363d1e90cbcf88328) Thanks [@shileiwill](https://github.com/shileiwill)! - tune debugging script #bugfix - [#13088](https://github.com/smartcontractkit/chainlink/pull/13088) [`29b16360fb`](https://github.com/smartcontractkit/chainlink/commit/29b16360fb41e4372f72fe744aaf3ee8234a9b67) Thanks [@shileiwill](https://github.com/shileiwill)! - get available erc20 for payment #bugfix - [#13165](https://github.com/smartcontractkit/chainlink/pull/13165) [`143741012c`](https://github.com/smartcontractkit/chainlink/commit/143741012c4d0b148ada9d5aa237ff932cd3005b) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - #db_update Add ON DELETE CASCADE to workflow tables - - [#12952](https://github.com/smartcontractkit/chainlink/pull/12952) [`7572a50a78`](https://github.com/smartcontractkit/chainlink/commit/7572a50a78a270188344786937f68233df82f65b) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #added an integration test for max gas price check - [#13272](https://github.com/smartcontractkit/chainlink/pull/13272) [`c7a6356f49`](https://github.com/smartcontractkit/chainlink/commit/c7a6356f4903e919964ca91493f18e0ebf4eb08b) Thanks [@friedemannf](https://github.com/friedemannf)! - #bugfix allow ChainType to be set to xdai diff --git a/package.json b/package.json index f12e869542..b60a4573d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainlink", - "version": "2.13.0", + "version": "2.14.0", "description": "node of the decentralized oracle network, bridging on and off-chain computation", "main": "index.js", "scripts": { From 2713d42a779f635a4809e2b0106e8dca7951b5be Mon Sep 17 00:00:00 2001 From: nogo <110664798+0xnogo@users.noreply.github.com> Date: Fri, 5 Jul 2024 13:21:25 +0200 Subject: [PATCH 47/61] Fix slice bounds out of range error in performBatchCall (#1145) Catching `err` if the evm call fails --- .../plugins/ccip/internal/pricegetter/evm.go | 3 + .../ccip/internal/pricegetter/evm_test.go | 61 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go index c8a70cfdc0..830d56cd3a 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm.go @@ -144,6 +144,9 @@ func (d *DynamicPriceGetter) performBatchCall(ctx context.Context, chainID uint6 calls = append(calls, batchCalls.latestRoundDataCalls...) results, err := evmCaller.BatchCall(ctx, 0, calls) + if err != nil { + return fmt.Errorf("batch call on chain %d failed: %w", chainID, err) + } // Extract results. decimals := make([]uint8, 0, nbDecimalCalls) diff --git a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go index 8d1bf67ab1..673b9776c7 100644 --- a/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go +++ b/core/services/ocr2/plugins/ccip/internal/pricegetter/evm_test.go @@ -25,6 +25,7 @@ type testParameters struct { evmClients map[uint64]DynamicPriceGetterClient tokens []common.Address expectedTokenPrices map[common.Address]big.Int + evmCallErr bool invalidConfigErrorExpected bool priceResolutionErrorExpected bool } @@ -58,6 +59,10 @@ func TestDynamicPriceGetter(t *testing.T) { name: "no_aggregator_for_token", param: testParamNoAggregatorForToken(t), }, + { + name: "batchCall_returns_err", + param: testParamBatchCallReturnsErr(t), + }, } for _, test := range tests { @@ -82,6 +87,12 @@ func TestDynamicPriceGetter(t *testing.T) { tokens = append(tokens, tokenAddr) } prices, err := pg.TokenPricesUSD(ctx, tokens) + + if test.param.evmCallErr { + require.Error(t, err) + return + } + if test.param.priceResolutionErrorExpected { require.Error(t, err) return @@ -454,6 +465,50 @@ func testParamNoAggregatorForToken(t *testing.T) testParameters { } } +func testParamBatchCallReturnsErr(t *testing.T) testParameters { + tk1 := utils.RandomAddress() + tk2 := utils.RandomAddress() + tk3 := utils.RandomAddress() + cfg := config.DynamicPriceGetterConfig{ + AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ + tk1: { + ChainID: 101, + AggregatorContractAddress: utils.RandomAddress(), + }, + tk2: { + ChainID: 102, + AggregatorContractAddress: utils.RandomAddress(), + }, + }, + StaticPrices: map[common.Address]config.StaticPriceConfig{ + tk3: { + ChainID: 103, + Price: big.NewInt(1_234_000), + }, + }, + } + // Real LINK/USD example from OP. + round1 := aggregator_v3_interface.LatestRoundData{ + RoundId: big.NewInt(1000), + Answer: big.NewInt(1396818990), + StartedAt: big.NewInt(1704896575), + UpdatedAt: big.NewInt(1704896575), + AnsweredInRound: big.NewInt(1000), + } + evmClients := map[uint64]DynamicPriceGetterClient{ + uint64(101): mockClient(t, []uint8{8}, []aggregator_v3_interface.LatestRoundData{round1}), + uint64(102): { + BatchCaller: mockErrCaller(t), + }, + } + return testParameters{ + cfg: cfg, + evmClients: evmClients, + tokens: []common.Address{tk1, tk2, tk3}, + evmCallErr: true, + } +} + func mockClient(t *testing.T, decimals []uint8, rounds []aggregator_v3_interface.LatestRoundData) DynamicPriceGetterClient { return DynamicPriceGetterClient{ BatchCaller: mockCaller(t, decimals, rounds), @@ -479,6 +534,12 @@ func mockCaller(t *testing.T, decimals []uint8, rounds []aggregator_v3_interface return caller } +func mockErrCaller(t *testing.T) *rpclibmocks.EvmBatchCaller { + caller := rpclibmocks.NewEvmBatchCaller(t) + caller.On("BatchCall", mock.Anything, uint64(0), mock.Anything).Return(nil, assert.AnError).Maybe() + return caller +} + // multExp returns the result of multiplying x by 10^e. func multExp(x *big.Int, e int64) *big.Int { return big.NewInt(0).Mul(x, big.NewInt(0).Exp(big.NewInt(10), big.NewInt(e), nil)) From 5ca33641bec013d004cd35d0060e9695a508b4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Evaldas=20Lato=C5=A1kinas?= <34982762+elatoskinas@users.noreply.github.com> Date: Fri, 5 Jul 2024 18:17:27 +0200 Subject: [PATCH 48/61] MultiOffRamp - family-agnostic messages (#1117) ## Motivation The Multi-OffRamp can be converted to be family agnostic by using more generic `Any2EVM` structures and breaking the reliance on abi hashing ## Solution * Remove `metadataHash` and use an implicit metadata hash composed of `(prefix, srcChainSelector, destChainSelector, onRampAddress)` * Convert `EVM2EVMMessage` to `Any2EVMRampMessage`, which uses a generic `bytes sender` * Decouple `messageId` from `hash(message)` * Out-of-scope: EVM2Any OnRamp changes Sample on why hashes between Any2X and X2Any are no longer equivalent: ``` Solana: - messageId: hash(Sol2AnyMessage msg) - (Sol2Any message could contain some extra fields that are SOL-specific) Off-chain: - Sol2AnyMessage -> Any2AnyMessage -> Any2EVMMessage - Route SOL -> Ethereum Ethereum: - messageId: hash(Any2EVMMessage msg) - (Any2EVMMessage will contain some EVM-specific fields, but not the SOL specific fields) hash(Sol2AnyMessage) != hash(Any2EVMMessage) ``` --------- Co-authored-by: Makram --- contracts/gas-snapshots/ccip.gas-snapshot | 225 +++-- .../scripts/native_solc_compile_all_ccip | 2 +- .../src/v0.8/ccip/libraries/Internal.sol | 72 +- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 122 +-- .../v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol | 2 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 216 +++-- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 54 +- .../helpers/EVM2EVMMultiOffRampHelper.sol | 6 +- .../v0.8/ccip/test/helpers/MessageHasher.sol | 53 +- .../test/offRamp/EVM2EVMMultiOffRamp.t.sol | 842 ++++++++---------- .../offRamp/EVM2EVMMultiOffRampSetup.t.sol | 102 +-- .../evm_2_evm_multi_offramp.go | 55 +- .../evm_2_evm_multi_onramp.go | 16 +- .../message_hasher/message_hasher.go | 162 +++- ...rapper-dependency-versions-do-not-edit.txt | 6 +- .../ocr3/plugins/ccipevm/msghasher.go | 153 ++-- .../ocr3/plugins/ccipevm/msghasher_test.go | 325 ++----- 17 files changed, 1243 insertions(+), 1170 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 60bd3a9b85..54443aa4e2 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -119,115 +119,110 @@ E2E:test_E2E_3MessagesSuccess_gas() (gas: 1104821) EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38361) EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108455) EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116907) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 191359) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 69836) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12359) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRampAndPrevOffRamp_Revert() (gas: 64548) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 64551) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 77549) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 12258) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 12199) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 294969) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 238328) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 157487) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188364) -EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 147255) -EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 527932) -EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10505) -EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 17210) -EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 63695) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460360) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95427) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90249) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105403) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15651) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 12989) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 305737) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 247076) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 162376) +EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 195244) +EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 150011) +EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 535435) +EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10525) +EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 16096) +EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67080) EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59630) EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58710) -EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6425913) -EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 6009185) +EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6574764) +EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 6157992) EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 108329) EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 118244) EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 108372) -EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353558) -EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 157810) -EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 132726) +EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353646) +EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 161185) +EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136112) EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136695) EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 58978) -EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 222706) +EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227569) EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 119611) EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77537) -EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205601) -EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6420302) +EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 209029) +EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6569153) EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47717) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 6024813) -EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 103217) -EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 99988) -EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 97859) -EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 103227) -EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 97758) -EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 97825) +EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 6158331) +EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 104384) +EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 100309) +EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 98180) +EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 106890) +EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 98079) +EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 98146) EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17299) -EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1546406) -EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 341361) -EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 258517) -EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6477785) -EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6060776) -EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 30048) -EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 164664) -EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148612) -EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6839860) +EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1640074) +EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 350683) +EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 267647) +EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6627625) +EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6210572) +EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 28435) +EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 167667) +EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 151623) +EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6989700) EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17174) -EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20655) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 255569) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 22806) -EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 207958) -EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50888) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 50398) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 235368) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 91184) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 287803) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 95288) -EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 37208) -EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23877) -EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidMessageId_Revert() (gas: 41684) -EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 458019) -EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 53460) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampAddress_Revert() (gas: 44527) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingSourceChainSelector_Revert() (gas: 41576) -EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 37438) -EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 181595) -EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 189957) -EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 47044) -EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 434527) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248935) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 174421) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 193347) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259840) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 127020) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 394980) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65861) -EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80076) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 541116) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 475488) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 37957) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 526295) -EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 523674) -EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 492610) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 126952) -EVM2EVMMultiOffRamp_executeSingleReport:test_execute_SkippedAlreadyExecutedMessage_Success() (gas: 155518) -EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3667544) -EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118276) -EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87396) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 79283) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 28601) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 163512) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 207222) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 28130) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 158903) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 505081) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2379173) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 209279) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 209853) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 664710) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 297865) -EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnOnRampAddress_Success() (gas: 10995) -EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnSourceChain_Success() (gas: 11041) -EVM2EVMMultiOffRamp_metadataHash:test_MetadataHash_Success() (gas: 9141) +EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 19548) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 254458) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21806) +EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 206750) +EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50035) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 49556) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 234116) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 90376) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 287302) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 94638) +EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 36249) +EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23921) +EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 462794) +EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 55975) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 37072) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 156143) +EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 36483) +EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 184243) +EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 194605) +EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 49553) +EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 439123) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 256572) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 179039) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 198372) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 262344) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 131587) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 399804) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 67753) +EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 82478) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 546583) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 486844) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 36976) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 534156) +EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 531524) +EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 498454) +EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 131751) +EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 160626) +EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3633818) +EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118144) +EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87253) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81957) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27558) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 165891) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 212381) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27086) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 166703) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 512307) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2397801) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 214474) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 215037) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 692864) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 309081) EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165102) EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 26890) EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 63495) @@ -236,19 +231,19 @@ EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupp EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 185299) EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 283897) EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11420) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215214) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215247) EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14223) EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11729) EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 13885) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55563) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33573) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 243560) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 252217) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 306038) -EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 285633) -EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176524) -EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178595) -EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141456) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55608) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33618) +EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 242740) +EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 251403) +EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 308206) +EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 285105) +EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176538) +EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178609) +EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141470) EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51507) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 33833) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16646) @@ -642,18 +637,18 @@ 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) -MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1424394) +MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1435700) 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: 251109) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 250287) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 303526) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 286447) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 250490) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 238465) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 144101) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 255244) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 257899) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 313263) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 295481) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 248932) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236918) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 147192) NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 173337) NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 217372) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125707) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index b00071c9b3..3cfecbc056 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=3600 -OPTIMIZE_RUNS_MULTI_OFFRAMP=1800 +OPTIMIZE_RUNS_MULTI_OFFRAMP=2400 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index e39fcf4c0f..9068ca3a10 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -71,7 +71,7 @@ library Internal { /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct ExecutionReportSingleChain { uint64 sourceChainSelector; // Source chain selector for which the report is submitted - EVM2EVMMessage[] messages; + Any2EVMRampMessage[] messages; // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token bytes[][] offchainTokenData; bytes32[] proofs; @@ -106,6 +106,7 @@ library Internal { bytes32 messageId; // a hash of the message data } + // TODO: create new const for EVM2AnyMessage /// @dev EVM2EVMMessage struct has 13 fields, including 3 variable arrays. /// Each variable array takes 1 more slot to store its length. /// When abi encoded, excluding array contents, @@ -113,6 +114,7 @@ library Internal { /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 17. uint256 public constant MESSAGE_FIXED_BYTES = 32 * 17; + // TODO: create new const for EVM2AnyMessage /// @dev Each token transfer adds 1 EVMTokenAmount and 1 bytes. /// When abiEncoded, each EVMTokenAmount takes 2 slots, each bytes takes 2 slots, excl bytes contents uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 4; @@ -132,6 +134,12 @@ library Internal { bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256("EVM2EVMMessageHashV2"); + /// @dev Used to hash messages for single-lane ramps. + /// OnRamp hash(EVM2EVMMessage) = OffRamp hash(EVM2EVMMessage) + /// The EVM2EVMMessage's messageId is expected to be the output of this hash function + /// @param original Message to hash + /// @param metadataHash Immutable metadata hash representing a lane with a fixed OnRamp + /// @return hashedMessage hashed message as a keccak256 function _hash(EVM2EVMMessage 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. @@ -158,6 +166,43 @@ library Internal { ); } + bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1"); + + /// @dev Used to hash messages for multi-lane family-agnostic OffRamps. + /// 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 + /// @return hashedMessage hashed message as a keccak256 + function _hash(Any2EVMRampMessage memory original, bytes memory onRamp) 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 + ) + ), + keccak256( + abi.encode( + original.header.messageId, + original.sender, + original.receiver, + original.header.sequenceNumber, + original.gasLimit, + original.header.nonce + ) + ), + keccak256(original.data), + keccak256(abi.encode(original.tokenAmounts)), + keccak256(abi.encode(original.sourceTokenData)) + ) + ); + } + /// @notice This methods provides validation for parsing abi encoded addresses by ensuring the /// address is within the EVM address space. If it isn't it will revert with an InvalidEVMAddress error, which /// we can catch and handle more gracefully than a revert from abi.decode. @@ -200,4 +245,29 @@ library Internal { Commit, Execution } + + /// @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 + // TODO: revisit if destChainSelector is required (likely sufficient to have it implicitly in the commit roots) + 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 + } + + /// @notice Family-agnostic message routed to an OffRamp + /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage), hash(Any2EVMRampMessage) != messageId + /// due to encoding & parameter differences + struct Any2EVMRampMessage { + RampMessageHeader header; // Message header + bytes sender; // sender address on the source chain + 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 + // TODO: revisit collapsing tokenAmounts + sourceTokenData into one struct array + Client.EVMTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer + bytes[] sourceTokenData; // array of token data, one per token + } } diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 44df9df050..08c8086884 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -24,8 +24,8 @@ import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts /// @notice EVM2EVMOffRamp enables OCR networks to execute multiple messages /// in an OffRamp in a single transaction. -/// @dev The EVM2EVMOnRamp, CommitStore and EVM2EVMOffRamp form an xchain upgradeable unit. Any change to one of them -/// results an onchain upgrade of all 3. +/// @dev The EVM2EVMMultiOnRamp and EVM2EVMMultiOffRamp form an xchain upgradeable unit. Any change to one of them +/// results an onchain upgrade of both contracts. /// @dev MultiOCR3Base is used to store multiple OCR configs for both the OffRamp and the CommitStore. /// The execution plugin type has to be configured without signature verification, and the commit /// plugin type with verification. @@ -51,7 +51,6 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { error TokenHandlingError(bytes error); error EmptyReport(); error CursedByRMN(uint64 sourceChainSelector); - error InvalidMessageId(bytes32 messageId); error NotACompatiblePool(address notPool); error InvalidDataLength(uint256 expected, uint256 got); error InvalidNewState(uint64 sourceChainSelector, uint64 sequenceNumber, Internal.MessageExecutionState newState); @@ -59,6 +58,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { error StaleCommitReport(); error InvalidInterval(uint64 sourceChainSelector, Interval interval); error ZeroAddressNotAllowed(); + error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); /// @dev Atlas depends on this event, if changing, please notify Atlas. event StaticConfigSet(StaticConfig staticConfig); @@ -89,20 +89,16 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Per-chain source config (defining a lane from a Source Chain -> Dest OffRamp) struct SourceChainConfig { - bool isEnabled; // ────╮ Flag whether the source chain is enabled or not - uint64 minSeqNr; // | The min sequence number expected for future messages - address onRamp; // ────╯ OnRamp address on the source chain - /// @dev Ensures that 2 identical messages sent to 2 different lanes will have a distinct hash. - /// Must match the metadataHash used in computing leaf hashes offchain for the root committed in - /// the commitStore and i_metadataHash in the onRamp. - bytes32 metadataHash; // Source-chain specific message hash preimage to ensure global uniqueness + bool isEnabled; // ──────────╮ Flag whether the source chain is enabled or not + uint64 minSeqNr; // ─────────╯ The min sequence number expected for future messages + bytes onRamp; // OnRamp address on the source chain } /// @notice SourceChainConfig update args scoped to one source chain struct SourceChainConfigArgs { uint64 sourceChainSelector; // ───╮ Source chain selector of the config to update - bool isEnabled; // │ Flag whether the source chain is enabled or not - address onRamp; // ────────────────╯ OnRamp address on the source chain + bool isEnabled; // ────────────────╯ Flag whether the source chain is enabled or not + bytes onRamp; // OnRamp address on the source chain } /// @notice Dynamic offRamp config @@ -345,14 +341,19 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { bytes32[] memory hashedLeaves = new bytes32[](numMsgs); for (uint256 i = 0; i < numMsgs; ++i) { - Internal.EVM2EVMMessage memory message = report.messages[i]; + Internal.Any2EVMRampMessage memory message = report.messages[i]; + + // Commits do not verify the destChainSelector in the message, since only the root is committed, + // so we have to check it explicitly + if (message.header.destChainSelector != i_chainSelector) { + revert InvalidMessageDestChainSelector(message.header.destChainSelector); + } + // We do this hash here instead of in _verifyMessages to avoid two separate loops - // over the same data, which increases gas cost - hashedLeaves[i] = Internal._hash(message, sourceChainConfig.metadataHash); - // For EVM2EVM offramps, the messageID is the leaf hash. - // Asserting that this is true ensures we don't accidentally commit and then execute - // a message with an unexpected hash. - if (hashedLeaves[i] != message.messageId) revert InvalidMessageId(message.messageId); + // 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); } // SECURITY CRITICAL CHECK @@ -363,14 +364,15 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { // Execute messages bool manualExecution = manualExecGasLimits.length != 0; for (uint256 i = 0; i < numMsgs; ++i) { - Internal.EVM2EVMMessage memory message = report.messages[i]; + Internal.Any2EVMRampMessage memory message = report.messages[i]; - Internal.MessageExecutionState originalState = getExecutionState(sourceChainSelector, message.sequenceNumber); + Internal.MessageExecutionState originalState = + getExecutionState(sourceChainSelector, message.header.sequenceNumber); if (originalState == Internal.MessageExecutionState.SUCCESS) { // If the message has already been executed, we skip it. We want to not revert on race conditions between // executing parties. This will allow us to open up manual exec while also attempting with the DON, without // reverting an entire DON batch when a user manually executes while the tx is inflight. - emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.sequenceNumber); + emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.sequenceNumber); continue; } // Two valid cases here, we either have never touched this message before, or we tried to execute @@ -381,7 +383,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { originalState == Internal.MessageExecutionState.UNTOUCHED || originalState == Internal.MessageExecutionState.FAILURE ) - ) revert AlreadyExecuted(sourceChainSelector, message.sequenceNumber); + ) revert AlreadyExecuted(sourceChainSelector, message.header.sequenceNumber); if (manualExecution) { bool isOldCommitReport = @@ -400,7 +402,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { // DON can only execute a message once // Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE if (originalState != Internal.MessageExecutionState.UNTOUCHED) { - revert AlreadyAttempted(sourceChainSelector, message.sequenceNumber); + revert AlreadyAttempted(sourceChainSelector, message.header.sequenceNumber); } } @@ -410,12 +412,10 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { // FAILURE -> FAILURE no nonce bump // FAILURE -> SUCCESS no nonce bump // UNTOUCHED messages MUST be executed in order always - if (message.nonce > 0 && originalState == Internal.MessageExecutionState.UNTOUCHED) { + if (message.header.nonce > 0 && originalState == Internal.MessageExecutionState.UNTOUCHED) { // If a nonce is not incremented, that means it was skipped, and we can ignore the message if ( - !INonceManager(i_nonceManager).incrementInboundNonce( - sourceChainSelector, message.nonce, abi.encode(message.sender) - ) + !INonceManager(i_nonceManager).incrementInboundNonce(sourceChainSelector, message.header.nonce, message.sender) ) continue; } @@ -423,12 +423,12 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { // when executing as a defense in depth measure. bytes[] memory offchainTokenData = report.offchainTokenData[i]; if (message.tokenAmounts.length != offchainTokenData.length) { - revert TokenDataMismatch(sourceChainSelector, message.sequenceNumber); + revert TokenDataMismatch(sourceChainSelector, message.header.sequenceNumber); } - _setExecutionState(sourceChainSelector, message.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); + _setExecutionState(sourceChainSelector, message.header.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); (Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData); - _setExecutionState(sourceChainSelector, message.sequenceNumber, newState); + _setExecutionState(sourceChainSelector, message.header.sequenceNumber, newState); // Since it's hard to estimate whether manual execution will succeed, we // revert the entire transaction if it fails. This will show the user if @@ -439,26 +439,28 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { ) { // If manual execution fails, we revert the entire transaction, unless the originalState is UNTOUCHED as we // would still be making progress by changing the state from UNTOUCHED to FAILURE. - revert ExecutionError(message.messageId, returnData); + revert ExecutionError(message.header.messageId, returnData); } // The only valid prior states are UNTOUCHED and FAILURE (checked above) // The only valid post states are FAILURE and SUCCESS (checked below) if (newState != Internal.MessageExecutionState.FAILURE && newState != Internal.MessageExecutionState.SUCCESS) { - revert InvalidNewState(sourceChainSelector, message.sequenceNumber, newState); + revert InvalidNewState(sourceChainSelector, message.header.sequenceNumber, newState); } - emit ExecutionStateChanged(sourceChainSelector, message.sequenceNumber, message.messageId, newState, returnData); + emit ExecutionStateChanged( + sourceChainSelector, message.header.sequenceNumber, message.header.messageId, newState, returnData + ); } } /// @notice Try executing a message. - /// @param message Internal.EVM2EVMMessage memory message. + /// @param message Internal.Any2EVMRampMessage memory message. /// @param offchainTokenData Data provided by the DON for token transfers. /// @return the new state of the message, being either SUCCESS or FAILURE. /// @return revert data in bytes if CCIP receiver reverted during execution. function _trialExecute( - Internal.EVM2EVMMessage memory message, + Internal.Any2EVMRampMessage memory message, bytes[] memory offchainTokenData ) internal returns (Internal.MessageExecutionState, bytes memory) { try this.executeSingleMessage(message, offchainTokenData) {} @@ -476,7 +478,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { return (Internal.MessageExecutionState.FAILURE, err); } else { // If revert is not caused by CCIP receiver, it is unexpected, bubble up the revert. - revert ExecutionError(message.messageId, err); + revert ExecutionError(message.header.messageId, err); } } // If message execution succeeded, no CCIP receiver return data is expected, return with empty bytes. @@ -490,21 +492,27 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// its execution and enforce atomicity among successful message processing and token transfer. /// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts /// (for example smart contract wallets) without an associated message. - function executeSingleMessage(Internal.EVM2EVMMessage memory message, bytes[] memory offchainTokenData) external { + function executeSingleMessage(Internal.Any2EVMRampMessage memory message, bytes[] memory offchainTokenData) 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, - abi.encode(message.sender), + message.sender, message.receiver, - message.sourceChainSelector, + message.header.sourceChainSelector, message.sourceTokenData, offchainTokenData ); } - Client.Any2EVMMessage memory any2EvmMessage = Internal._toAny2EVMMessage(message, destTokenAmounts); + Client.Any2EVMMessage memory any2EvmMessage = Client.Any2EVMMessage({ + messageId: message.header.messageId, + sourceChainSelector: message.header.sourceChainSelector, + sender: abi.encode(message.sender), + data: message.data, + destTokenAmounts: destTokenAmounts + }); address messageValidator = s_dynamicConfig.messageValidator; if (messageValidator != address(0)) { @@ -535,11 +543,6 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { if (!success) revert ReceiverError(returnData); } - /// @notice creates a unique hash to be used in message hashing. - function _metadataHash(uint64 sourceChainSelector, address onRamp, bytes32 prefix) internal view returns (bytes32) { - return keccak256(abi.encode(prefix, sourceChainSelector, i_chainSelector, onRamp)); - } - // ================================================================ // │ Commit │ // ================================================================ @@ -728,21 +731,20 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { revert ZeroChainSelectorNotAllowed(); } - if (sourceConfigUpdate.onRamp == address(0)) { - revert ZeroAddressNotAllowed(); - } - 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 (currentConfig.onRamp == address(0)) { - currentConfig.metadataHash = - _metadataHash(sourceChainSelector, sourceConfigUpdate.onRamp, Internal.EVM_2_EVM_MESSAGE_HASH); - currentConfig.onRamp = sourceConfigUpdate.onRamp; - currentConfig.minSeqNr = 1; + if (currentOnRamp.length == 0) { + if (newOnRamp.length == 0) { + revert ZeroAddressNotAllowed(); + } + currentConfig.onRamp = newOnRamp; + currentConfig.minSeqNr = 1; emit SourceChainSelectorAdded(sourceChainSelector); - } else if (currentConfig.onRamp != sourceConfigUpdate.onRamp) { + } else if (keccak256(currentOnRamp) != keccak256(newOnRamp)) { revert InvalidStaticConfig(sourceChainSelector); } @@ -788,9 +790,11 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @param sourceAmount The amount of 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 sourceTokenData A struct containing the local token address, the source pool address and optional data /// returned from the source pool. /// @param offchainTokenData Data fetched offchain by the DON. + /// @return destTokenAmount local token address with amount function _releaseOrMintSingleToken( uint256 sourceAmount, bytes memory originalSender, @@ -863,8 +867,12 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Uses pools to release or mint a number of different tokens to a receiver address. /// @param sourceTokenAmounts List of tokens and amount values to be released/minted. - /// @param encodedSourceTokenData Array of token data returned by token pools on the source chain. + /// @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 encodedSourceTokenData Encoded source token data, decoding to Internal.SourceTokenData /// @param offchainTokenData Array of token data fetched offchain by the DON. + /// @return destTokenAmounts local token addresses with amounts /// @dev This function wrappes 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. diff --git a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol index df3ba45b48..130309a9a6 100644 --- a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol @@ -54,7 +54,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre event TokenTransferFeeConfigUpdated( uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig ); - event TokenTransferFeeConfigDeleted(uint256 indexed destChainSelector, address indexed token); + event TokenTransferFeeConfigDeleted(uint64 indexed destChainSelector, address indexed token); /// RMN depends on this event, if changing, please notify the RMN maintainers. event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2EVMMessage message); event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index f6e332701d..b780f4cfad 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -322,20 +322,28 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { EVM2EVMOffRampHelper internal s_prevOffRamp; EVM2EVMOffRampHelper[] internal s_nestedPrevOffRamps; + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_1 = abi.decode(ON_RAMP_ADDRESS_1, (address)); + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_2 = abi.decode(ON_RAMP_ADDRESS_2, (address)); + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_3 = abi.decode(ON_RAMP_ADDRESS_3, (address)); + function setUp() public virtual override { super.setUp(); ICommitStore mockPrevCommitStore = new MockCommitStore(); s_prevOffRamp = _deploySingleLaneOffRamp( - mockPrevCommitStore, s_destRouter, address(0), SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1 + mockPrevCommitStore, s_destRouter, address(0), SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1 ); s_nestedPrevOffRamps = new EVM2EVMOffRampHelper[](2); s_nestedPrevOffRamps[0] = _deploySingleLaneOffRamp( - mockPrevCommitStore, s_destRouter, address(0), SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2 + mockPrevCommitStore, s_destRouter, address(0), SOURCE_CHAIN_SELECTOR_2, SINGLE_LANE_ON_RAMP_ADDRESS_2 ); s_nestedPrevOffRamps[1] = _deploySingleLaneOffRamp( - mockPrevCommitStore, s_destRouter, address(s_nestedPrevOffRamps[0]), SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2 + mockPrevCommitStore, + s_destRouter, + address(s_nestedPrevOffRamps[0]), + SOURCE_CHAIN_SELECTOR_2, + SINGLE_LANE_ON_RAMP_ADDRESS_2 ); NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](3); @@ -345,8 +353,9 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { previousRamps[1] = NonceManager.PreviousRampsArgs( SOURCE_CHAIN_SELECTOR_2, NonceManager.PreviousRamps(address(0), address(s_nestedPrevOffRamps[1])) ); - previousRamps[2] = - NonceManager.PreviousRampsArgs(SOURCE_CHAIN_SELECTOR_3, NonceManager.PreviousRamps(ON_RAMP_ADDRESS_3, address(0))); + previousRamps[2] = NonceManager.PreviousRampsArgs( + SOURCE_CHAIN_SELECTOR_3, NonceManager.PreviousRamps(SINGLE_LANE_ON_RAMP_ADDRESS_3, address(0)) + ); s_inboundNonceManager.applyPreviousRampsUpdates(previousRamps); EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = @@ -374,12 +383,13 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { } function test_Upgraded_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -388,23 +398,26 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { } function test_NoPrevOffRampForChain_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.EVM2EVMMessage[] memory messages = + _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); uint64 startNonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messages[0].sender)); - s_prevOffRamp.execute(_generateSingleRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_prevOffRamp.execute( + _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) + ); // Nonce unchanged for chain 3 assertEq( startNonceChain3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messages[0].sender)) ); - Internal.EVM2EVMMessage[] memory messagesChain3 = + Internal.Any2EVMRampMessage[] memory messagesChain3 = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_3, - messagesChain3[0].sequenceNumber, - messagesChain3[0].messageId, + messagesChain3[0].header.sequenceNumber, + messagesChain3[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -413,17 +426,19 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new uint256[](0) ); assertEq( - startNonceChain3 + 1, - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messagesChain3[0].sender)) + startNonceChain3 + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].sender) ); } function test_UpgradedSenderNoncesReadsPreviousRamp_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.EVM2EVMMessage[] memory messages = + _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); for (uint64 i = 1; i < 4; ++i) { - s_prevOffRamp.execute(_generateSingleRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_prevOffRamp.execute( + _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) + ); // messages contains a single message - update for the next execution messages[0].nonce++; @@ -437,12 +452,13 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { } function test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); + Internal.EVM2EVMMessage[] memory messages = + _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, SINGLE_LANE_ON_RAMP_ADDRESS_2); uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_2, abi.encode(messages[0].sender)); for (uint64 i = 1; i < 4; ++i) { s_nestedPrevOffRamps[0].execute( - _generateSingleRampReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new uint256[](0) + _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new uint256[](0) ); // messages contains a single message - update for the next execution @@ -458,122 +474,190 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { } function test_UpgradedNonceStartsAtV1Nonce_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.EVM2EVMMessage[] memory messages = + _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); - s_prevOffRamp.execute(_generateSingleRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_prevOffRamp.execute( + _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) + ); assertEq( startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) ); - messages[0].nonce++; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + Internal.Any2EVMRampMessage[] memory messagesMultiRamp = + _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); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) + ); assertEq( - startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) + startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) ); - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messagesMultiRamp[0].header.nonce++; + messagesMultiRamp[0].header.sequenceNumber++; + messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) + ); assertEq( - startNonce + 3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) + startNonce + 3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) ); } function test_UpgradedNonceNewSenderStartsAtZero_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.EVM2EVMMessage[] memory messages = + _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); + + s_prevOffRamp.execute( + _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) + ); - s_prevOffRamp.execute(_generateSingleRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + Internal.Any2EVMRampMessage[] memory messagesMultiRamp = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - address newSender = address(1234567); - messages[0].sender = newSender; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + bytes memory newSender = abi.encode(address(1234567)); + messagesMultiRamp[0].sender = newSender; + messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); // new sender nonce in new offramp should go from 0 -> 1 - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(newSender)), 0); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(newSender)), 1); + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) + ); + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 1); } function test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); address newSender = address(1234567); - messages[0].sender = newSender; - messages[0].nonce = 2; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].sender = abi.encode(newSender); + messages[0].header.nonce = 2; + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); // new offramp sees msg nonce higher than senderNonce // it waits for previous offramp to execute vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].nonce, abi.encode(newSender)); + 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)); - assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender))); + assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); + + Internal.EVM2EVMMessage[] memory messagesSingleLane = + _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); - messages[0].nonce = 1; - messages[0].messageId = Internal._hash(messages[0], s_prevOffRamp.metadataHash()); + messagesSingleLane[0].nonce = 1; + messagesSingleLane[0].sender = newSender; + messagesSingleLane[0].messageId = Internal._hash(messagesSingleLane[0], s_prevOffRamp.metadataHash()); // previous offramp executes msg and increases nonce - s_prevOffRamp.execute(_generateSingleRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_prevOffRamp.execute( + _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesSingleLane), new uint256[](0) + ); assertEq( - startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) + startNonce + 1, + s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messagesSingleLane[0].sender)) ); - messages[0].nonce = 2; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.nonce = 2; + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); // new offramp is able to execute vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - assertEq( - startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) + assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); + } + + function _generateSingleLaneRampReportFromMessages( + uint64 sourceChainSelector, + 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) { + offchainTokenData[i] = new bytes[](messages[i].tokenAmounts.length); + } + + return Internal.ExecutionReport({ + proofs: new bytes32[](0), + proofFlagBits: 2 ** 256 - 1, + messages: messages, + offchainTokenData: offchainTokenData + }); + } + + function _generateSingleLaneSingleBasicMessage( + uint64 sourceChainSelector, + address onRamp + ) internal view returns (Internal.EVM2EVMMessage[] memory) { + Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](1); + + bytes memory data = abi.encode(0); + messages[0] = Internal.EVM2EVMMessage({ + sequenceNumber: 1, + sender: OWNER, + nonce: 1, + gasLimit: GAS_LIMIT, + strict: false, + sourceChainSelector: sourceChainSelector, + receiver: address(s_receiver), + data: data, + tokenAmounts: new Client.EVMTokenAmount[](0), + sourceTokenData: new bytes[](0), + feeToken: s_destFeeToken, + feeTokenAmount: uint256(0), + messageId: "" + }); + + messages[0].messageId = Internal._hash( + messages[0], + keccak256(abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, sourceChainSelector, DEST_CHAIN_SELECTOR, onRamp)) ); + + return messages; } } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index d8cc6cc97c..1d9a99f182 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -14,7 +14,7 @@ import "../onRamp/EVM2EVMMultiOnRampSetup.t.sol"; /// 2. Commit multiple merkle roots (1 for each source chain). /// 3. Batch execute all the committed messages. contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { - using Internal for Internal.EVM2EVMMessage; + using Internal for Internal.Any2EVMRampMessage; Router internal s_sourceRouter2; EVM2EVMMultiOnRampHelper internal s_onRamp2; @@ -89,12 +89,13 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR, isEnabled: true, - onRamp: address(s_onRamp) + // Must match OnRamp address + onRamp: abi.encode(address(s_onRamp)) }); sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, isEnabled: true, - onRamp: address(s_onRamp2) + onRamp: abi.encode(address(s_onRamp2)) }); _setupMultipleOffRampsFromConfigs(sourceChainConfigs); @@ -108,10 +109,10 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { uint256 balance1Pre = token1.balanceOf(OWNER); // Send messages - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); + 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.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); messages2[0] = _sendRequest(1, SOURCE_CHAIN_SELECTOR + 1, 1, s_metadataHash2, s_sourceRouter2, s_tokenAdminRegistry2); @@ -124,13 +125,10 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { // Commit bytes32[] memory hashedMessages1 = new bytes32[](2); - hashedMessages1[0] = messages1[0]._hash(s_metadataHash); - messages1[0].messageId = hashedMessages1[0]; - hashedMessages1[1] = messages1[1]._hash(s_metadataHash); - messages1[1].messageId = hashedMessages1[1]; + 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(s_metadataHash2); - messages2[0].messageId = hashedMessages2[0]; + hashedMessages2[0] = messages2[0]._hash(abi.encode(address(s_onRamp2))); bytes32[] memory merkleRoots = new bytes32[](2); merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); @@ -139,12 +137,12 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](2); roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: EVM2EVMMultiOffRamp.Interval(messages1[0].sequenceNumber, messages1[1].sequenceNumber), + interval: EVM2EVMMultiOffRamp.Interval(messages1[0].header.sequenceNumber, messages1[1].header.sequenceNumber), merkleRoot: merkleRoots[0] }); roots[1] = EVM2EVMMultiOffRamp.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - interval: EVM2EVMMultiOffRamp.Interval(messages2[0].sequenceNumber, messages2[0].sequenceNumber), + interval: EVM2EVMMultiOffRamp.Interval(messages2[0].header.sequenceNumber, messages2[0].header.sequenceNumber), merkleRoot: merkleRoots[1] }); @@ -176,8 +174,8 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR, - messages1[0].sequenceNumber, - messages1[0].messageId, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -185,8 +183,8 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR, - messages1[1].sequenceNumber, - messages1[1].messageId, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -194,8 +192,8 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR + 1, - messages2[0].sequenceNumber, - messages2[0].messageId, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -215,7 +213,7 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { bytes32 metadataHash, Router router, TokenAdminRegistry tokenAdminRegistry - ) public returns (Internal.EVM2EVMMessage memory) { + ) public returns (Internal.Any2EVMRampMessage memory) { Client.EVM2AnyMessage memory message = _generateTokenMessage(); uint256 expectedFee = router.getFee(DEST_CHAIN_SELECTOR, message); @@ -242,6 +240,20 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - return msgEvent; + return Internal.Any2EVMRampMessage({ + header: Internal.RampMessageHeader({ + messageId: msgEvent.messageId, + sourceChainSelector: sourceChainSelector, + destChainSelector: DEST_CHAIN_SELECTOR, + sequenceNumber: msgEvent.sequenceNumber, + nonce: msgEvent.nonce + }), + sender: abi.encode(msgEvent.sender), + data: msgEvent.data, + receiver: msgEvent.receiver, + gasLimit: msgEvent.gasLimit, + tokenAmounts: msgEvent.tokenAmounts, + sourceTokenData: msgEvent.sourceTokenData + }); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol index 83b9569425..0e2202869e 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol @@ -26,10 +26,6 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { return s_executionStates[sourceChainSelector][bitmapIndex]; } - function metadataHash(uint64 sourceChainSelector, address onRamp) external view returns (bytes32) { - return _metadataHash(sourceChainSelector, onRamp, Internal.EVM_2_EVM_MESSAGE_HASH); - } - function releaseOrMintSingleToken( uint256 sourceTokenAmount, bytes calldata originalSender, @@ -57,7 +53,7 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { } function trialExecute( - Internal.EVM2EVMMessage memory message, + Internal.Any2EVMRampMessage memory message, bytes[] memory offchainTokenData ) external returns (Internal.MessageExecutionState, bytes memory) { return _trialExecute(message, offchainTokenData); diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol index fcb5819948..755b326c0d 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -1,11 +1,58 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -// MessageHasher is a contract that provides a function to hash an EVM2EVMMessage. +/// @notice MessageHasher is a contract that utility functions to hash an Any2EVMRampMessage +/// and encode various preimages for the final hash of the message. contract MessageHasher { - function hash(Internal.EVM2EVMMessage memory msg, bytes32 metadataHash) public pure returns (bytes32) { - return Internal._hash(msg, metadataHash); + function hash(Internal.Any2EVMRampMessage memory message, bytes memory onRamp) public pure returns (bytes32) { + return Internal._hash(message, onRamp); + } + + function encodeTokenAmountsHashPreimage(Client.EVMTokenAmount[] memory tokenAmounts) + public + pure + returns (bytes memory) + { + return abi.encode(tokenAmounts); + } + + function encodeSourceTokenDataHashPreimage(bytes[] memory sourceTokenData) public pure returns (bytes memory) { + return abi.encode(sourceTokenData); + } + + function encodeMetadataHashPreimage( + bytes32 any2EVMMessageHash, + uint64 sourceChainSelector, + uint64 destChainSelector, + bytes memory onRamp + ) public pure returns (bytes memory) { + return abi.encode(any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp); + } + + function encodeFixedSizeFieldsHashPreimage( + bytes32 messageId, + bytes memory sender, + address receiver, + uint64 sequenceNumber, + uint256 gasLimit, + uint64 nonce + ) public pure returns (bytes memory) { + return abi.encode(messageId, sender, receiver, sequenceNumber, gasLimit, nonce); + } + + function encodeFinalHashPreimage( + bytes32 leafDomainSeparator, + bytes32 implicitMetadataHash, + bytes32 fixedSizeFieldsHash, + bytes32 dataHash, + bytes32 tokenAmountsHash, + bytes32 sourceTokenDataHash + ) public pure returns (bytes memory) { + return abi.encode( + leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash + ); } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index edb27d1a74..c994cf5698 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -49,28 +49,20 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](2); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true }); sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, - isEnabled: true, - onRamp: address(uint160(ON_RAMP_ADDRESS_1) + 1) + onRamp: ON_RAMP_ADDRESS_2, + isEnabled: true }); - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig1 = EVM2EVMMultiOffRamp.SourceChainConfig({ - isEnabled: true, - minSeqNr: 1, - onRamp: sourceChainConfigs[0].onRamp, - metadataHash: s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, sourceChainConfigs[0].onRamp) - }); + EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig1 = + EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: true, minSeqNr: 1, onRamp: sourceChainConfigs[0].onRamp}); - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig2 = EVM2EVMMultiOffRamp.SourceChainConfig({ - isEnabled: true, - minSeqNr: 1, - onRamp: sourceChainConfigs[1].onRamp, - metadataHash: s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1 + 1, sourceChainConfigs[1].onRamp) - }); + EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig2 = + EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: true, minSeqNr: 1, onRamp: sourceChainConfigs[1].onRamp}); vm.expectEmit(); emit EVM2EVMMultiOffRamp.StaticConfigSet(staticConfig); @@ -148,8 +140,8 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: address(0) + onRamp: new bytes(0), + isEnabled: true }); vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); @@ -172,7 +164,7 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = - EVM2EVMMultiOffRamp.SourceChainConfigArgs({sourceChainSelector: 0, isEnabled: true, onRamp: address(0)}); + EVM2EVMMultiOffRamp.SourceChainConfigArgs({sourceChainSelector: 0, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true}); vm.expectRevert(EVM2EVMMultiOffRamp.ZeroChainSelectorNotAllowed.selector); @@ -326,74 +318,6 @@ contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { } } -contract EVM2EVMMultiOffRamp_metadataHash is EVM2EVMMultiOffRampSetup { - function test_MetadataHash_Success() public view { - bytes32 h = s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - assertEq( - h, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR_1, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS_1) - ) - ); - } - - function test_MetadataHashChangesOnSourceChain_Success() public view { - bytes32 h = s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1 + 1, ON_RAMP_ADDRESS_1); - assertEq( - h, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR_1 + 1, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS_1) - ) - ); - assertTrue(h != s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); - } - - function test_MetadataHashChangesOnOnRampAddress_Success() public view { - address mockOnRampAddress = address(uint160(ON_RAMP_ADDRESS_1) + 1); - bytes32 h = s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, mockOnRampAddress); - assertEq( - h, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR_1, DEST_CHAIN_SELECTOR, mockOnRampAddress) - ) - ); - assertTrue(h != s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); - } - - // NOTE: to get a reliable result, set fuzz runs to at least 1mil - /// forge-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 10000 - function test_Fuzz__MetadataHash_NoCollisions( - uint64 destChainSelector, - uint64 sourceChainSelector1, - uint64 sourceChainSelector2, - address onRamp1, - address onRamp2 - ) public { - // Edge case: metadata hash should be the same when values match - if (sourceChainSelector1 == sourceChainSelector2 && onRamp1 == onRamp2) { - return; - } - - // Disallow 0 source chain selectors - vm.assume(sourceChainSelector1 != 0); - vm.assume(sourceChainSelector2 != 0); - vm.assume(destChainSelector != 0); - - EVM2EVMMultiOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); - - staticConfig.chainSelector = destChainSelector; - s_offRamp = new EVM2EVMMultiOffRampHelper(staticConfig, sourceChainConfigs); - - bytes32 h1 = s_offRamp.metadataHash(sourceChainSelector1, onRamp1); - bytes32 h2 = s_offRamp.metadataHash(sourceChainSelector2, onRamp2); - - assertTrue(h1 != h2); - } -} - contract EVM2EVMMultiOffRamp_ccipReceive is EVM2EVMMultiOffRampSetup { // Reverts @@ -414,114 +338,109 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { } function test_SingleMessageNoTokens_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - messages[0].nonce++; - messages[0].sequenceNumber++; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.nonce++; + messages[0].header.sequenceNumber++; + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); - assertGt( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)), nonceBefore - ); + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } function test_SingleMessageNoTokensUnordered_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].nonce = 0; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + 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); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); // Nonce never increments on unordered messages. - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); assertEq( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)), + s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore, "nonce must remain unchanged on unordered messages" ); - messages[0].sequenceNumber++; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.sequenceNumber++; + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); // Nonce never increments on unordered messages. - nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); + nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); assertEq( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)), + s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore, "nonce must remain unchanged on unordered messages" ); } function test_SingleMessageNoTokensOtherChain_Success() public { - Internal.EVM2EVMMessage[] memory messagesChain1 = + 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) ); - uint64 nonceChain1 = - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messagesChain1[0].sender)); + uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender); assertGt(nonceChain1, 0); - Internal.EVM2EVMMessage[] memory messagesChain2 = + Internal.Any2EVMRampMessage[] memory messagesChain2 = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messagesChain2[0].sender)), 0); + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); s_offRamp.executeSingleReport( _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain2), new uint256[](0) ); - assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messagesChain2[0].sender)), 0); + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); // Other chain's nonce is unaffected - assertEq( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messagesChain1[0].sender)), nonceChain1 - ); + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender), nonceChain1); } function test_ReceiverError_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); bytes memory realError1 = new bytes(2); realError1[0] = 0xbe; @@ -529,14 +448,13 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_reverting_receiver.setErr(realError1); messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( EVM2EVMMultiOffRamp.ReceiverError.selector, @@ -550,50 +468,51 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { } function test_SkippedIncorrectNonce_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].nonce++; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.nonce++; + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit NonceManager.SkippedIncorrectNonce( - messages[0].sourceChainSelector, messages[0].nonce, abi.encode(messages[0].sender) + messages[0].header.sourceChainSelector, messages[0].header.nonce, messages[0].sender ); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } function test_SkippedIncorrectNonceStillExecutes_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[1].nonce++; - messages[1].messageId = - Internal._hash(messages[1], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[1].header.nonce++; + messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].nonce, abi.encode(messages[1].sender)); + emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].header.nonce, messages[1].sender); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } - function test_execute_SkippedAlreadyExecutedMessage_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + function test__execute_SkippedAlreadyExecutedMessage_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -601,22 +520,22 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].sequenceNumber); + emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].nonce = 0; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + 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); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -624,7 +543,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].sequenceNumber); + emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } @@ -632,17 +551,17 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { // Send a message to a contract that does not implement the CCIPReceiver interface // This should execute successfully. function test_SingleMessageToNonCCIPReceiver_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); messages[0].receiver = address(newReceiver); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -652,13 +571,14 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { function test_SingleMessagesNoTokensSuccess_gas() public { vm.pauseGasMetering(); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -671,17 +591,17 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { function test_TwoMessagesWithTokensSuccess_gas() public { vm.pauseGasMetering(); - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _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].messageId = - Internal._hash(messages[1], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -689,8 +609,8 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[1].sequenceNumber, - messages[1].messageId, + messages[1].header.sequenceNumber, + messages[1].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -702,17 +622,17 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { } function test_TwoMessagesWithTokensAndGE_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _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].messageId = - Internal._hash(messages[1], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -720,8 +640,8 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[1].sequenceNumber, - messages[1].messageId, + messages[1].header.sequenceNumber, + messages[1].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -734,7 +654,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { } function test_Fuzz_InterleavingOrderedAndUnorderedMessages_Success(bool[7] memory orderings) public { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](orderings.length); + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](orderings.length); // number of tokens needs to be capped otherwise we hit UnsupportedNumberOfTokens. Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](3); for (uint256 i = 0; i < 3; ++i) { @@ -746,16 +666,15 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { messages[i] = _generateAny2EVMMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, uint64(i + 1), tokenAmounts, !orderings[i]); if (orderings[i]) { - messages[i].nonce = ++expectedNonce; + messages[i].header.nonce = ++expectedNonce; } - messages[i].messageId = - Internal._hash(messages[i], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[i].header.messageId = Internal._hash(messages[i], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[i].sequenceNumber, - messages[i].messageId, + messages[i].header.sequenceNumber, + messages[i].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -769,7 +688,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { // all executions should succeed. for (uint256 i = 0; i < orderings.length; ++i) { assertEq( - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, messages[i].sequenceNumber)), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, messages[i].header.sequenceNumber)), uint256(Internal.MessageExecutionState.SUCCESS) ); } @@ -781,7 +700,8 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { function test_InvalidSourcePoolAddress_Success() public { address fakePoolAddress = address(0x0000000000333333); - Internal.EVM2EVMMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].sourceTokenData[0] = abi.encode( Internal.SourceTokenData({ sourcePoolAddress: abi.encode(fakePoolAddress), @@ -790,16 +710,14 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { }) ); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); - messages[1].messageId = - Internal._hash(messages[1], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( EVM2EVMMultiOffRamp.TokenHandlingError.selector, @@ -822,34 +740,37 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { // Reverts - function test_InvalidMessageId_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].nonce++; - // MessageID no longer matches hash. - Internal.ExecutionReportSingleChain memory executionReport = - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidMessageId.selector, messages[0].messageId)); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); - } + function test_MismatchingDestChainSelector_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); + messages[0].header.destChainSelector = DEST_CHAIN_SELECTOR + 1; - function test_MismatchingSourceChainSelector_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - messages[0].sourceChainSelector = SOURCE_CHAIN_SELECTOR_1; - // MessageID no longer matches hash. Internal.ExecutionReportSingleChain memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidMessageId.selector, messages[0].messageId)); + + vm.expectRevert( + abi.encodeWithSelector( + EVM2EVMMultiOffRamp.InvalidMessageDestChainSelector.selector, messages[0].header.destChainSelector + ) + ); s_offRamp.executeSingleReport(executionReport, new uint256[](0)); } - function test_MismatchingOnRampAddress_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_3)); - // MessageID no longer matches hash. + 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); + + EVM2EVMMultiOffRamp.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(EVM2EVMMultiOffRamp.InvalidMessageId.selector, messages[0].messageId)); + vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); s_offRamp.executeSingleReport(executionReport, new uint256[](0)); } @@ -909,7 +830,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, proofs: new bytes32[](0), proofFlagBits: 0, - messages: new Internal.EVM2EVMMessage[](0), + messages: new Internal.Any2EVMRampMessage[](0), offchainTokenData: new bytes[][](0) }), new uint256[](0) @@ -920,7 +841,8 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); s_offRamp.executeSingleReport( _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) ); @@ -933,7 +855,8 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { abi.encodeWithSelector(EVM2EVMMultiOffRamp.ManualExecutionNotYetEnabled.selector, SOURCE_CHAIN_SELECTOR_1) ); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); s_offRamp.executeSingleReport( _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) ); @@ -941,43 +864,45 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { function test_NonExistingSourceChain_Revert() public { uint64 newSourceChainSelector = SOURCE_CHAIN_SELECTOR_1 + 1; - address newOnRamp = address(uint160(ON_RAMP_ADDRESS_1) + 1); + bytes memory newOnRamp = abi.encode(ON_RAMP_ADDRESS, 1); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(newSourceChainSelector, newOnRamp); + Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(newSourceChainSelector, newOnRamp); vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.SourceChainNotEnabled.selector, newSourceChainSelector)); s_offRamp.executeSingleReport(_generateReportFromMessages(newSourceChainSelector, messages), new uint256[](0)); } function test_DisabledSourceChain_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.SourceChainNotEnabled.selector, SOURCE_CHAIN_SELECTOR_2)); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new uint256[](0)); } function test_TokenDataMismatch_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); report.offchainTokenData[0] = new bytes[](messages[0].tokenAmounts.length + 1); vm.expectRevert( abi.encodeWithSelector( - EVM2EVMMultiOffRamp.TokenDataMismatch.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].sequenceNumber + EVM2EVMMultiOffRamp.TokenDataMismatch.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber ) ); s_offRamp.executeSingleReport(report, new uint256[](0)); } function test_RouterYULCall_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); // 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].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -985,7 +910,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { vm.expectRevert( abi.encodeWithSelector( EVM2EVMMultiOffRamp.ExecutionError.selector, - messages[0].messageId, + messages[0].header.messageId, abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector) ) ); @@ -993,7 +918,8 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { } function test_RetryFailedMessageWithoutManualExecution_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); bytes memory realError1 = new bytes(2); realError1[0] = 0xbe; @@ -1001,14 +927,13 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_reverting_receiver.setErr(realError1); messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( EVM2EVMMultiOffRamp.ReceiverError.selector, @@ -1019,11 +944,25 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { vm.expectRevert( abi.encodeWithSelector( - EVM2EVMMultiOffRamp.AlreadyAttempted.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].sequenceNumber + EVM2EVMMultiOffRamp.AlreadyAttempted.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber ) ); s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); } + + function _constructCommitReport(bytes32 merkleRoot) internal view returns (EVM2EVMMultiOffRamp.CommitReport memory) { + EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); + roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + interval: EVM2EVMMultiOffRamp.Interval(1, 2), + merkleRoot: merkleRoot + }); + + return EVM2EVMMultiOffRamp.CommitReport({ + priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots + }); + } } contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { @@ -1034,13 +973,14 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { } function test_executeSingleMessage_NoTokens_Success() public { - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); } function test_executeSingleMessage_WithTokens_Success() public { - Internal.EVM2EVMMessage memory message = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; + Internal.Any2EVMRampMessage memory message = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); Internal.SourceTokenData memory sourceTokenData = abi.decode(message.sourceTokenData[0], (Internal.SourceTokenData)); @@ -1049,7 +989,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { abi.encodeWithSelector( LockReleaseTokenPool.releaseOrMint.selector, Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(message.sender), + originalSender: message.sender, receiver: message.receiver, amount: message.tokenAmounts[0].amount, localToken: s_destTokenBySourceToken[message.tokenAmounts[0].token], @@ -1069,13 +1009,13 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { vm.startPrank(OWNER); _enableInboundMessageValidator(); vm.startPrank(address(s_offRamp)); - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); } function test_NonContract_Success() public { - Internal.EVM2EVMMessage memory message = + 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)); @@ -1089,7 +1029,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { emit TokenPool.Released(address(s_offRamp), STRANGER, amounts[0]); vm.expectEmit(); emit TokenPool.Minted(address(s_offRamp), STRANGER, amounts[1]); - Internal.EVM2EVMMessage memory message = + 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)); @@ -1104,7 +1044,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { bytes memory errorMessage = "Random token pool issue"; - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); @@ -1114,7 +1054,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { } function test_ZeroGasDONExecution_Revert() public { - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.gasLimit = 0; @@ -1125,7 +1065,7 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { function test_MessageSender_Revert() public { vm.stopPrank(); - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); vm.expectRevert(EVM2EVMMultiOffRamp.CanOnlySelfCall.selector); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); @@ -1136,9 +1076,9 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { vm.startPrank(OWNER); _enableInboundMessageValidator(); vm.startPrank(address(s_offRamp)); - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_inboundMessageValidator.setMessageIdValidationState(message.messageId, true); + s_inboundMessageValidator.setMessageIdValidationState(message.header.messageId, true); vm.expectRevert( abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -1154,15 +1094,15 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { _enableInboundMessageValidator(); vm.startPrank(address(s_offRamp)); - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); // 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.messageId = Internal._hash(message, s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); - s_inboundMessageValidator.setMessageIdValidationState(message.messageId, true); + s_inboundMessageValidator.setMessageIdValidationState(message.header.messageId, true); vm.expectRevert( abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -1182,27 +1122,26 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { } function test_SingleReport_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); - assertGt( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)), nonceBefore - ); + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } function test_MultipleReportsSameChain_Success() public { - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); - Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + 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); @@ -1214,41 +1153,39 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[0].sourceChainSelector, - messages1[0].sequenceNumber, - messages1[0].messageId, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[1].sourceChainSelector, - messages1[1].sequenceNumber, - messages1[1].messageId, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages2[0].sourceChainSelector, - messages2[0].sequenceNumber, - messages2[0].messageId, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages1[0].sender)); + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); s_offRamp.batchExecute(reports, new uint256[][](2)); - assertGt( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages1[0].sender)), nonceBefore - ); + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender), nonceBefore); } function test_MultipleReportsDifferentChains_Success() public { - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); - Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + 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); @@ -1260,35 +1197,35 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[0].sourceChainSelector, - messages1[0].sequenceNumber, - messages1[0].messageId, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[1].sourceChainSelector, - messages1[1].sequenceNumber, - messages1[1].messageId, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages2[0].sourceChainSelector, - messages2[0].sequenceNumber, - messages2[0].messageId, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); s_offRamp.batchExecute(reports, new uint256[][](2)); - uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages1[0].sender)); - uint64 nonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messages2[0].sender)); + uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); + uint64 nonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messages2[0].sender); assertTrue(nonceChain1 != nonceChain3); assertGt(nonceChain1, 0); @@ -1296,7 +1233,8 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { } function test_MultipleReportsSkipDuplicate_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -1304,15 +1242,15 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].sequenceNumber); + emit EVM2EVMMultiOffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); s_offRamp.batchExecute(reports, new uint256[][](2)); } @@ -1343,8 +1281,8 @@ contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { } function test_OutOfBoundsGasLimitsAccess_Revert() public { - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); - Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + 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); @@ -1369,10 +1307,10 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_manuallyExecute_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + 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_reverting_receiver.setRevert(false); @@ -1380,8 +1318,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1392,10 +1330,10 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_manuallyExecute_WithGasOverride_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + 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_reverting_receiver.setRevert(false); @@ -1403,8 +1341,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1417,14 +1355,13 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_manuallyExecute_DoesNotRevertIfUntouched_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); assertEq( - messages[0].nonce - 1, - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) + messages[0].header.nonce - 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) ); s_reverting_receiver.setRevert(true); @@ -1432,8 +1369,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( EVM2EVMMultiOffRamp.ReceiverError.selector, @@ -1447,26 +1384,24 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); assertEq( - messages[0].nonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) + messages[0].header.nonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) ); } function test_manuallyExecute_WithMultiReportGasOverride_Success() public { - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](3); - Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](2); + 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].messageId = - Internal._hash(messages1[i], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + 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].messageId = - Internal._hash(messages2[i], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3)); + messages2[i].header.messageId = Internal._hash(messages2[i], ON_RAMP_ADDRESS_3); } Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); @@ -1485,8 +1420,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages1[i].sequenceNumber, - messages1[i].messageId, + messages1[i].header.sequenceNumber, + messages1[i].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1498,8 +1433,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_3, - messages2[i].sequenceNumber, - messages2[i].messageId, + messages2[i].header.sequenceNumber, + messages2[i].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1511,20 +1446,19 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_manuallyExecute_WithPartialMessages_Success() public { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](3); + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); for (uint64 i = 0; i < 3; ++i) { messages[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); } messages[1].receiver = address(s_reverting_receiver); - messages[1].messageId = - Internal._hash(messages[1], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1532,8 +1466,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[1].sequenceNumber, - messages[1].messageId, + messages[1].header.sequenceNumber, + messages[1].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( EVM2EVMMultiOffRamp.ReceiverError.selector, @@ -1544,8 +1478,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[2].sequenceNumber, - messages[2].messageId, + messages[2].header.sequenceNumber, + messages[2].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1555,7 +1489,7 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { s_reverting_receiver.setRevert(false); // Only the 2nd message reverted - Internal.EVM2EVMMessage[] memory newMessages = new Internal.EVM2EVMMessage[](1); + Internal.Any2EVMRampMessage[] memory newMessages = new Internal.Any2EVMRampMessage[](1); newMessages[0] = messages[1]; uint256[][] memory gasLimitOverrides = new uint256[][](1); @@ -1565,8 +1499,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - newMessages[0].sequenceNumber, - newMessages[0].messageId, + newMessages[0].header.sequenceNumber, + newMessages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1575,17 +1509,17 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_manuallyExecute_LowGasLimit_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _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].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector(EVM2EVMMultiOffRamp.ReceiverError.selector, "") ); @@ -1601,8 +1535,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1612,7 +1546,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { // Reverts function test_manuallyExecute_ForkedChain_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -1628,7 +1563,7 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_ManualExecGasLimitMismatchSingleReport_Revert() public { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](2); + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); @@ -1659,8 +1594,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() public { - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); - Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + 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); @@ -1702,7 +1637,8 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_ManualExecInvalidGasLimit_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); uint256[][] memory gasLimitOverrides = new uint256[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); @@ -1717,11 +1653,11 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } function test_manuallyExecute_FailedTx_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); @@ -1733,7 +1669,7 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { vm.expectRevert( abi.encodeWithSelector( EVM2EVMMultiOffRamp.ExecutionError.selector, - messages[0].messageId, + messages[0].header.messageId, abi.encodeWithSelector( EVM2EVMMultiOffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) @@ -1755,10 +1691,10 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { // For this test any message will be flagged as correct by the // commitStore. In a real scenario the abuser would have to actually // send the message that they want to replay. - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].tokenAmounts = new Client.EVMTokenAmount[](1); messages[0].tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: tokenAmount}); - messages[0].receiver = address(receiver); messages[0].sourceTokenData = new bytes[](1); messages[0].sourceTokenData[0] = abi.encode( Internal.SourceTokenData({ @@ -1768,8 +1704,9 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { }) ); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + messages[0].receiver = address(receiver); + + messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -1784,14 +1721,16 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { // This means the first tx is marked `FAILURE` with the error message of the second tx. vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages[0].sourceChainSelector, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( EVM2EVMMultiOffRamp.ReceiverError.selector, abi.encodeWithSelector( - EVM2EVMMultiOffRamp.AlreadyExecuted.selector, messages[0].sourceChainSelector, messages[0].sequenceNumber + EVM2EVMMultiOffRamp.AlreadyExecuted.selector, + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber ) ) ); @@ -1812,15 +1751,16 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { // Asserts that execute completes function test_SingleReport_Success() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, + messages[0].header.sequenceNumber, + messages[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1834,8 +1774,8 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { } function test_MultipleReports_Success() public { - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); - Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + 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); @@ -1847,27 +1787,27 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[0].sourceChainSelector, - messages1[0].sequenceNumber, - messages1[0].messageId, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[1].sourceChainSelector, - messages1[1].sequenceNumber, - messages1[1].messageId, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages2[0].sourceChainSelector, - messages2[0].sequenceNumber, - messages2[0].messageId, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1883,7 +1823,7 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { function test_LargeBatch_Success() public { Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](10); for (uint64 i = 0; i < reports.length; ++i) { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](3); + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1 + i * 3); messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2 + i * 3); messages[2] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3 + i * 3); @@ -1895,9 +1835,9 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { for (uint64 j = 0; j < reports[i].messages.length; ++j) { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - reports[i].messages[j].sourceChainSelector, - reports[i].messages[j].sequenceNumber, - reports[i].messages[j].messageId, + reports[i].messages[j].header.sourceChainSelector, + reports[i].messages[j].header.sequenceNumber, + reports[i].messages[j].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); @@ -1915,8 +1855,8 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { function test_MultipleReportsWithPartialValidationFailures_Success() public { _enableInboundMessageValidator(); - Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); - Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + 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); @@ -1926,14 +1866,14 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); - s_inboundMessageValidator.setMessageIdValidationState(messages1[0].messageId, true); - s_inboundMessageValidator.setMessageIdValidationState(messages2[0].messageId, true); + s_inboundMessageValidator.setMessageIdValidationState(messages1[0].header.messageId, true); + s_inboundMessageValidator.setMessageIdValidationState(messages2[0].header.messageId, true); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[0].sourceChainSelector, - messages1[0].sequenceNumber, - messages1[0].messageId, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -1943,18 +1883,18 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages1[1].sourceChainSelector, - messages1[1].sequenceNumber, - messages1[1].messageId, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, Internal.MessageExecutionState.SUCCESS, "" ); vm.expectEmit(); emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - messages2[0].sourceChainSelector, - messages2[0].sequenceNumber, - messages2[0].messageId, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -1975,7 +1915,8 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { function test_UnauthorizedTransmitter_Revert() public { bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -1987,7 +1928,8 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -2013,7 +1955,8 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { }); s_offRamp.setOCR3Configs(ocrConfigs); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -2041,7 +1984,8 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { }); s_offRamp.setOCR3Configs(ocrConfigs); - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -2070,7 +2014,8 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { function test_NonArray_Revert() public { bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.startPrank(s_validTransmitters[0]); @@ -2242,7 +2187,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { amounts[0] = 1000; amounts[1] = 50; - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); IERC20 dstToken0 = IERC20(s_destTokens[0]); uint256 startingBalance = dstToken0.balanceOf(message.receiver); @@ -2266,7 +2211,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { bytes memory errorMessage = "Random token pool issue"; - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); @@ -2286,7 +2231,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { bytes memory errorMessage = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); @@ -2300,7 +2245,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { function test_TokenPoolIsNotAContract_Success() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 10000; - Internal.EVM2EVMMessage memory message = + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); // Happy path, pool is correct @@ -2320,12 +2265,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { }) ); - message.messageId = Internal._hash( - message, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR_1, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS_1) - ) - ); + 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)); @@ -2343,12 +2283,7 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { }) ); - message.messageId = Internal._hash( - message, - keccak256( - abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR_1, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS_1) - ) - ); + message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); @@ -2743,17 +2678,13 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 - }); - - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = EVM2EVMMultiOffRamp.SourceChainConfig({ - isEnabled: true, - minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1, - metadataHash: s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + isEnabled: true }); + EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = + EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); + vm.expectEmit(); emit EVM2EVMMultiOffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); @@ -2770,19 +2701,15 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true }); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); sourceChainConfigs[0].isEnabled = false; - EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = EVM2EVMMultiOffRamp.SourceChainConfig({ - isEnabled: false, - minSeqNr: 1, - onRamp: sourceChainConfigs[0].onRamp, - metadataHash: s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, sourceChainConfigs[0].onRamp) - }); + EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = + EVM2EVMMultiOffRamp.SourceChainConfig({isEnabled: false, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); vm.expectEmit(); emit EVM2EVMMultiOffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); @@ -2806,18 +2733,18 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](3); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 + onRamp: abi.encode(ON_RAMP_ADDRESS_1, 0), + isEnabled: true }); sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, - isEnabled: false, - onRamp: address(uint160(ON_RAMP_ADDRESS_1) + 7) + onRamp: abi.encode(ON_RAMP_ADDRESS_1, 1), + isEnabled: false }); sourceChainConfigs[2] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 2, - isEnabled: true, - onRamp: address(uint160(ON_RAMP_ADDRESS_1) + 42) + onRamp: abi.encode(ON_RAMP_ADDRESS_1, 2), + isEnabled: true }); EVM2EVMMultiOffRamp.SourceChainConfig[] memory expectedSourceChainConfigs = @@ -2826,8 +2753,7 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam expectedSourceChainConfigs[i] = EVM2EVMMultiOffRamp.SourceChainConfig({ isEnabled: sourceChainConfigs[i].isEnabled, minSeqNr: 1, - onRamp: sourceChainConfigs[i].onRamp, - metadataHash: s_offRamp.metadataHash(sourceChainConfigs[i].sourceChainSelector, sourceChainConfigs[i].onRamp) + onRamp: abi.encode(ON_RAMP_ADDRESS_1, i) }); vm.expectEmit(); @@ -2841,15 +2767,10 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - // uint64[] memory resultSourceChainSelectors = s_offRamp.getSourceChainSelectors(); - // assertEq(resultSourceChainSelectors.length, 3); - for (uint256 i = 0; i < 3; ++i) { _assertSourceChainConfigEquality( s_offRamp.getSourceChainConfig(sourceChainConfigs[i].sourceChainSelector), expectedSourceChainConfigs[i] ); - - // assertEq(resultSourceChainSelectors[i], sourceChainConfigs[i].sourceChainSelector); } } @@ -2858,29 +2779,27 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam ) public { // Skip invalid inputs vm.assume(sourceChainConfigArgs.sourceChainSelector != 0); - vm.assume(sourceChainConfigArgs.onRamp != address(0)); + vm.assume(sourceChainConfigArgs.onRamp.length != 0); EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](2); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true }); sourceChainConfigs[1] = sourceChainConfigArgs; // Handle cases when an update occurs - bool isNewChain = true; - if (sourceChainConfigs[1].sourceChainSelector == SOURCE_CHAIN_SELECTOR_1) { + bool isNewChain = sourceChainConfigs[1].sourceChainSelector != SOURCE_CHAIN_SELECTOR_1; + if (!isNewChain) { sourceChainConfigs[1].onRamp = sourceChainConfigs[0].onRamp; - isNewChain = false; } EVM2EVMMultiOffRamp.SourceChainConfig memory expectedSourceChainConfig = EVM2EVMMultiOffRamp.SourceChainConfig({ isEnabled: sourceChainConfigArgs.isEnabled, minSeqNr: 1, - onRamp: sourceChainConfigArgs.onRamp, - metadataHash: s_offRamp.metadataHash(sourceChainConfigArgs.sourceChainSelector, sourceChainConfigArgs.onRamp) + onRamp: sourceChainConfigArgs.onRamp }); if (isNewChain) { @@ -2905,8 +2824,8 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: address(0) + onRamp: new bytes(0), + isEnabled: true }); vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); @@ -2917,7 +2836,7 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = - EVM2EVMMultiOffRamp.SourceChainConfigArgs({sourceChainSelector: 0, isEnabled: true, onRamp: ON_RAMP_ADDRESS_1}); + EVM2EVMMultiOffRamp.SourceChainConfigArgs({sourceChainSelector: 0, onRamp: ON_RAMP_ADDRESS_1, isEnabled: true}); vm.expectRevert(EVM2EVMMultiOffRamp.ZeroChainSelectorNotAllowed.selector); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); @@ -2928,30 +2847,13 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 - }); - - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - sourceChainConfigs[0].onRamp = address(uint160(sourceChainConfigs[0].onRamp) + 1); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidStaticConfig.selector, SOURCE_CHAIN_SELECTOR_1)); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - } - - function test_ReplaceExistingChainOnRampAndPrevOffRamp_Revert() public { - EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = - new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true }); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - sourceChainConfigs[0].onRamp = address(uint160(sourceChainConfigs[0].onRamp) + 1); + sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidStaticConfig.selector, SOURCE_CHAIN_SELECTOR_1)); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol index e5d882b10e..7355d6a072 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol @@ -35,9 +35,9 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba uint64 internal constant SOURCE_CHAIN_SELECTOR_2 = 6433500567565415381; uint64 internal constant SOURCE_CHAIN_SELECTOR_3 = 4051577828743386545; - address internal constant ON_RAMP_ADDRESS_1 = ON_RAMP_ADDRESS; - address internal constant ON_RAMP_ADDRESS_2 = 0xaA3f843Cf8E33B1F02dd28303b6bD87B1aBF8AE4; - address internal constant ON_RAMP_ADDRESS_3 = 0x71830C37Cb193e820de488Da111cfbFcC680a1b9; + bytes internal constant ON_RAMP_ADDRESS_1 = abi.encode(ON_RAMP_ADDRESS); + bytes internal constant ON_RAMP_ADDRESS_2 = abi.encode(0xaA3f843Cf8E33B1F02dd28303b6bD87B1aBF8AE4); + bytes internal constant ON_RAMP_ADDRESS_3 = abi.encode(0x71830C37Cb193e820de488Da111cfbFcC680a1b9); address internal constant BLESS_VOTE_ADDR = address(8888); @@ -175,18 +175,18 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](3); sourceChainConfigs[0] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true }); sourceChainConfigs[1] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, - isEnabled: false, - onRamp: ON_RAMP_ADDRESS_2 + onRamp: ON_RAMP_ADDRESS_2, + isEnabled: false }); sourceChainConfigs[2] = EVM2EVMMultiOffRamp.SourceChainConfigArgs({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_3 + onRamp: ON_RAMP_ADDRESS_3, + isEnabled: true }); _setupMultipleOffRampsFromConfigs(sourceChainConfigs); } @@ -196,14 +196,12 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](sourceChainConfigs.length); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2 * onRampUpdates.length); + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2 * sourceChainConfigs.length); for (uint256 i = 0; i < sourceChainConfigs.length; ++i) { uint64 sourceChainSelector = sourceChainConfigs[i].sourceChainSelector; - onRampUpdates[i] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: sourceChainConfigs[i].onRamp}); - offRampUpdates[2 * i] = Router.OffRamp({sourceChainSelector: sourceChainSelector, offRamp: address(s_offRamp)}); offRampUpdates[2 * i + 1] = Router.OffRamp({ sourceChainSelector: sourceChainSelector, @@ -243,7 +241,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba }); } - function _convertToGeneralMessage(Internal.EVM2EVMMessage memory original) + function _convertToGeneralMessage(Internal.Any2EVMRampMessage memory original) internal view returns (Client.Any2EVMMessage memory message) @@ -262,8 +260,8 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba } return Client.Any2EVMMessage({ - messageId: original.messageId, - sourceChainSelector: original.sourceChainSelector, + messageId: original.header.messageId, + sourceChainSelector: original.header.sourceChainSelector, sender: abi.encode(original.sender), data: original.data, destTokenAmounts: destTokenAmounts @@ -272,18 +270,18 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba function _generateAny2EVMMessageNoTokens( uint64 sourceChainSelector, - address onRamp, + bytes memory onRamp, uint64 sequenceNumber - ) internal view returns (Internal.EVM2EVMMessage memory) { + ) internal view returns (Internal.Any2EVMRampMessage memory) { return _generateAny2EVMMessage(sourceChainSelector, onRamp, sequenceNumber, new Client.EVMTokenAmount[](0), false); } function _generateAny2EVMMessageWithTokens( uint64 sourceChainSelector, - address onRamp, + bytes memory onRamp, uint64 sequenceNumber, uint256[] memory amounts - ) internal view returns (Internal.EVM2EVMMessage memory) { + ) internal view returns (Internal.Any2EVMRampMessage memory) { Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); for (uint256 i = 0; i < tokenAmounts.length; ++i) { tokenAmounts[i].amount = amounts[i]; @@ -293,26 +291,26 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba function _generateAny2EVMMessage( uint64 sourceChainSelector, - address onRamp, + bytes memory onRamp, uint64 sequenceNumber, Client.EVMTokenAmount[] memory tokenAmounts, bool allowOutOfOrderExecution - ) internal view returns (Internal.EVM2EVMMessage memory) { + ) internal view returns (Internal.Any2EVMRampMessage memory) { bytes memory data = abi.encode(0); - Internal.EVM2EVMMessage memory message = Internal.EVM2EVMMessage({ - sequenceNumber: sequenceNumber, - sender: OWNER, - nonce: allowOutOfOrderExecution ? 0 : sequenceNumber, - gasLimit: GAS_LIMIT, - strict: false, - sourceChainSelector: sourceChainSelector, - receiver: address(s_receiver), + Internal.Any2EVMRampMessage memory message = Internal.Any2EVMRampMessage({ + header: Internal.RampMessageHeader({ + messageId: "", + sourceChainSelector: sourceChainSelector, + destChainSelector: DEST_CHAIN_SELECTOR, + sequenceNumber: sequenceNumber, + nonce: allowOutOfOrderExecution ? 0 : sequenceNumber + }), + sender: abi.encode(OWNER), data: data, + receiver: address(s_receiver), tokenAmounts: tokenAmounts, sourceTokenData: new bytes[](tokenAmounts.length), - feeToken: s_destFeeToken, - feeTokenAmount: uint256(0), - messageId: "" + gasLimit: GAS_LIMIT }); // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. @@ -326,27 +324,25 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba ); } - message.messageId = Internal._hash( - message, keccak256(abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, sourceChainSelector, DEST_CHAIN_SELECTOR, onRamp)) - ); + message.header.messageId = Internal._hash(message, onRamp); return message; } function _generateSingleBasicMessage( uint64 sourceChainSelector, - address onRamp - ) internal view returns (Internal.EVM2EVMMessage[] memory) { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](1); + bytes memory onRamp + ) internal view returns (Internal.Any2EVMRampMessage[] memory) { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); messages[0] = _generateAny2EVMMessageNoTokens(sourceChainSelector, onRamp, 1); return messages; } function _generateMessagesWithTokens( uint64 sourceChainSelector, - address onRamp - ) internal view returns (Internal.EVM2EVMMessage[] memory) { - Internal.EVM2EVMMessage[] memory messages = new Internal.EVM2EVMMessage[](2); + bytes memory onRamp + ) internal view returns (Internal.Any2EVMRampMessage[] memory) { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); Client.EVMTokenAmount[] memory tokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); tokenAmounts[0].amount = 1e18; tokenAmounts[1].amount = 5e18; @@ -356,24 +352,9 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba return messages; } - function _generateSingleRampReportFromMessages( - uint64 sourceChainSelector, - Internal.EVM2EVMMessage[] memory messages - ) internal pure returns (Internal.ExecutionReport memory) { - Internal.ExecutionReportSingleChain memory singleChainReport = - _generateReportFromMessages(sourceChainSelector, messages); - - return Internal.ExecutionReport({ - proofs: singleChainReport.proofs, - proofFlagBits: singleChainReport.proofFlagBits, - messages: singleChainReport.messages, - offchainTokenData: singleChainReport.offchainTokenData - }); - } - function _generateReportFromMessages( uint64 sourceChainSelector, - Internal.EVM2EVMMessage[] memory messages + Internal.Any2EVMRampMessage[] memory messages ) internal pure returns (Internal.ExecutionReportSingleChain memory) { bytes[][] memory offchainTokenData = new bytes[][](messages.length); @@ -392,14 +373,14 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba function _generateBatchReportFromMessages( uint64 sourceChainSelector, - Internal.EVM2EVMMessage[] memory messages + Internal.Any2EVMRampMessage[] memory messages ) internal pure returns (Internal.ExecutionReportSingleChain[] memory) { Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](1); reports[0] = _generateReportFromMessages(sourceChainSelector, messages); return reports; } - function _getGasLimitsFromMessages(Internal.EVM2EVMMessage[] memory messages) + function _getGasLimitsFromMessages(Internal.Any2EVMRampMessage[] memory messages) internal pure returns (uint256[] memory) @@ -431,7 +412,6 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba assertEq(config1.isEnabled, config2.isEnabled); assertEq(config1.minSeqNr, config2.minSeqNr); assertEq(config1.onRamp, config2.onRamp); - assertEq(config1.metadataHash, config2.metadataHash); } function _getDefaultSourceTokenData(Client.EVMTokenAmount[] memory srcTokenAmounts) diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go index f5a77a4070..b2fcdc4670 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go @@ -69,16 +69,15 @@ type EVM2EVMMultiOffRampMerkleRoot struct { } type EVM2EVMMultiOffRampSourceChainConfig struct { - IsEnabled bool - MinSeqNr uint64 - OnRamp common.Address - MetadataHash [32]byte + IsEnabled bool + MinSeqNr uint64 + OnRamp []byte } type EVM2EVMMultiOffRampSourceChainConfigArgs struct { SourceChainSelector uint64 IsEnabled bool - OnRamp common.Address + OnRamp []byte } type EVM2EVMMultiOffRampStaticConfig struct { @@ -93,25 +92,19 @@ type EVM2EVMMultiOffRampUnblessedRoot struct { MerkleRoot [32]byte } -type InternalEVM2EVMMessage struct { - SourceChainSelector uint64 - Sender common.Address - Receiver common.Address - SequenceNumber uint64 - GasLimit *big.Int - Strict bool - Nonce uint64 - FeeToken common.Address - FeeTokenAmount *big.Int - Data []byte - TokenAmounts []ClientEVMTokenAmount - SourceTokenData [][]byte - MessageId [32]byte +type InternalAny2EVMRampMessage struct { + Header InternalRampMessageHeader + Sender []byte + Data []byte + Receiver common.Address + GasLimit *big.Int + TokenAmounts []ClientEVMTokenAmount + SourceTokenData [][]byte } type InternalExecutionReportSingleChain struct { SourceChainSelector uint64 - Messages []InternalEVM2EVMMessage + Messages []InternalAny2EVMRampMessage OffchainTokenData [][][]byte Proofs [][32]byte ProofFlagBits *big.Int @@ -127,6 +120,14 @@ type InternalPriceUpdates struct { GasPriceUpdates []InternalGasPriceUpdate } +type InternalRampMessageHeader struct { + MessageId [32]byte + SourceChainSelector uint64 + DestChainSelector uint64 + SequenceNumber uint64 + Nonce uint64 +} + type InternalTokenPriceUpdate struct { SourceToken common.Address UsdPerToken *big.Int @@ -155,8 +156,8 @@ type MultiOCR3BaseOCRConfigArgs struct { } var EVM2EVMMultiOffRampMetaData = &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\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"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\":\"error\",\"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\":\"structEVM2EVMMultiOffRamp.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\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"InvalidMessageId\",\"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\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"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\":\"error\",\"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\":[{\"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\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\"}],\"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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"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\":\"structEVM2EVMMultiOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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: "0x6101206040523480156200001257600080fd5b506040516200641738038062006417833981016040819052620000359162000631565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001ee565b5050466080525060208201516001600160a01b03161580620000ec575060408201516001600160a01b0316155b8062000103575060608201516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b81516001600160401b0390811660a052602080840180516001600160a01b0390811660c05260408087018051831660e0526060808901805185166101005283518a519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e68162000299565b5050620007b8565b336001600160a01b03821603620002485760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b815181101562000505576000828281518110620002bd57620002bd620007a2565b60200260200101519050600081600001519050806001600160401b0316600003620002fb5760405163c656089560e01b815260040160405180910390fd5b60408201516001600160a01b031662000327576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526007602052604090208054690100000000000000000090046001600160a01b03166200041957620003938284604001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36200050960201b60201c565b60018201556040838101518254610100600160481b03196001600160a01b0390921669010000000000000000000291909116610100600160e81b031990911617610100178255516001600160401b03831681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a162000465565b60408301518154690100000000000000000090046001600160a01b03908116911614620004655760405163c39a620560e01b81526001600160401b038316600482015260240162000083565b6020830151815490151560ff199091161781556040516001600160401b038316907fb8f0c74385134334c728fcac437ec6c6397c9f2c1440532b0c44175a090b140190620004ee908490815460ff811615158252600881901c6001600160401b0316602083015260481c6001600160a01b03166040820152600190910154606082015260800190565b60405180910390a25050508060010190506200029c565b5050565b60a0805160408051602081018590526001600160401b0380881692820192909252911660608201526001600160a01b0384166080820152600091016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200059e576200059e62000563565b60405290565b604051606081016001600160401b03811182821017156200059e576200059e62000563565b604051601f8201601f191681016001600160401b0381118282101715620005f457620005f462000563565b604052919050565b80516001600160401b03811681146200061457600080fd5b919050565b80516001600160a01b03811681146200061457600080fd5b60008082840360a08112156200064657600080fd5b60808112156200065557600080fd5b506200066062000579565b6200066b84620005fc565b815260206200067c81860162000619565b818301526040620006906040870162000619565b60408401526060620006a56060880162000619565b606085015260808701519395506001600160401b0380851115620006c857600080fd5b848801945088601f860112620006dd57600080fd5b845181811115620006f257620006f262000563565b62000702858260051b01620005c9565b8181528581019250606090910286018501908a8211156200072257600080fd5b958501955b81871015620007915783878c031215620007415760008081fd5b6200074b620005a4565b6200075688620005fc565b81528688015180151581146200076c5760008081fd5b818801526200077d88870162000619565b818701528352958301959185019162000727565b809750505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161010051615bf0620008276000396000818161023e0152612b1d01526000818161020f0152612ed60152600081816101e001528181611557015261160e0152600081816101b00152612df8015260008181611baa0152611bf60152615bf06000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063d2a15d351161008c578063f52121a511610066578063f52121a514610662578063f716f99f14610675578063ff888fb11461068857600080fd5b8063d2a15d3514610556578063e9d68a8e14610569578063f2fde38b1461064f57600080fd5b80638e7da1af116100bd5780638e7da1af146104de578063c673e584146104f1578063ccd37ba31461051157600080fd5b806385572ffb146104b55780638da5cb5b146104c357600080fd5b8063403b2d631161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba5097146104ad57600080fd5b8063403b2d6314610352578063542625af1461036557600080fd5b80632d04ab76116101605780632d04ab761461030e578063311cd513146103235780633f4b04aa1461033657600080fd5b806306285c691461017c578063181f5a77146102c5575b600080fd5b61026e60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102bc9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103016040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b6040516102bc9190613f13565b61032161031c366004613fbe565b6106ab565b005b610321610331366004614071565b610a71565b600a5460405167ffffffffffffffff90911681526020016102bc565b6103216103603660046141fb565b610ada565b610321610373366004614816565b610c97565b61038b610386366004614941565b610e3c565b6040516102bc919061499e565b6104446040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526004546001600160a01b03808216835263ffffffff74010000000000000000000000000000000000000000830481166020850152600160c01b8304811694840194909452600160e01b90910490921660608201526005548216608082015260065490911660a082015290565b6040516102bc9190600060c0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401528060a08501511660a08401525092915050565b610321610e92565b6103216101773660046149ac565b6000546040516001600160a01b0390911681526020016102bc565b6103216104ec3660046149e7565b610f50565b6105046104ff366004614acf565b610f64565b6040516102bc9190614b2f565b61054861051f366004614ba4565b67ffffffffffffffff919091166000908152600960209081526040808320938352929052205490565b6040519081526020016102bc565b610321610564366004614bce565b6110c2565b610607610577366004614c43565b6040805160808101825260008082526020820181905291810182905260608101919091525067ffffffffffffffff9081166000908152600760209081526040918290208251608081018452815460ff81161515825261010081049095169281019290925269010000000000000000009093046001600160a01b031691810191909152600190910154606082015290565b6040516102bc919081511515815260208083015167ffffffffffffffff16908201526040808301516001600160a01b0316908201526060918201519181019190915260800190565b61032161065d366004614c5e565b61117c565b610321610670366004614c7b565b61118d565b610321610683366004614d47565b6114bf565b61069b610696366004614e92565b611501565b60405190151581526020016102bc565b60006106b98789018961501b565b805151519091501515806106d257508051602001515115155b156107d257600a5460208a01359067ffffffffffffffff8083169116101561079157600a805467ffffffffffffffff191667ffffffffffffffff831617905560065482516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691633937306f9161075a9160040161524d565b600060405180830381600087803b15801561077457600080fd5b505af1158015610788573d6000803e3d6000fd5b505050506107d0565b8160200151516000036107d0576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b8160200151518110156109ba576000826020015182815181106107fa576107fa615186565b60200260200101519050600081600001519050610816816115c2565b6000610821826116c4565b602084015151815491925067ffffffffffffffff90811661010090920416141580610863575060208084015190810151905167ffffffffffffffff9182169116115b156108ac57825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526108a3929190600401615260565b60405180910390fd5b6040830151806108e8576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff1660009081526009602090815260408083208484529091529020541561095b5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016108a3565b602080850151015161096e9060016152ab565b825468ffffffffffffffff00191661010067ffffffffffffffff9283160217909255925116600090815260096020908152604080832094835293905291909120429055506001016107d5565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d816040516109ea91906152d3565b60405180910390a1610a6660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611724915050565b505050505050505050565b610ab1610a8082840184615370565b6040805160008082526020820190925290610aab565b6060815260200190600190039081610a965790505b50611a9b565b604080516000808252602082019092529050610ad4600185858585866000611724565b50505050565b610ae2611b4b565b60a08101516001600160a01b03161580610b04575080516001600160a01b0316155b15610b3b576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a177401000000000000000000000000000000000000000063ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff19908116928e1692909217905560a0808e01805160068054909416908f161790925586519a8b5297518716988a0198909852925185169388019390935251909216958501959095525185169383019390935251909216908201527f0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c9060c00160405180910390a150565b610c9f611ba7565b815181518114610cdb576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610e2c576000848281518110610cfa57610cfa615186565b60200260200101519050600081602001515190506000858481518110610d2257610d22615186565b6020026020010151905080518214610d66576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610e1d576000828281518110610d8557610d85615186565b6020026020010151905080600014158015610dc0575084602001518281518110610db157610db1615186565b60200260200101516080015181105b15610e145784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064016108a3565b50600101610d69565b50505050806001019050610cde565b50610e378383611a9b565b505050565b6000610e4a600160046153a5565b6002610e576080856153ce565b67ffffffffffffffff16610e6b91906153f5565b610e758585611c28565b901c166003811115610e8957610e89614974565b90505b92915050565b6001546001600160a01b03163314610eec5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108a3565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f58611b4b565b610f6181611c6f565b50565b610fa76040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561105057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611032575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156110b257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611094575b5050505050815250509050919050565b6110ca611b4b565b60005b81811015610e375760008383838181106110e9576110e9615186565b9050604002018036038101906110ff919061540c565b905061110e8160200151611501565b61117357805167ffffffffffffffff1660009081526009602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016110cd565b611184611b4b565b610f6181611f30565b3330146111c6576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281611203565b60408051808201909152600080825260208201528152602001906001900390816111dc5790505b50610140840151519091501561126457611261836101400151846020015160405160200161124091906001600160a01b0391909116815260200190565b60408051601f19818403018152918152860151865161016088015187611fe6565b90505b60006112708483612093565b6005549091506001600160a01b0316801561135d576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a1906112ca9085906004016154f3565b600060405180830381600087803b1580156112e457600080fd5b505af19250505080156112f5575060015b61135d573d808015611323576040519150601f19603f3d011682016040523d82523d6000602084013e611328565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016108a39190613f13565b6101208501515115801561137357506080850151155b8061138a575060408501516001600160a01b03163b155b806113ca575060408501516113c8906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000612136565b155b156113d6575050505050565b60048054608087015160408089015190517f3cf9798300000000000000000000000000000000000000000000000000000000815260009485946001600160a01b031693633cf9798393611431938a9361138893929101615506565b6000604051808303816000875af1158015611450573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114789190810190615587565b5091509150816114b657806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016108a39190613f13565b50505050505050565b6114c7611b4b565b60005b81518110156114fd576114f58282815181106114e8576114e8615186565b6020026020010151612152565b6001016114ca565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa15801561159e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8c91906155e1565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561165d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168191906155e1565b15610f61576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108a3565b67ffffffffffffffff81166000908152600760205260408120805460ff16610e8c576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108a3565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117838760a46155fe565b90508260600151156117cb57845161179c9060206153f5565b86516117a99060206153f5565b6117b49060a06155fe565b6117be91906155fe565b6117c890826155fe565b90505b36811461180d576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016108a3565b50815181146118555781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016108a3565b61185d611ba7565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156118ab576118ab614974565b60028111156118bc576118bc614974565b90525090506002816020015160028111156118d9576118d9614974565b14801561192d5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061191557611915615186565b6000918252602090912001546001600160a01b031633145b611963576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611a4557602082015161197e906001615611565b60ff168551146119ba576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146119f5576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611a0792919061562a565b604051908190038120611a1e918b9060200161563a565b604051602081830303815290604052805190602001209050611a438a8288888861245d565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611ad5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611b4457611b3c858281518110611b0a57611b0a615186565b602002602001015184611b3657858381518110611b2957611b29615186565b6020026020010151612674565b83612674565b600101611aec565b5050505050565b6000546001600160a01b03163314611ba55760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108a3565b565b467f000000000000000000000000000000000000000000000000000000000000000014611ba5576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016108a3565b67ffffffffffffffff8216600090815260086020526040812081611c4d60808561564e565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b60005b81518110156114fd576000828281518110611c8f57611c8f615186565b602002602001015190506000816000015190508067ffffffffffffffff16600003611ce6576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516001600160a01b0316611d2a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526007602052604090208054690100000000000000000090046001600160a01b0316611e2c57611d8e8284604001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3612df2565b6001820155604083810151825468ffffffffffffffff00196001600160a01b03909216690100000000000000000002919091167fffffff00000000000000000000000000000000000000000000000000000000ff909116176101001782555167ffffffffffffffff831681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611e90565b60408301518154690100000000000000000090046001600160a01b03908116911614611e90576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016108a3565b6020830151815490151560ff1990911617815560405167ffffffffffffffff8316907fb8f0c74385134334c728fcac437ec6c6397c9f2c1440532b0c44175a090b140190611f1a908490815460ff811615158252600881901c67ffffffffffffffff16602083015260481c6001600160a01b03166040820152600190910154606082015260800190565b60405180910390a2505050806001019050611c72565b336001600160a01b03821603611f885760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108a3565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8560005b87518110156120885761206388828151811061200857612008615186565b60200260200101516020015188888888868151811061202957612029615186565b60200260200101518060200190518101906120449190615675565b88878151811061205657612056615186565b6020026020010151612e75565b82828151811061207557612075615186565b6020908102919091010152600101611fea565b509695505050505050565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff168152602001846020015160405160200161210b91906001600160a01b0391909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b6000612141836131ee565b8015610e895750610e89838361323a565b806040015160ff1660000361217d576000604051631b3fab5160e11b81526004016108a3919061572a565b60208082015160ff808216600090815260029093526040832060018101549293909283921690036121ce576060840151600182018054911515620100000262ff000019909216919091179055612223565b6060840151600182015460ff6201000090910416151590151514612223576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016108a3565b60a08401518051601f60ff82161115612252576001604051631b3fab5160e11b81526004016108a3919061572a565b6122b885856003018054806020026020016040519081016040528092919081815260200182805480156122ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612290575b50505050506132dc565b8560600151156123ca5761232685856002018054806020026020016040519081016040528092919081815260200182805480156122ae576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122905750505050506132dc565b608086015180516123409060028701906020840190613e21565b50805160018501805461ff00191661010060ff841690810291909117909155601f1015612383576002604051631b3fab5160e11b81526004016108a3919061572a565b6040880151612393906003615744565b60ff168160ff16116123bb576003604051631b3fab5160e11b81526004016108a3919061572a565b6123c787836001613345565b50505b6123d685836002613345565b81516123eb9060038601906020850190613e21565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793612444938a939260028b01929190615760565b60405180910390a1612455856134c5565b505050505050565b612465613e8f565b835160005b8181101561266a57600060018886846020811061248957612489615186565b61249691901a601b615611565b8985815181106124a8576124a8615186565b60200260200101518986815181106124c2576124c2615186565b602002602001015160405160008152602001604052604051612500949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612522573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561258357612583614974565b600281111561259457612594614974565b90525090506001816020015160028111156125b1576125b1614974565b146125e8576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f81106125ff576125ff615186565b60200201511561263b576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061265657612656615186565b91151560209092020152505060010161246a565b5050505050505050565b815161267f816115c2565b600061268a826116c4565b60208501515190915060008190036126cd576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461270b576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff811115612726576127266140c5565b60405190808252806020026020018201604052801561274f578160200160208202803683370190505b50905060005b828110156128145760008760200151828151811061277557612775615186565b6020026020010151905061278d8186600101546134e1565b83838151811061279f5761279f615186565b6020026020010181815250508061018001518383815181106127c3576127c3615186565b60200260200101511461280b578061018001516040517f345039be0000000000000000000000000000000000000000000000000000000081526004016108a391815260200190565b50600101612755565b50600061282b858389606001518a6080015161363d565b905080600003612873576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016108a3565b8551151560005b84811015610a665760008960200151828151811061289a5761289a615186565b6020026020010151905060006128b4898360600151610e3c565b905060028160038111156128ca576128ca614974565b036129205760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612dea565b600081600381111561293457612934614974565b14806129515750600381600381111561294f5761294f614974565b145b6129a15760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016108a3565b8315612a825760045460009074010000000000000000000000000000000000000000900463ffffffff166129d587426153a5565b11905080806129f5575060038260038111156129f3576129f3614974565b145b612a37576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526024016108a3565b8a8481518110612a4957612a49615186565b6020026020010151600014612a7c578a8481518110612a6a57612a6a615186565b60200260200101518360800181815250505b50612ae7565b6000816003811115612a9657612a96614974565b14612ae75760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016108a3565b60008260c0015167ffffffffffffffff16118015612b1657506000816003811115612b1457612b14614974565b145b15612bef577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8a8460c001518560200151604051602001612b7491906001600160a01b0391909116815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612ba1939291906157e6565b6020604051808303816000875af1158015612bc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be491906155e1565b612bef575050612dea565b60008b604001518481518110612c0757612c07615186565b6020026020010151905080518361014001515114612c6b5760608301516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808d16600483015290911660248201526044016108a3565b612c7b8a84606001516001613693565b600080612c88858461373b565b91509150612c9b8c866060015184613693565b868015612cb957506003826003811115612cb757612cb7614974565b145b8015612cd757506000846003811115612cd457612cd4614974565b14155b15612d1757846101800151816040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526004016108a3929190615813565b6003826003811115612d2b57612d2b614974565b14158015612d4b57506002826003811115612d4857612d48614974565b14155b15612d8b5760608501516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526108a3918e91859060040161582c565b846101800151856060015167ffffffffffffffff168d67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051612ddc929190615852565b60405180910390a450505050505b60010161287a565b600081847f000000000000000000000000000000000000000000000000000000000000000085604051602001612e55949392919093845267ffffffffffffffff9283166020850152911660408301526001600160a01b0316606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b60408051808201909152600080825260208201526000612e988460200151613986565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f419190615872565b90506001600160a01b0381161580612f895750612f876001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000612136565b155b15612fcb576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016108a3565b600080613096633907753760e01b6040518061010001604052808d81526020018b67ffffffffffffffff1681526020018c6001600160a01b031681526020018e8152602001876001600160a01b031681526020018a6000015181526020018a60400151815260200189815250604051602401613047919061588f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600454859063ffffffff600160e01b9091041661138860846139c8565b5091509150816130bb578060405163e1cd550960e01b81526004016108a39190613f13565b80516020146131035780516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016108a3565b6000818060200190518101906131199190615966565b604080516001600160a01b038d16602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb0000000000000000000000000000000000000000000000000000000017905260045491925061319c918790600160c01b900463ffffffff1661138860846139c8565b509093509150826131c2578160405163e1cd550960e01b81526004016108a39190613f13565b604080518082019091526001600160a01b03909516855260208501525091925050509695505050505050565b600061321a827f01ffc9a70000000000000000000000000000000000000000000000000000000061323a565b8015610e8c5750613233826001600160e01b031961323a565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132c5575060208210155b80156132d15750600081115b979650505050505050565b60005b8151811015610e375760ff83166000908152600360205260408120835190919084908490811061331157613311615186565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016132df565b60005b82518160ff161015610ad4576000838260ff168151811061336b5761336b615186565b602002602001015190506000600281111561338857613388614974565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156133c7576133c7614974565b146133e8576004604051631b3fab5160e11b81526004016108a3919061572a565b6001600160a01b038116613428576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561344e5761344e614974565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156134ab576134ab614974565b021790555090505050806134be9061597f565b9050613348565b60ff8116610f6157600a805467ffffffffffffffff1916905550565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016135779897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016135b0919061599e565b604051602081830303815290604052805190602001208761016001516040516020016135dc9190615a53565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061364b858585613aee565b905061365681611501565b61366457600091505061368b565b67ffffffffffffffff86166000908152600960209081526040808320938352929052205490505b949350505050565b600060026136a26080856153ce565b67ffffffffffffffff166136b691906153f5565b905060006136c48585611c28565b9050816136d3600160046153a5565b901b1916818360038111156136ea576136ea614974565b67ffffffffffffffff871660009081526008602052604081209190921b9290921791829161371960808861564e565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a59061377f9087908790600401615a66565b600060405180830381600087803b15801561379957600080fd5b505af19250505080156137aa575060015b61396a573d8080156137d8576040519150601f19603f3d011682016040523d82523d6000602084013e6137dd565b606091505b5060006137e982615bab565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000006001600160e01b031982161480613833575063e1cd550960e01b6001600160e01b03198216145b8061384e575063046b337b60e51b6001600160e01b03198216145b8061388257507f78ef8024000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138b657507f0c3b563c000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138ea57507fae9b4ce9000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b8061391e57507f09c25325000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b1561392f575060039250905061397f565b856101800151826040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526004016108a3929190615813565b50506040805160208101909152600081526002905b9250929050565b600081516020146139ac578160405163046b337b60e51b81526004016108a39190613f13565b610e8c828060200190518101906139c39190615966565b613d8c565b6000606060008361ffff1667ffffffffffffffff8111156139eb576139eb6140c5565b6040519080825280601f01601f191660200182016040528015613a15576020820181803683370190505b509150863b613a48577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613a7b577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ab4577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613ad75750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b2f576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b4357506101018111155b613b60576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613b8a576040516309bde33960e01b815260040160405180910390fd5b80600003613bb75786600081518110613ba557613ba5615186565b60200260200101519350505050612e6e565b60008167ffffffffffffffff811115613bd257613bd26140c5565b604051908082528060200260200182016040528015613bfb578160200160208202803683370190505b50905060008080805b85811015613d255760006001821b8b811603613c5f5788851015613c48578c5160018601958e918110613c3957613c39615186565b60200260200101519050613c81565b8551600185019487918110613c3957613c39615186565b8b5160018401938d918110613c7657613c76615186565b602002602001015190505b600089861015613cb1578d5160018701968f918110613ca257613ca2615186565b60200260200101519050613cd3565b8651600186019588918110613cc857613cc8615186565b602002602001015190505b82851115613cf4576040516309bde33960e01b815260040160405180910390fd5b613cfe8282613de0565b878481518110613d1057613d10615186565b60209081029190910101525050600101613c04565b506001850382148015613d3757508683145b8015613d4257508581145b613d5f576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613d7457613d74615186565b60200260200101519750505050505050509392505050565b60006001600160a01b03821180613da4575061040082105b15613ddc5760408051602081018490520160408051601f198184030181529082905263046b337b60e51b82526108a391600401613f13565b5090565b6000818310613df857613df38284613dfe565b610e89565b610e8983835b60408051600160208201529081018390526060810182905260009060800161361f565b828054828255906000526020600020908101928215613e83579160200282015b82811115613e83578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e41565b50613ddc929150613eae565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613ddc5760008155600101613eaf565b60005b83811015613ede578181015183820152602001613ec6565b50506000910152565b60008151808452613eff816020860160208601613ec3565b601f01601f19169290920160200192915050565b602081526000610e896020830184613ee7565b8060608101831015610e8c57600080fd5b60008083601f840112613f4957600080fd5b50813567ffffffffffffffff811115613f6157600080fd5b60208301915083602082850101111561397f57600080fd5b60008083601f840112613f8b57600080fd5b50813567ffffffffffffffff811115613fa357600080fd5b6020830191508360208260051b850101111561397f57600080fd5b60008060008060008060008060e0898b031215613fda57600080fd5b613fe48a8a613f26565b9750606089013567ffffffffffffffff8082111561400157600080fd5b61400d8c838d01613f37565b909950975060808b013591508082111561402657600080fd5b6140328c838d01613f79565b909750955060a08b013591508082111561404b57600080fd5b506140588b828c01613f79565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561408657600080fd5b6140908585613f26565b9250606084013567ffffffffffffffff8111156140ac57600080fd5b6140b886828701613f37565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156140fe576140fe6140c5565b60405290565b6040805190810167ffffffffffffffff811182821017156140fe576140fe6140c5565b6040516101a0810167ffffffffffffffff811182821017156140fe576140fe6140c5565b60405160a0810167ffffffffffffffff811182821017156140fe576140fe6140c5565b6040516060810167ffffffffffffffff811182821017156140fe576140fe6140c5565b604051601f8201601f1916810167ffffffffffffffff811182821017156141ba576141ba6140c5565b604052919050565b6001600160a01b0381168114610f6157600080fd5b80356141e2816141c2565b919050565b803563ffffffff811681146141e257600080fd5b600060c0828403121561420d57600080fd5b6142156140db565b8235614220816141c2565b815261422e602084016141e7565b602082015261423f604084016141e7565b6040820152614250606084016141e7565b60608201526080830135614263816141c2565b608082015260a0830135614276816141c2565b60a08201529392505050565b600067ffffffffffffffff82111561429c5761429c6140c5565b5060051b60200190565b803567ffffffffffffffff811681146141e257600080fd5b8015158114610f6157600080fd5b80356141e2816142be565b600067ffffffffffffffff8211156142f1576142f16140c5565b50601f01601f191660200190565b600082601f83011261431057600080fd5b813561432361431e826142d7565b614191565b81815284602083860101111561433857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261436657600080fd5b8135602061437661431e83614282565b82815260069290921b8401810191818101908684111561439557600080fd5b8286015b8481101561208857604081890312156143b25760008081fd5b6143ba614104565b81356143c5816141c2565b81528185013585820152835291830191604001614399565b600082601f8301126143ee57600080fd5b813560206143fe61431e83614282565b82815260059290921b8401810191818101908684111561441d57600080fd5b8286015b8481101561208857803567ffffffffffffffff8111156144415760008081fd5b61444f8986838b01016142ff565b845250918301918301614421565b60006101a0828403121561447057600080fd5b614478614127565b9050614483826142a6565b8152614491602083016141d7565b60208201526144a2604083016141d7565b60408201526144b3606083016142a6565b6060820152608082013560808201526144ce60a083016142cc565b60a08201526144df60c083016142a6565b60c08201526144f060e083016141d7565b60e082015261010082810135908201526101208083013567ffffffffffffffff8082111561451d57600080fd5b614529868387016142ff565b8385015261014092508285013591508082111561454557600080fd5b61455186838701614355565b8385015261016092508285013591508082111561456d57600080fd5b5061457a858286016143dd565b82840152505061018080830135818301525092915050565b600082601f8301126145a357600080fd5b813560206145b361431e83614282565b82815260059290921b840181019181810190868411156145d257600080fd5b8286015b8481101561208857803567ffffffffffffffff8111156145f65760008081fd5b6146048986838b010161445d565b8452509183019183016145d6565b600082601f83011261462357600080fd5b8135602061463361431e83614282565b82815260059290921b8401810191818101908684111561465257600080fd5b8286015b8481101561208857803567ffffffffffffffff8111156146765760008081fd5b6146848986838b01016143dd565b845250918301918301614656565b600082601f8301126146a357600080fd5b813560206146b361431e83614282565b8083825260208201915060208460051b8701019350868411156146d557600080fd5b602086015b8481101561208857803583529183019183016146da565b600082601f83011261470257600080fd5b8135602061471261431e83614282565b82815260059290921b8401810191818101908684111561473157600080fd5b8286015b8481101561208857803567ffffffffffffffff808211156147565760008081fd5b9088019060a0828b03601f19018113156147705760008081fd5b61477861414b565b6147838885016142a6565b8152604080850135848111156147995760008081fd5b6147a78e8b83890101614592565b8a84015250606080860135858111156147c05760008081fd5b6147ce8f8c838a0101614612565b83850152506080915081860135858111156147e95760008081fd5b6147f78f8c838a0101614692565b9184019190915250919093013590830152508352918301918301614735565b600080604080848603121561482a57600080fd5b833567ffffffffffffffff8082111561484257600080fd5b61484e878388016146f1565b945060209150818601358181111561486557600080fd5b8601601f8101881361487657600080fd5b803561488461431e82614282565b81815260059190911b8201840190848101908a8311156148a357600080fd5b8584015b8381101561492f578035868111156148bf5760008081fd5b8501603f81018d136148d15760008081fd5b878101356148e161431e82614282565b81815260059190911b82018a0190898101908f8311156149015760008081fd5b928b01925b8284101561491f5783358252928a0192908a0190614906565b86525050509186019186016148a7565b50809750505050505050509250929050565b6000806040838503121561495457600080fd5b61495d836142a6565b915061496b602084016142a6565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b6004811061499a5761499a614974565b9052565b60208101610e8c828461498a565b6000602082840312156149be57600080fd5b813567ffffffffffffffff8111156149d557600080fd5b820160a08185031215612e6e57600080fd5b600060208083850312156149fa57600080fd5b823567ffffffffffffffff811115614a1157600080fd5b8301601f81018513614a2257600080fd5b8035614a3061431e82614282565b81815260609182028301840191848201919088841115614a4f57600080fd5b938501935b83851015614ab25780858a031215614a6c5760008081fd5b614a7461416e565b614a7d866142a6565b815286860135614a8c816142be565b81880152604086810135614a9f816141c2565b9082015283529384019391850191614a54565b50979650505050505050565b803560ff811681146141e257600080fd5b600060208284031215614ae157600080fd5b610e8982614abe565b60008151808452602080850194506020840160005b83811015614b245781516001600160a01b031687529582019590820190600101614aff565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614b7e60e0840182614aea565b90506040840151601f198483030160c0850152614b9b8282614aea565b95945050505050565b60008060408385031215614bb757600080fd5b614bc0836142a6565b946020939093013593505050565b60008060208385031215614be157600080fd5b823567ffffffffffffffff80821115614bf957600080fd5b818501915085601f830112614c0d57600080fd5b813581811115614c1c57600080fd5b8660208260061b8501011115614c3157600080fd5b60209290920196919550909350505050565b600060208284031215614c5557600080fd5b610e89826142a6565b600060208284031215614c7057600080fd5b8135612e6e816141c2565b60008060408385031215614c8e57600080fd5b823567ffffffffffffffff80821115614ca657600080fd5b614cb28683870161445d565b93506020850135915080821115614cc857600080fd5b50614cd5858286016143dd565b9150509250929050565b600082601f830112614cf057600080fd5b81356020614d0061431e83614282565b8083825260208201915060208460051b870101935086841115614d2257600080fd5b602086015b84811015612088578035614d3a816141c2565b8352918301918301614d27565b60006020808385031215614d5a57600080fd5b823567ffffffffffffffff80821115614d7257600080fd5b818501915085601f830112614d8657600080fd5b8135614d9461431e82614282565b81815260059190911b83018401908481019088831115614db357600080fd5b8585015b83811015614e8557803585811115614dce57600080fd5b860160c0818c03601f19011215614de55760008081fd5b614ded6140db565b8882013581526040614e00818401614abe565b8a8301526060614e11818501614abe565b8284015260809150614e248285016142cc565b9083015260a08381013589811115614e3c5760008081fd5b614e4a8f8d83880101614cdf565b838501525060c0840135915088821115614e645760008081fd5b614e728e8c84870101614cdf565b9083015250845250918601918601614db7565b5098975050505050505050565b600060208284031215614ea457600080fd5b5035919050565b80356001600160e01b03811681146141e257600080fd5b600082601f830112614ed357600080fd5b81356020614ee361431e83614282565b82815260069290921b84018101918181019086841115614f0257600080fd5b8286015b848110156120885760408189031215614f1f5760008081fd5b614f27614104565b614f30826142a6565b8152614f3d858301614eab565b81860152835291830191604001614f06565b600082601f830112614f6057600080fd5b81356020614f7061431e83614282565b82815260079290921b84018101918181019086841115614f8f57600080fd5b8286015b84811015612088578088036080811215614fad5760008081fd5b614fb561416e565b614fbe836142a6565b8152604080601f1984011215614fd45760008081fd5b614fdc614104565b9250614fe98785016142a6565b8352614ff68185016142a6565b8388015281870192909252606083013591810191909152835291830191608001614f93565b6000602080838503121561502e57600080fd5b823567ffffffffffffffff8082111561504657600080fd5b8185019150604080838803121561505c57600080fd5b615064614104565b83358381111561507357600080fd5b84016040818a03121561508557600080fd5b61508d614104565b81358581111561509c57600080fd5b8201601f81018b136150ad57600080fd5b80356150bb61431e82614282565b81815260069190911b8201890190898101908d8311156150da57600080fd5b928a01925b8284101561512a5787848f0312156150f75760008081fd5b6150ff614104565b843561510a816141c2565b8152615117858d01614eab565b818d0152825292870192908a01906150df565b84525050508187013593508484111561514257600080fd5b61514e8a858401614ec2565b818801528252508385013591508282111561516857600080fd5b61517488838601614f4f565b85820152809550505050505092915050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b818110156151f357835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016151bc565b50508583015187820388850152805180835290840192506000918401905b80831015614ab2578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615211565b602081526000610e89602083018461519c565b67ffffffffffffffff8316815260608101612e6e6020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156152cc576152cc615295565b5092915050565b6000602080835260608451604080848701526152f2606087018361519c565b87850151878203601f19016040890152805180835290860193506000918601905b80831015614e8557845167ffffffffffffffff81511683528781015161535289850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615313565b60006020828403121561538257600080fd5b813567ffffffffffffffff81111561539957600080fd5b61368b848285016146f1565b81810381811115610e8c57610e8c615295565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806153e9576153e96153b8565b92169190910692915050565b8082028115828204841417610e8c57610e8c615295565b60006040828403121561541e57600080fd5b615426614104565b61542f836142a6565b8152602083013560208201528091505092915050565b60008151808452602080850194506020840160005b83811015614b2457815180516001600160a01b03168852602090810151908801526040870196509082019060010161545a565b8051825267ffffffffffffffff60208201511660208301526000604082015160a060408501526154c060a0850182613ee7565b9050606083015184820360608601526154d98282613ee7565b91505060808301518482036080860152614b9b8282615445565b602081526000610e89602083018461548d565b608081526000615519608083018761548d565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b600082601f83011261555357600080fd5b815161556161431e826142d7565b81815284602083860101111561557657600080fd5b61368b826020830160208701613ec3565b60008060006060848603121561559c57600080fd5b83516155a7816142be565b602085015190935067ffffffffffffffff8111156155c457600080fd5b6155d086828701615542565b925050604084015190509250925092565b6000602082840312156155f357600080fd5b8151612e6e816142be565b80820180821115610e8c57610e8c615295565b60ff8181168382160190811115610e8c57610e8c615295565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615669576156696153b8565b92169190910492915050565b60006020828403121561568757600080fd5b815167ffffffffffffffff8082111561569f57600080fd5b90830190606082860312156156b357600080fd5b6156bb61416e565b8251828111156156ca57600080fd5b6156d687828601615542565b8252506020830151828111156156eb57600080fd5b6156f787828601615542565b60208301525060408301518281111561570f57600080fd5b61571b87828601615542565b60408301525095945050505050565b602081016005831061573e5761573e614974565b91905290565b60ff81811683821602908116908181146152cc576152cc615295565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b818110156157ba5784546001600160a01b031683526001948501949284019201615795565b505084810360608601526157ce8188614aea565b935050505060ff831660808301529695505050505050565b600067ffffffffffffffff808616835280851660208401525060606040830152614b9b6060830184613ee7565b82815260406020820152600061368b6040830184613ee7565b67ffffffffffffffff8481168252831660208201526060810161368b604083018461498a565b61585c818461498a565b60406020820152600061368b6040830184613ee7565b60006020828403121561588457600080fd5b8151612e6e816141c2565b60208152600082516101008060208501526158ae610120850183613ee7565b915060208501516158cb604086018267ffffffffffffffff169052565b5060408501516001600160a01b03811660608601525060608501516080850152608085015161590560a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159228483613ee7565b935060c08701519150808685030160e087015261593f8483613ee7565b935060e087015191508086850301838701525061595c8382613ee7565b9695505050505050565b60006020828403121561597857600080fd5b5051919050565b600060ff821660ff810361599557615995615295565b60010192915050565b6020808252825182820181905260009190848201906040850190845b818110156159ed57835180516001600160a01b0316845260209081015190840152604083019385019392506001016159ba565b50909695505050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015615a4657601f19868403018952615a34838351613ee7565b98840198925090830190600101615a18565b5090979650505050505050565b602081526000610e8960208301846159f9565b60408152615a8160408201845167ffffffffffffffff169052565b60006020840151615a9d60608401826001600160a01b03169052565b5060408401516001600160a01b038116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c0840151610100615afe8185018367ffffffffffffffff169052565b60e08601519150610120615b1c818601846001600160a01b03169052565b81870151925061014091508282860152808701519250506101a06101608181870152615b4c6101e0870185613ee7565b9350828801519250603f19610180818887030181890152615b6d8686615445565b9550828a01519450818887030184890152615b8886866159f9565b9550808a01516101c089015250505050508281036020840152614b9b81856159f9565b6000815160208301516001600160e01b031980821693506004831015615bdb5780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", + 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\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"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\":\"error\",\"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\":\"structEVM2EVMMultiOffRamp.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\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"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\":\"error\",\"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\":[{\"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\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\"}],\"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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"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\":\"structEVM2EVMMultiOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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: "0x6101206040523480156200001257600080fd5b506040516200694f3803806200694f8339810160408190526200003591620005bd565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001ee565b5050466080525060208201516001600160a01b03161580620000ec575060408201516001600160a01b0316155b8062000103575060608201516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b81516001600160401b0390811660a052602080840180516001600160a01b0390811660c05260408087018051831660e0526060808901805185166101005283518a519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e68162000299565b505062000a03565b336001600160a01b03821603620002485760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015620004eb576000828281518110620002bd57620002bd620007cc565b60200260200101519050600081600001519050806001600160401b0316600003620002fb5760405163c656089560e01b815260040160405180910390fd5b6001600160401b03811660009081526007602052604081206001810180549192916200032790620007e2565b80601f01602080910402602001604051908101604052809291908181526020018280546200035590620007e2565b8015620003a65780601f106200037a57610100808354040283529160200191620003a6565b820191906000526020600020905b8154815290600101906020018083116200038857829003601f168201915b50505050509050600084604001519050815160000362000449578051600003620003e3576040516342bcdf7f60e11b815260040160405180910390fd5b60018301620003f3828262000873565b508254610100600160481b0319166101001783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a162000484565b8080519060200120828051906020012014620004845760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b6020850151835460ff19169015151783556040516001600160401b038516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba90620004d29086906200093f565b60405180910390a250505050508060010190506200029c565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200052a576200052a620004ef565b60405290565b604051606081016001600160401b03811182821017156200052a576200052a620004ef565b604051601f8201601f191681016001600160401b0381118282101715620005805762000580620004ef565b604052919050565b80516001600160401b0381168114620005a057600080fd5b919050565b80516001600160a01b0381168114620005a057600080fd5b60008082840360a0811215620005d257600080fd5b6080811215620005e157600080fd5b50620005ec62000505565b620005f78462000588565b8152602062000608818601620005a5565b818301526200061a60408601620005a5565b60408301526200062d60608601620005a5565b606083015260808501519193506001600160401b03808311156200065057600080fd5b828601925086601f8401126200066557600080fd5b8251818111156200067a576200067a620004ef565b8060051b6200068b84820162000555565b918252848101840191848101908a841115620006a657600080fd5b85870192505b83831015620007bb57825185811115620006c557600080fd5b8701601f196060828e0382011215620006dd57600080fd5b620006e762000530565b620006f489840162000588565b8152604083015180151581146200070a57600080fd5b818a01526060830151888111156200072157600080fd5b8084019350508d603f8401126200073757600080fd5b88830151888111156200074e576200074e620004ef565b620007608a84601f8401160162000555565b92508083528e60408286010111156200077857600080fd5b60005b818110156200079957848101604001518482018c01528a016200077b565b5060009083018a015260408101919091528352509185019190850190620006ac565b809750505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620007f757607f821691505b6020821081036200081857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200086e576000816000526020600020601f850160051c81016020861015620008495750805b601f850160051c820191505b818110156200086a5782815560010162000855565b5050505b505050565b81516001600160401b038111156200088f576200088f620004ef565b620008a781620008a08454620007e2565b846200081e565b602080601f831160018114620008df5760008415620008c65750858301515b600019600386901b1c1916600185901b1785556200086a565b600085815260208120601f198616915b828110156200091057888601518255948401946001909101908401620008ef565b50858210156200092f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020808252825460ff811615158383015260081c6001600160401b031660408301526060808301526001808401805460009392919084906200098181620007e2565b80608089015260a06001831660008114620009a55760018114620009c257620009f4565b60ff19841660a08b015260a083151560051b8b01019450620009f4565b85600052602060002060005b84811015620009eb5781548c8201850152908801908901620009ce565b8b0160a0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615edd62000a726000396000818161023e0152612be101526000818161020f0152612ecb0152600081816101e0015281816115ca01526116810152600081816101b00152612755015260008181611fb901526120050152615edd6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b146105b1578063f716f99f146105c4578063ff888fb1146105d757600080fd5b8063ccd37ba314610539578063d2a15d351461057e578063e9d68a8e1461059157600080fd5b8063a12a9870116100bd578063a12a9870146104f3578063bec0b14314610506578063c673e5841461051957600080fd5b806385572ffb146104ca5780638da5cb5b146104d857600080fd5b8063403b2d631161012f5780635ffb5ced116101145780635ffb5ced146103855780637437ff9f1461039857806379ba5097146104c257600080fd5b8063403b2d63146103525780635e36480c1461036557600080fd5b80632d04ab76116101605780632d04ab761461030e578063311cd513146103235780633f4b04aa1461033657600080fd5b806306285c691461017c578063181f5a77146102c5575b600080fd5b61026e60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102bc9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103016040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b6040516102bc9190613f11565b61032161031c366004613fbc565b6105fa565b005b61032161033136600461406f565b6109c0565b600a5460405167ffffffffffffffff90911681526020016102bc565b6103216103603660046141f8565b610a29565b610378610373366004614297565b610bfb565b6040516102bc91906142f4565b610321610393366004614600565b610c51565b6104596040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526004546001600160a01b03808216835263ffffffff7401000000000000000000000000000000000000000083048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b90910490921660608201526005548216608082015260065490911660a082015290565b6040516102bc9190600060c0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401528060a08501511660a08401525092915050565b610321610fa9565b610321610177366004614664565b6000546040516001600160a01b0390911681526020016102bc565b6103216105013660046146b8565b611067565b610321610514366004614a46565b61107b565b61052c610527366004614b82565b611220565b6040516102bc9190614be2565b610570610547366004614c57565b67ffffffffffffffff919091166000908152600960209081526040808320938352929052205490565b6040519081526020016102bc565b61032161058c366004614c81565b61137e565b6105a461059f366004614cf6565b611438565b6040516102bc9190614d11565b6103216105bf366004614d4c565b611521565b6103216105d2366004614dd1565b611532565b6105ea6105e5366004614f0f565b611574565b60405190151581526020016102bc565b600061060887890189615098565b8051515190915015158061062157508051602001515115155b1561072157600a5460208a01359067ffffffffffffffff808316911610156106e057600a805467ffffffffffffffff191667ffffffffffffffff831617905560065482516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691633937306f916106a9916004016152d6565b600060405180830381600087803b1580156106c357600080fd5b505af11580156106d7573d6000803e3d6000fd5b5050505061071f565b81602001515160000361071f576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b8160200151518110156109095760008260200151828151811061074957610749615203565b6020026020010151905060008160000151905061076581611635565b600061077082611737565b602084015151815491925067ffffffffffffffff908116610100909204161415806107b2575060208084015190810151905167ffffffffffffffff9182169116115b156107fb57825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526107f29291906004016152e9565b60405180910390fd5b604083015180610837576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff166000908152600960209081526040808320848452909152902054156108aa5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016107f2565b60208085015101516108bd906001615334565b825468ffffffffffffffff00191661010067ffffffffffffffff928316021790925592511660009081526009602090815260408083209483529390529190912042905550600101610724565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610939919061535c565b60405180910390a16109b560008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611797915050565b505050505050505050565b610a006109cf828401846153f9565b60408051600080825260208201909252906109fa565b60608152602001906001900390816109e55790505b50611b0e565b604080516000808252602082019092529050610a23600185858585866000611797565b50505050565b610a31611bbe565b60a08101516001600160a01b03161580610a53575080516001600160a01b0316155b15610a8a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a177401000000000000000000000000000000000000000063ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff19908116928e1692909217905560a0808e01805160068054909416908f161790925586519a8b5297518716988a0198909852925185169388019390935251909216958501959095525185169383019390935251909216908201527f0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c9060c00160405180910390a150565b6000610c096001600461542e565b6002610c16608085615457565b67ffffffffffffffff16610c2a919061547e565b610c348585611c1a565b901c166003811115610c4857610c486142ca565b90505b92915050565b333014610c8a576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610cc7565b6040805180820190915260008082526020820152815260200190600190039081610ca05790505b5060a08401515190915015610cff57610cfc8360a00151846020015185606001518660000151602001518760c0015187611c61565b90505b6040805160a0810182528451518152845160209081015167ffffffffffffffff1681830152808601518351600094840192610d3b929101613f11565b60408051601f19818403018152918152908252868101516020830152018390526005549091506001600160a01b03168015610e48576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610db5908590600401615543565b600060405180830381600087803b158015610dcf57600080fd5b505af1925050508015610de0575060015b610e48573d808015610e0e576040519150601f19603f3d011682016040523d82523d6000602084013e610e13565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107f29190613f11565b604085015151158015610e5d57506080850151155b80610e74575060608501516001600160a01b03163b155b80610eb457506060850151610eb2906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611d0e565b155b15610ec0575050505050565b60048054608087015160608801516040517f3cf9798300000000000000000000000000000000000000000000000000000000815260009485946001600160a01b031693633cf9798393610f1b938a9361138893929101615556565b6000604051808303816000875af1158015610f3a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f6291908101906155d7565b509150915081610fa057806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107f29190613f11565b50505050505050565b6001546001600160a01b031633146110035760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016107f2565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61106f611bbe565b61107881611d2a565b50565b611083611fb6565b8151815181146110bf576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156112105760008482815181106110de576110de615203565b6020026020010151905060008160200151519050600085848151811061110657611106615203565b602002602001015190508051821461114a576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561120157600082828151811061116957611169615203565b60200260200101519050806000141580156111a457508460200151828151811061119557611195615203565b60200260200101516080015181105b156111f85784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064016107f2565b5060010161114d565b505050508060010190506110c2565b5061121b8383611b0e565b505050565b6112636040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561130c57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112ee575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561136e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611350575b5050505050815250509050919050565b611386611bbe565b60005b8181101561121b5760008383838181106113a5576113a5615203565b9050604002018036038101906113bb9190615631565b90506113ca8160200151611574565b61142f57805167ffffffffffffffff1660009081526009602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b50600101611389565b60408051606080820183526000808352602080840182905283850183905267ffffffffffffffff8681168352600782529185902085519384018652805460ff8116151585526101009004909216908301526001810180549394929391928401916114a19061566a565b80601f01602080910402602001604051908101604052809291908181526020018280546114cd9061566a565b801561136e5780601f106114ef5761010080835404028352916020019161136e565b820191906000526020600020905b8154815290600101906020018083116114fd57505050919092525091949350505050565b611529611bbe565b61107881612037565b61153a611bbe565b60005b81518110156115705761156882828151811061155b5761155b615203565b60200260200101516120ed565b60010161153d565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611611573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b91906156a4565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156116d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f491906156a4565b15611078576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016107f2565b67ffffffffffffffff81166000908152600760205260408120805460ff16610c4b576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016107f2565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117f68760a46156c1565b905082606001511561183e57845161180f90602061547e565b865161181c90602061547e565b6118279060a06156c1565b61183191906156c1565b61183b90826156c1565b90505b368114611880576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016107f2565b50815181146118c85781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107f2565b6118d0611fb6565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561191e5761191e6142ca565b600281111561192f5761192f6142ca565b905250905060028160200151600281111561194c5761194c6142ca565b1480156119a05750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061198857611988615203565b6000918252602090912001546001600160a01b031633145b6119d6576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611ab85760208201516119f19060016156d4565b60ff16855114611a2d576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611a68576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611a7a9291906156ed565b604051908190038120611a91918b906020016156fd565b604051602081830303815290604052805190602001209050611ab68a82888888612431565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611b48576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611bb757611baf858281518110611b7d57611b7d615203565b602002602001015184611ba957858381518110611b9c57611b9c615203565b6020026020010151612648565b83612648565b600101611b5f565b5050505050565b6000546001600160a01b03163314611c185760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107f2565b565b67ffffffffffffffff8216600090815260086020526040812081611c3f608085615711565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b8560005b8751811015611d0357611cde888281518110611c8357611c83615203565b602002602001015160200151888888888681518110611ca457611ca4615203565b6020026020010151806020019051810190611cbf9190615738565b888781518110611cd157611cd1615203565b6020026020010151612e6a565b828281518110611cf057611cf0615203565b6020908102919091010152600101611c65565b509695505050505050565b6000611d19836131f8565b8015610c485750610c488383613244565b60005b8151811015611570576000828281518110611d4a57611d4a615203565b602002602001015190506000816000015190508067ffffffffffffffff16600003611da1576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600760205260408120600181018054919291611dcc9061566a565b80601f0160208091040260200160405190810160405280929190818152602001828054611df89061566a565b8015611e455780601f10611e1a57610100808354040283529160200191611e45565b820191906000526020600020905b815481529060010190602001808311611e2857829003601f168201915b505050505090506000846040015190508151600003611efe578051600003611e99576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301611ea78282615835565b50825468ffffffffffffffff00191661010017835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611f51565b8080519060200120828051906020012014611f51576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016107f2565b6020850151835460ff191690151517835560405167ffffffffffffffff8516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba90611f9e9086906158f5565b60405180910390a25050505050806001019050611d2d565b467f000000000000000000000000000000000000000000000000000000000000000014611c18576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107f2565b336001600160a01b0382160361208f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107f2565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003612118576000604051631b3fab5160e11b81526004016107f291906159b1565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361218557606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff9092169190911790556121da565b6060840151600182015460ff62010000909104161515901515146121da576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016107f2565b60a08401518051601f60ff82161115612209576001604051631b3fab5160e11b81526004016107f291906159b1565b61226f858560030180548060200260200160405190810160405280929190818152602001828054801561226557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612247575b50505050506132e6565b85606001511561239e576122dd8585600201805480602002602001604051908101604052809291908181526020018280548015612265576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122475750505050506132e6565b608086015180516122f79060028701906020840190613e1f565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612357576002604051631b3fab5160e11b81526004016107f291906159b1565b60408801516123679060036159cb565b60ff168160ff161161238f576003604051631b3fab5160e11b81526004016107f291906159b1565b61239b8783600161334f565b50505b6123aa8583600261334f565b81516123bf9060038601906020850190613e1f565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793612418938a939260028b019291906159e7565b60405180910390a1612429856134cf565b505050505050565b612439613e8d565b835160005b8181101561263e57600060018886846020811061245d5761245d615203565b61246a91901a601b6156d4565b89858151811061247c5761247c615203565b602002602001015189868151811061249657612496615203565b6020026020010151604051600081526020016040526040516124d4949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156124f6573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612557576125576142ca565b6002811115612568576125686142ca565b9052509050600181602001516002811115612585576125856142ca565b146125bc576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f81106125d3576125d3615203565b60200201511561260f576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061262a5761262a615203565b91151560209092020152505060010161243e565b5050505050505050565b815161265381611635565b600061265e82611737565b60208501515190915060008190036126a1576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001515181146126df576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff8111156126fa576126fa6140c3565b604051908082528060200260200182016040528015612723578160200160208202803683370190505b50905060005b828110156128985760008760200151828151811061274957612749615203565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff16146127dc57805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f2565b612872818660010180546127ef9061566a565b80601f016020809104026020016040519081016040528092919081815260200182805461281b9061566a565b80156128685780601f1061283d57610100808354040283529160200191612868565b820191906000526020600020905b81548152906001019060200180831161284b57829003601f168201915b50505050506134eb565b83838151811061288457612884615203565b602090810291909101015250600101612729565b5060006128af858389606001518a6080015161363d565b9050806000036128f7576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016107f2565b8551151560005b848110156109b55760008960200151828151811061291e5761291e615203565b60200260200101519050600061293c89836000015160600151610bfb565b90506002816003811115612952576129526142ca565b036129a9578151606001516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612e62565b60008160038111156129bd576129bd6142ca565b14806129da575060038160038111156129d8576129d86142ca565b145b612a2b578151606001516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016107f2565b8315612b0c5760045460009074010000000000000000000000000000000000000000900463ffffffff16612a5f874261542e565b1190508080612a7f57506003826003811115612a7d57612a7d6142ca565b145b612ac1576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526024016107f2565b8a8481518110612ad357612ad3615203565b6020026020010151600014612b06578a8481518110612af457612af4615203565b60200260200101518360800181815250505b50612b72565b6000816003811115612b2057612b206142ca565b14612b72578151606001516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016107f2565b81516080015167ffffffffffffffff1615801590612ba157506000816003811115612b9f57612b9f6142ca565b145b15612c665781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c18928e929190600401615a6d565b6020604051808303816000875af1158015612c37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5b91906156a4565b612c66575050612e62565b60008b604001518481518110612c7e57612c7e615203565b6020026020010151905080518360a001515114612ce2578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808d16600483015290911660248201526044016107f2565b612cf68a8460000151606001516001613693565b600080612d03858461373b565b91509150612d1a8c86600001516060015184613693565b868015612d3857506003826003811115612d3657612d366142ca565b145b8015612d5657506000846003811115612d5357612d536142ca565b14155b15612d93578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526107f291908390600401615a9a565b6003826003811115612da757612da76142ca565b14158015612dc757506002826003811115612dc457612dc46142ca565b14155b15612e08578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526107f2918e918590600401615ab3565b8451805160609091015160405167ffffffffffffffff918216918f16907f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df290612e549087908790615ad9565b60405180910390a450505050505b6001016128fe565b60408051808201909152600080825260208201526000612e8d8460200151613983565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f369190615af9565b90506001600160a01b0381161580612f7e5750612f7c6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611d0e565b155b15612fc0576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016107f2565b60008061308b633907753760e01b6040518061010001604052808d81526020018b67ffffffffffffffff1681526020018c6001600160a01b031681526020018e8152602001876001600160a01b031681526020018a6000015181526020018a6040015181526020018981525060405160240161303c9190615b16565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600454859063ffffffff600160e01b9091041661138860846139c5565b5091509150816130b0578060405163e1cd550960e01b81526004016107f29190613f11565b80516020146130f85780516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016107f2565b60008180602001905181019061310e9190615bed565b604080516001600160a01b038d16602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526004549192506131a69187907801000000000000000000000000000000000000000000000000900463ffffffff1661138860846139c5565b509093509150826131cc578160405163e1cd550960e01b81526004016107f29190613f11565b604080518082019091526001600160a01b03909516855260208501525091925050509695505050505050565b6000613224827f01ffc9a700000000000000000000000000000000000000000000000000000000613244565b8015610c4b575061323d826001600160e01b0319613244565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132cf575060208210155b80156132db5750600081115b979650505050505050565b60005b815181101561121b5760ff83166000908152600360205260408120835190919084908490811061331b5761331b615203565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016132e9565b60005b82518160ff161015610a23576000838260ff168151811061337557613375615203565b6020026020010151905060006002811115613392576133926142ca565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156133d1576133d16142ca565b146133f2576004604051631b3fab5160e11b81526004016107f291906159b1565b6001600160a01b038116613432576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff168152602001846002811115613458576134586142ca565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156134b5576134b56142ca565b021790555090505050806134c890615c06565b9050613352565b60ff811661107857600a805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613531937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c25565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761357a9794969395929491939101615c58565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016135b19190615cab565b604051602081830303815290604052805190602001208760c001516040516020016135dc9190615d60565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061364b858585613aeb565b905061365681611574565b61366457600091505061368b565b67ffffffffffffffff86166000908152600960209081526040808320938352929052205490505b949350505050565b600060026136a2608085615457565b67ffffffffffffffff166136b6919061547e565b905060006136c48585611c1a565b9050816136d36001600461542e565b901b1916818360038111156136ea576136ea6142ca565b67ffffffffffffffff871660009081526008602052604081209190921b92909217918291613719608088615711565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517f5ffb5ced0000000000000000000000000000000000000000000000000000000081526000906060903090635ffb5ced9061377f9087908790600401615d73565b600060405180830381600087803b15801561379957600080fd5b505af19250505080156137aa575060015b613967573d8080156137d8576040519150601f19603f3d011682016040523d82523d6000602084013e6137dd565b606091505b5060006137e982615e98565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000006001600160e01b031982161480613833575063e1cd550960e01b6001600160e01b03198216145b8061384e575063046b337b60e51b6001600160e01b03198216145b8061388257507f78ef8024000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138b657507f0c3b563c000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138ea57507fae9b4ce9000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b8061391e57507f09c25325000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b1561392f575060039250905061397c565b8551516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526107f291908490600401615a9a565b50506040805160208101909152600081526002905b9250929050565b600081516020146139a9578160405163046b337b60e51b81526004016107f29190613f11565b610c4b828060200190518101906139c09190615bed565b613d8a565b6000606060008361ffff1667ffffffffffffffff8111156139e8576139e86140c3565b6040519080825280601f01601f191660200182016040528015613a12576020820181803683370190505b509150863b613a45577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613a78577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ab1577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613ad45750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b2c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b4057506101018111155b613b5d576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613b87576040516309bde33960e01b815260040160405180910390fd5b80600003613bb45786600081518110613ba257613ba2615203565b60200260200101519350505050613d83565b60008167ffffffffffffffff811115613bcf57613bcf6140c3565b604051908082528060200260200182016040528015613bf8578160200160208202803683370190505b50905060008080805b85811015613d225760006001821b8b811603613c5c5788851015613c45578c5160018601958e918110613c3657613c36615203565b60200260200101519050613c7e565b8551600185019487918110613c3657613c36615203565b8b5160018401938d918110613c7357613c73615203565b602002602001015190505b600089861015613cae578d5160018701968f918110613c9f57613c9f615203565b60200260200101519050613cd0565b8651600186019588918110613cc557613cc5615203565b602002602001015190505b82851115613cf1576040516309bde33960e01b815260040160405180910390fd5b613cfb8282613dde565b878481518110613d0d57613d0d615203565b60209081029190910101525050600101613c01565b506001850382148015613d3457508683145b8015613d3f57508581145b613d5c576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613d7157613d71615203565b60200260200101519750505050505050505b9392505050565b60006001600160a01b03821180613da2575061040082105b15613dda5760408051602081018490520160408051601f198184030181529082905263046b337b60e51b82526107f291600401613f11565b5090565b6000818310613df657613df18284613dfc565b610c48565b610c4883835b60408051600160208201529081018390526060810182905260009060800161361f565b828054828255906000526020600020908101928215613e81579160200282015b82811115613e81578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e3f565b50613dda929150613eac565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613dda5760008155600101613ead565b60005b83811015613edc578181015183820152602001613ec4565b50506000910152565b60008151808452613efd816020860160208601613ec1565b601f01601f19169290920160200192915050565b602081526000610c486020830184613ee5565b8060608101831015610c4b57600080fd5b60008083601f840112613f4757600080fd5b50813567ffffffffffffffff811115613f5f57600080fd5b60208301915083602082850101111561397c57600080fd5b60008083601f840112613f8957600080fd5b50813567ffffffffffffffff811115613fa157600080fd5b6020830191508360208260051b850101111561397c57600080fd5b60008060008060008060008060e0898b031215613fd857600080fd5b613fe28a8a613f24565b9750606089013567ffffffffffffffff80821115613fff57600080fd5b61400b8c838d01613f35565b909950975060808b013591508082111561402457600080fd5b6140308c838d01613f77565b909750955060a08b013591508082111561404957600080fd5b506140568b828c01613f77565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561408457600080fd5b61408e8585613f24565b9250606084013567ffffffffffffffff8111156140aa57600080fd5b6140b686828701613f35565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156140fc576140fc6140c3565b60405290565b60405160a0810167ffffffffffffffff811182821017156140fc576140fc6140c3565b6040805190810167ffffffffffffffff811182821017156140fc576140fc6140c3565b60405160e0810167ffffffffffffffff811182821017156140fc576140fc6140c3565b6040516060810167ffffffffffffffff811182821017156140fc576140fc6140c3565b604051601f8201601f1916810167ffffffffffffffff811182821017156141b7576141b76140c3565b604052919050565b6001600160a01b038116811461107857600080fd5b80356141df816141bf565b919050565b803563ffffffff811681146141df57600080fd5b600060c0828403121561420a57600080fd5b6142126140d9565b823561421d816141bf565b815261422b602084016141e4565b602082015261423c604084016141e4565b604082015261424d606084016141e4565b60608201526080830135614260816141bf565b608082015260a0830135614273816141bf565b60a08201529392505050565b803567ffffffffffffffff811681146141df57600080fd5b600080604083850312156142aa57600080fd5b6142b38361427f565b91506142c16020840161427f565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106142f0576142f06142ca565b9052565b60208101610c4b82846142e0565b600060a0828403121561431457600080fd5b61431c614102565b90508135815261432e6020830161427f565b602082015261433f6040830161427f565b60408201526143506060830161427f565b60608201526143616080830161427f565b608082015292915050565b600067ffffffffffffffff821115614386576143866140c3565b50601f01601f191660200190565b600082601f8301126143a557600080fd5b81356143b86143b38261436c565b61418e565b8181528460208386010111156143cd57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115614404576144046140c3565b5060051b60200190565b600082601f83011261441f57600080fd5b8135602061442f6143b3836143ea565b82815260069290921b8401810191818101908684111561444e57600080fd5b8286015b84811015611d03576040818903121561446b5760008081fd5b614473614125565b813561447e816141bf565b81528185013585820152835291830191604001614452565b600082601f8301126144a757600080fd5b813560206144b76143b3836143ea565b82815260059290921b840181019181810190868411156144d657600080fd5b8286015b84811015611d0357803567ffffffffffffffff8111156144fa5760008081fd5b6145088986838b0101614394565b8452509183019183016144da565b6000610160828403121561452957600080fd5b614531614148565b905061453d8383614302565b815260a082013567ffffffffffffffff8082111561455a57600080fd5b61456685838601614394565b602084015260c084013591508082111561457f57600080fd5b61458b85838601614394565b604084015261459c60e085016141d4565b606084015261010084013560808401526101208401359150808211156145c157600080fd5b6145cd8583860161440e565b60a08401526101408401359150808211156145e757600080fd5b506145f484828501614496565b60c08301525092915050565b6000806040838503121561461357600080fd5b823567ffffffffffffffff8082111561462b57600080fd5b61463786838701614516565b9350602085013591508082111561464d57600080fd5b5061465a85828601614496565b9150509250929050565b60006020828403121561467657600080fd5b813567ffffffffffffffff81111561468d57600080fd5b820160a08185031215613d8357600080fd5b801515811461107857600080fd5b80356141df8161469f565b600060208083850312156146cb57600080fd5b823567ffffffffffffffff808211156146e357600080fd5b818501915085601f8301126146f757600080fd5b81356147056143b3826143ea565b81815260059190911b8301840190848101908883111561472457600080fd5b8585015b838110156147b4578035858111156147405760008081fd5b86016060818c03601f19018113156147585760008081fd5b61476061416b565b61476b8a840161427f565b815260408084013561477c8161469f565b828c01529183013591888311156147935760008081fd5b6147a18e8c85870101614394565b9082015285525050918601918601614728565b5098975050505050505050565b600082601f8301126147d257600080fd5b813560206147e26143b3836143ea565b82815260059290921b8401810191818101908684111561480157600080fd5b8286015b84811015611d0357803567ffffffffffffffff8111156148255760008081fd5b6148338986838b0101614516565b845250918301918301614805565b600082601f83011261485257600080fd5b813560206148626143b3836143ea565b82815260059290921b8401810191818101908684111561488157600080fd5b8286015b84811015611d0357803567ffffffffffffffff8111156148a55760008081fd5b6148b38986838b0101614496565b845250918301918301614885565b600082601f8301126148d257600080fd5b813560206148e26143b3836143ea565b8083825260208201915060208460051b87010193508684111561490457600080fd5b602086015b84811015611d035780358352918301918301614909565b600082601f83011261493157600080fd5b813560206149416143b3836143ea565b82815260059290921b8401810191818101908684111561496057600080fd5b8286015b84811015611d0357803567ffffffffffffffff808211156149855760008081fd5b818901915060a080601f19848d030112156149a05760008081fd5b6149a8614102565b6149b388850161427f565b8152604080850135848111156149c95760008081fd5b6149d78e8b838901016147c1565b8a84015250606080860135858111156149f05760008081fd5b6149fe8f8c838a0101614841565b8385015250608091508186013585811115614a195760008081fd5b614a278f8c838a01016148c1565b9184019190915250919093013590830152508352918301918301614964565b6000806040808486031215614a5a57600080fd5b833567ffffffffffffffff80821115614a7257600080fd5b614a7e87838801614920565b9450602091508186013581811115614a9557600080fd5b8601601f81018813614aa657600080fd5b8035614ab46143b3826143ea565b81815260059190911b8201840190848101908a831115614ad357600080fd5b8584015b83811015614b5f57803586811115614aef5760008081fd5b8501603f81018d13614b015760008081fd5b87810135614b116143b3826143ea565b81815260059190911b82018a0190898101908f831115614b315760008081fd5b928b01925b82841015614b4f5783358252928a0192908a0190614b36565b8652505050918601918601614ad7565b50809750505050505050509250929050565b803560ff811681146141df57600080fd5b600060208284031215614b9457600080fd5b610c4882614b71565b60008151808452602080850194506020840160005b83811015614bd75781516001600160a01b031687529582019590820190600101614bb2565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c3160e0840182614b9d565b90506040840151601f198483030160c0850152614c4e8282614b9d565b95945050505050565b60008060408385031215614c6a57600080fd5b614c738361427f565b946020939093013593505050565b60008060208385031215614c9457600080fd5b823567ffffffffffffffff80821115614cac57600080fd5b818501915085601f830112614cc057600080fd5b813581811115614ccf57600080fd5b8660208260061b8501011115614ce457600080fd5b60209290920196919550909350505050565b600060208284031215614d0857600080fd5b610c488261427f565b6020815281511515602082015267ffffffffffffffff60208301511660408201526000604083015160608084015261368b6080840182613ee5565b600060208284031215614d5e57600080fd5b8135613d83816141bf565b600082601f830112614d7a57600080fd5b81356020614d8a6143b3836143ea565b8083825260208201915060208460051b870101935086841115614dac57600080fd5b602086015b84811015611d03578035614dc4816141bf565b8352918301918301614db1565b60006020808385031215614de457600080fd5b823567ffffffffffffffff80821115614dfc57600080fd5b818501915085601f830112614e1057600080fd5b8135614e1e6143b3826143ea565b81815260059190911b83018401908481019088831115614e3d57600080fd5b8585015b838110156147b457803585811115614e5857600080fd5b860160c0818c03601f19011215614e6f5760008081fd5b614e776140d9565b8882013581526040614e8a818401614b71565b8a8301526060614e9b818501614b71565b8284015260809150614eae8285016146ad565b9083015260a08381013589811115614ec65760008081fd5b614ed48f8d83880101614d69565b838501525060c0840135915088821115614eee5760008081fd5b614efc8e8c84870101614d69565b9083015250845250918601918601614e41565b600060208284031215614f2157600080fd5b5035919050565b80356001600160e01b03811681146141df57600080fd5b600082601f830112614f5057600080fd5b81356020614f606143b3836143ea565b82815260069290921b84018101918181019086841115614f7f57600080fd5b8286015b84811015611d035760408189031215614f9c5760008081fd5b614fa4614125565b614fad8261427f565b8152614fba858301614f28565b81860152835291830191604001614f83565b600082601f830112614fdd57600080fd5b81356020614fed6143b3836143ea565b82815260079290921b8401810191818101908684111561500c57600080fd5b8286015b84811015611d0357808803608081121561502a5760008081fd5b61503261416b565b61503b8361427f565b8152604080601f19840112156150515760008081fd5b615059614125565b925061506687850161427f565b835261507381850161427f565b8388015281870192909252606083013591810191909152835291830191608001615010565b600060208083850312156150ab57600080fd5b823567ffffffffffffffff808211156150c357600080fd5b818501915060408083880312156150d957600080fd5b6150e1614125565b8335838111156150f057600080fd5b84016040818a03121561510257600080fd5b61510a614125565b81358581111561511957600080fd5b8201601f81018b1361512a57600080fd5b80356151386143b3826143ea565b81815260069190911b8201890190898101908d83111561515757600080fd5b928a01925b828410156151a75787848f0312156151745760008081fd5b61517c614125565b8435615187816141bf565b8152615194858d01614f28565b818d0152825292870192908a019061515c565b8452505050818701359350848411156151bf57600080fd5b6151cb8a858401614f3f565b81880152825250838501359150828211156151e557600080fd5b6151f188838601614fcc565b85820152809550505050505092915050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561527057835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615239565b50508583015187820388850152805180835290840192506000918401905b808310156152ca578351805167ffffffffffffffff1683528501516001600160e01b03168583015292840192600192909201919085019061528e565b50979650505050505050565b602081526000610c486020830184615219565b67ffffffffffffffff8316815260608101613d836020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153555761535561531e565b5092915050565b60006020808352606084516040808487015261537b6060870183615219565b87850151878203601f19016040890152805180835290860193506000918601905b808310156147b457845167ffffffffffffffff8151168352878101516153db89850182805167ffffffffffffffff908116835260209182015116910152565b5084015182870152938601936001929092019160809091019061539c565b60006020828403121561540b57600080fd5b813567ffffffffffffffff81111561542257600080fd5b61368b84828501614920565b81810381811115610c4b57610c4b61531e565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061547257615472615441565b92169190910692915050565b8082028115828204841417610c4b57610c4b61531e565b60008151808452602080850194506020840160005b83811015614bd757815180516001600160a01b0316885260209081015190880152604087019650908201906001016154aa565b8051825267ffffffffffffffff60208201511660208301526000604082015160a0604085015261551060a0850182613ee5565b9050606083015184820360608601526155298282613ee5565b91505060808301518482036080860152614c4e8282615495565b602081526000610c4860208301846154dd565b60808152600061556960808301876154dd565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b600082601f8301126155a357600080fd5b81516155b16143b38261436c565b8181528460208386010111156155c657600080fd5b61368b826020830160208701613ec1565b6000806000606084860312156155ec57600080fd5b83516155f78161469f565b602085015190935067ffffffffffffffff81111561561457600080fd5b61562086828701615592565b925050604084015190509250925092565b60006040828403121561564357600080fd5b61564b614125565b6156548361427f565b8152602083013560208201528091505092915050565b600181811c9082168061567e57607f821691505b60208210810361569e57634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156156b657600080fd5b8151613d838161469f565b80820180821115610c4b57610c4b61531e565b60ff8181168382160190811115610c4b57610c4b61531e565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff8084168061572c5761572c615441565b92169190910492915050565b60006020828403121561574a57600080fd5b815167ffffffffffffffff8082111561576257600080fd5b908301906060828603121561577657600080fd5b61577e61416b565b82518281111561578d57600080fd5b61579987828601615592565b8252506020830151828111156157ae57600080fd5b6157ba87828601615592565b6020830152506040830151828111156157d257600080fd5b6157de87828601615592565b60408301525095945050505050565b601f82111561121b576000816000526020600020601f850160051c810160208610156158165750805b601f850160051c820191505b8181101561242957828155600101615822565b815167ffffffffffffffff81111561584f5761584f6140c3565b6158638161585d845461566a565b846157ed565b602080601f83116001811461589857600084156158805750858301515b600019600386901b1c1916600185901b178555612429565b600085815260208120601f198616915b828110156158c7578886015182559484019460019091019084016158a8565b50858210156158e55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020808352835460ff81161515602085015267ffffffffffffffff8160081c166040850152506001808501606080860152600081546159358161566a565b80608089015260a060018316600081146159565760018114615972576159a2565b60ff19841660a08b015260a083151560051b8b010194506159a2565b85600052602060002060005b848110156159995781548c820185015290880190890161597e565b8b0160a0019550505b50929998505050505050505050565b60208101600583106159c5576159c56142ca565b91905290565b60ff81811683821602908116908181146153555761535561531e565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015615a415784546001600160a01b031683526001948501949284019201615a1c565b50508481036060860152615a558188614b9d565b935050505060ff831660808301529695505050505050565b600067ffffffffffffffff808616835280851660208401525060606040830152614c4e6060830184613ee5565b82815260406020820152600061368b6040830184613ee5565b67ffffffffffffffff8481168252831660208201526060810161368b60408301846142e0565b615ae381846142e0565b60406020820152600061368b6040830184613ee5565b600060208284031215615b0b57600080fd5b8151613d83816141bf565b6020815260008251610100806020850152615b35610120850183613ee5565b91506020850151615b52604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615b8c60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615ba98483613ee5565b935060c08701519150808685030160e0870152615bc68483613ee5565b935060e0870151915080868503018387015250615be38382613ee5565b9695505050505050565b600060208284031215615bff57600080fd5b5051919050565b600060ff821660ff8103615c1c57615c1c61531e565b60010192915050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152615be36080830184613ee5565b86815260c060208201526000615c7160c0830188613ee5565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b6020808252825182820181905260009190848201906040850190845b81811015615cfa57835180516001600160a01b031684526020908101519084015260408301938501939250600101615cc7565b50909695505050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015615d5357601f19868403018952615d41838351613ee5565b98840198925090830190600101615d25565b5090979650505050505050565b602081526000610c486020830184615d06565b60408152615dc460408201845180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208401516101608060e0850152615de26101a0850183613ee5565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615e1f8483613ee5565b935060608801519150615e3e6101208701836001600160a01b03169052565b608088015161014087015260a08801519150808685030183870152615e638483615495565b935060c0880151925080868503016101808701525050615e838282615d06565b9150508281036020840152614c4e8185615d06565b6000815160208301516001600160e01b031980821693506004831015615ec85780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", } var EVM2EVMMultiOffRampABI = EVM2EVMMultiOffRampMetaData.ABI @@ -583,15 +584,15 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) Execute(report return _EVM2EVMMultiOffRamp.Contract.Execute(&_EVM2EVMMultiOffRamp.TransactOpts, reportContext, report) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { return _EVM2EVMMultiOffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { return _EVM2EVMMultiOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMMultiOffRamp.TransactOpts, message, offchainTokenData) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ExecuteSingleMessage(message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { return _EVM2EVMMultiOffRamp.Contract.ExecuteSingleMessage(&_EVM2EVMMultiOffRamp.TransactOpts, message, offchainTokenData) } @@ -2220,7 +2221,7 @@ func (EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) Topic() common.Hash { } func (EVM2EVMMultiOffRampSourceChainConfigSet) Topic() common.Hash { - return common.HexToHash("0xb8f0c74385134334c728fcac437ec6c6397c9f2c1440532b0c44175a090b1401") + return common.HexToHash("0x4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba") } func (EVM2EVMMultiOffRampSourceChainSelectorAdded) Topic() common.Hash { @@ -2270,7 +2271,7 @@ type EVM2EVMMultiOffRampInterface interface { Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) - ExecuteSingleMessage(opts *bind.TransactOpts, message InternalEVM2EVMMessage, offchainTokenData [][]byte) (*types.Transaction, error) + ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go index 6b45c341a0..fadeefb48b 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go @@ -137,8 +137,8 @@ type InternalEVM2EVMMessage struct { } var EVM2EVMMultiOnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"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\":[{\"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\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainDynamicConfigUpdated\",\"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\"},{\"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\":\"uint256\",\"name\":\"destChainSelector\",\"type\":\"uint256\"},{\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"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\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":[{\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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: "0x6101406040523480156200001257600080fd5b5060405162006b4538038062006b458339810160408190526200003591620014af565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000214565b505085516001600160a01b031615905080620000e6575060208501516001600160401b0316155b80620000fd575060608501516001600160a01b0316155b8062000114575060808501516001600160a01b0316155b806200012b575060a08501516001600160a01b0316155b156200014a576040516306b7c75960e31b815260040160405180910390fd5b84516001600160a01b0390811660a090815260208701516001600160401b031660c05260408701516001600160601b031660809081526060880151831660e0528701518216610100528601511661012052620001a684620002bf565b620001b18362000482565b620001bc8262000a00565b60408051600080825260208201909252620002099183919062000202565b6040805180820190915260008082526020820152815260200190600190039081620001da5790505b5062000acc565b5050505050620018f7565b336001600160a01b038216036200026e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b03161580620002e5575060608101516001600160a01b0316155b1562000304576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b039283166001600160a01b0319918216179091556020808401516003805491851691841691909117905560408085015160048054918616918516919091179055606080860151600580549187169190951617909355805160c0808201835260a080518716835290516001600160401b031693820193909352608080516001600160601b03168284015260e05186169482019490945261010051851693810193909352610120519093169082015290517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916200047791849082516001600160a01b0390811682526020808501516001600160401b0316818401526040808601516001600160601b03168185015260608087015184168186015260808088015185169086015260a0968701518416968501969096528451831660c085015290840151821660e084015283015181166101008301529190920151166101208201526101400190565b60405180910390a150565b60005b8151811015620009fc576000828281518110620004a657620004a6620015f5565b602002602001015190506000838381518110620004c757620004c7620015f5565b6020026020010151600001519050806001600160401b031660001480620004fe5750602082015161018001516001600160401b0316155b15620005295760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b600060066000836001600160401b03166001600160401b0316815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a90046001600160401b03166001600160401b031681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff02191690831515021790555090505082600301546000801b03620009195760c051604080517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b360208201526001600160401b0392831691810191909152908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b03821615620008d0576002830180546001600160a01b0319166001600160a01b0384161790555b836001600160401b03167f4be92415590c4554edbd7d3fbf308eeb6e5d00ababade0791f835b4a18416ed6846040516200090b91906200160b565b60405180910390a2620009eb565b60028301546001600160a01b03838116911614620009565760405163c35aa79d60e01b81526001600160401b038516600482015260240162000083565b60208560200151610160015163ffffffff161015620009a357602085015161016001516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000083565b836001600160401b03167f1173725509a61aed633c58cd12e31c104cd26ca24f6c270c8ac81c5f6f12e8e98660200151604051620009e29190620017b5565b60405180910390a25b505050505080600101905062000485565b5050565b60005b8151811015620009fc57600082828151811062000a245762000a24620015f5565b6020026020010151600001519050600083838151811062000a495762000a49620015f5565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a03565b60005b825181101562000d3957600083828151811062000af05762000af0620015f5565b6020026020010151905060008160000151905060005b82602001515181101562000d2a5760008360200151828151811062000b2f5762000b2f620015f5565b602002602001015160200151905060008460200151838151811062000b585762000b58620015f5565b60200260200101516000015190506020826080015163ffffffff16101562000bb15760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d17908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b06565b50505080600101905062000acf565b5060005b815181101562000dff57600082828151811062000d5e5762000d5e620015f5565b6020026020010151600001519050600083838151811062000d835762000d83620015f5565b6020908102919091018101518101516001600160401b03841660008181526008845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917ffa22e84f9c809b5b7e94f084eb45cf17a5e4703cecef8f27ed35e54b719bffcd9190a3505060010162000d3d565b505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000e3f5762000e3f62000e04565b60405290565b60405161020081016001600160401b038111828210171562000e3f5762000e3f62000e04565b604080519081016001600160401b038111828210171562000e3f5762000e3f62000e04565b60405160c081016001600160401b038111828210171562000e3f5762000e3f62000e04565b604051601f8201601f191681016001600160401b038111828210171562000ee05762000ee062000e04565b604052919050565b80516001600160a01b038116811462000f0057600080fd5b919050565b80516001600160401b038116811462000f0057600080fd5b60006080828403121562000f3057600080fd5b604051608081016001600160401b038111828210171562000f555762000f5562000e04565b60405290508062000f668362000ee8565b815262000f766020840162000ee8565b602082015262000f896040840162000ee8565b604082015262000f9c6060840162000ee8565b60608201525092915050565b60006001600160401b0382111562000fc45762000fc462000e04565b5060051b60200190565b8051801515811462000f0057600080fd5b805161ffff8116811462000f0057600080fd5b805163ffffffff8116811462000f0057600080fd5b600082601f8301126200101957600080fd5b81516020620010326200102c8362000fa8565b62000eb5565b82815261024092830285018201928282019190878511156200105357600080fd5b8387015b85811015620012125780890382811215620010725760008081fd5b6200107c62000e1a565b620010878362000f05565b815261020080601f19840112156200109f5760008081fd5b620010a962000e45565b9250620010b888850162000fce565b83526040620010c981860162000fdf565b898501526060620010dc81870162000ff2565b828601526080620010ef81880162000ff2565b8287015260a091506200110482880162000ff2565b9086015260c06200111787820162000fdf565b8287015260e091506200112c82880162000ff2565b908601526101006200114087820162000fdf565b8287015261012091506200115682880162000fdf565b908601526101406200116a87820162000fdf565b8287015261016091506200118082880162000ff2565b908601526101806200119487820162000ff2565b828701526101a09150620011aa82880162000f05565b908601526101c0620011be87820162000f05565b828701526101e09150620011d482880162000ff2565b90860152620011e586840162000fce565b81860152508389840152620011fe610220860162000ee8565b908301525085525092840192810162001057565b5090979650505050505050565b600082601f8301126200123157600080fd5b81516020620012446200102c8362000fa8565b82815260069290921b840181019181810190868411156200126457600080fd5b8286015b84811015620012ba5760408189031215620012835760008081fd5b6200128d62000e6b565b620012988262000ee8565b8152620012a785830162000f05565b8186015283529183019160400162001268565b509695505050505050565b600082601f830112620012d757600080fd5b81516020620012ea6200102c8362000fa8565b82815260059290921b840181019181810190868411156200130a57600080fd5b8286015b84811015620012ba5780516001600160401b03808211156200132f57600080fd5b908801906040601f19838c0381018213156200134a57600080fd5b6200135462000e6b565b6200136189860162000f05565b815282850151848111156200137557600080fd5b8086019550508c603f8601126200138b57600080fd5b888501519350620013a06200102c8562000fa8565b84815260e09094028501830193898101908e861115620013bf57600080fd5b958401955b858710156200149857868f0360e0811215620013df57600080fd5b620013e962000e6b565b620013f48962000ee8565b815260c086830112156200140757600080fd5b6200141162000e90565b9150620014208d8a0162000ff2565b82526200142f878a0162000ff2565b8d8301526200144160608a0162000fdf565b878301526200145360808a0162000ff2565b60608301526200146660a08a0162000ff2565b60808301526200147960c08a0162000fce565b60a0830152808d0191909152825260e09690960195908a0190620013c4565b828b0152508752505050928401925083016200130e565b60008060008060008587036101a0811215620014ca57600080fd5b60c0811215620014d957600080fd5b50620014e462000e90565b620014ef8762000ee8565b8152620014ff6020880162000f05565b602082015260408701516001600160601b03811681146200151f57600080fd5b6040820152620015326060880162000ee8565b6060820152620015456080880162000ee8565b60808201526200155860a0880162000ee8565b60a082015294506200156e8760c0880162000f1d565b6101408701519094506001600160401b03808211156200158d57600080fd5b6200159b89838a0162001007565b9450610160880151915080821115620015b357600080fd5b620015c189838a016200121f565b9350610180880151915080821115620015d957600080fd5b50620015e888828901620012c5565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c811660408601526200165360608601828560381c1663ffffffff169052565b6200166b60808601828560581c1663ffffffff169052565b6200168160a08601838560781c1661ffff169052565b6200169960c08601828560881c1663ffffffff169052565b620016af60e08601838560a81c1661ffff169052565b620016c66101008601838560b81c1661ffff169052565b620016dd6101208601838560c81c1661ffff169052565b620016f66101408601828560d81c1663ffffffff169052565b600186015463ffffffff8282161661016087015292506001600160401b03602084901c811661018087015291506200173f6101a08601838560601c166001600160401b03169052565b620017586101c08601828560a01c1663ffffffff169052565b506200176f6101e0850160ff8460c01c1615159052565b60028501546001600160a01b0381166102008601529150620017a26102208501828460a01c166001600160401b03169052565b5050600383015461024083015292915050565b81511515815261020081016020830151620017d6602084018261ffff169052565b506040830151620017ef604084018263ffffffff169052565b50606083015162001808606084018263ffffffff169052565b50608083015162001821608084018263ffffffff169052565b5060a08301516200183860a084018261ffff169052565b5060c08301516200185160c084018263ffffffff169052565b5060e08301516200186860e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b03908116918501919091526101a080860151909116908401526101c080850151909116908301526101e0928301511515929091019190915290565b60805160a05160c05160e0516101005161012051615195620019b0600039600081816102da01528181610f260152612adf0152600081816102ab01528181612ab7015261323e01526000818161027c01528181612a8d0152612bf30152600081816102180152818161265001528181612a2801526130f90152600081816101e901528181612a0301528181612eda0152612f8401526000818161024801528181612a5a0152818161304601526130b601526151956000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063a69c64c011610081578063df0aa9e911610066578063df0aa9e9146108c0578063f2fde38b146108d3578063fbca3b74146108e657600080fd5b8063a69c64c01461089a578063a6f3ab6c146108ad57600080fd5b80638da5cb5b116100b25780638da5cb5b146108635780639041be3d14610874578063932e53c81461088757600080fd5b806379ba5097146106f857806382b49eb01461070057600080fd5b80633a019940116101245780636def4ce7116101095780636def4ce7146103b65780637437ff9f14610672578063770e2dc4146106e557600080fd5b80633a0199401461038157806348a98aa41461038b57600080fd5b8063061877e31461015657806306285c69146101a7578063181f5a771461031757806320487ded14610360575b600080fd5b610189610164366004613945565b6001600160a01b031660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61030a6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161019e9190613962565b6103536040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161019e9190613a1e565b61037361036e366004613a6a565b610906565b60405190815260200161019e565b610389610d27565b005b61039e610399366004613aba565b610eeb565b6040516001600160a01b03909116815260200161019e565b6106656103c4366004613af3565b604080516102808101825260006080820181815260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e08301829052610200830182905261022083018290526102408301829052610260830182905282526020820181905291810182905260608101919091525067ffffffffffffffff908116600090815260066020908152604091829020825161028081018452815460ff80821615156080840190815261ffff610100808504821660a087015263ffffffff63010000008604811660c08801526701000000000000008604811660e08801526b01000000000000000000000086048116918701919091526f01000000000000000000000000000000850482166101208701527101000000000000000000000000000000000085048116610140870152750100000000000000000000000000000000000000000085048216610160870152770100000000000000000000000000000000000000000000008504821661018087015279010000000000000000000000000000000000000000000000000085049091166101a08601527b0100000000000000000000000000000000000000000000000000000090930483166101c085015260018501548084166101e0860152640100000000810489166102008601526c010000000000000000000000008104891661022086015274010000000000000000000000000000000000000000808204909416610240860152780100000000000000000000000000000000000000000000000090049091161515610260840152825260028301546001600160a01b0381169483019490945290920490931691810191909152600390910154606082015290565b60405161019e9190613c41565b6106d860408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526002546001600160a01b03908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161019e9190613c8e565b6103896106f3366004613ec1565b610f9a565b610389610fb0565b61080361070e366004613aba565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff9190911660009081526008602090815260408083206001600160a01b0394909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b60405161019e9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b6000546001600160a01b031661039e565b610189610882366004613af3565b611079565b61038961089536600461413b565b6110bd565b6103896108a8366004614348565b6110d1565b6103896108bb366004614406565b6110e2565b6103736108ce36600461448b565b6110f3565b6103896108e1366004613945565b61157b565b6108f96108f4366004613af3565b61158c565b60405161019e91906144f7565b67ffffffffffffffff82166000908152600660205260408120805460ff1661096b576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b600061099961097d6080860186614544565b6001850154640100000000900467ffffffffffffffff166115c0565b90506109ca856109ac6020870187614544565b84519091506109be6040890189614592565b9050856020015161172d565b60006007816109df6080880160608901613945565b6001600160a01b03168152602081019190915260400160009081205467ffffffffffffffff169150819003610a5c57610a1e6080860160608701613945565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b60035460009081906001600160a01b031663ffdb4b37610a8260808a0160608b01613945565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8b1660248201526044016040805180830381865afa158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b119190614608565b90925090506000808080610b2860408c018c614592565b90501115610b6357610b578b610b4460808d0160608e01613945565b87610b5260408f018f614592565b6118a3565b91945092509050610b9a565b6001880154610b979074010000000000000000000000000000000000000000900463ffffffff16662386f26fc10000614661565b92505b875460009077010000000000000000000000000000000000000000000000900461ffff1615610c0657610c038c6dffffffffffffffffffffffffffff607088901c16610be960208f018f614544565b90508e8060400190610bfb9190614592565b905086611c94565b90505b600089600101600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff168463ffffffff168b600001600f9054906101000a900461ffff1661ffff168e8060200190610c599190614544565b610c64929150614661565b8c548c51610c87916b010000000000000000000000900463ffffffff1690614678565b610c919190614678565b610c9b9190614678565b610cb5906dffffffffffffffffffffffffffff8916614661565b610cbf9190614661565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff87168282610cf667ffffffffffffffff8c1689614661565b610d009190614678565b610d0a9190614678565b610d14919061468b565b9a50505050505050505050505b92915050565b600354604080517fcdc73d5100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163cdc73d5191600480830192869291908290030181865afa158015610d89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610db191908101906146c6565b6005549091506001600160a01b031660005b8251811015610ee6576000838281518110610de057610de0614755565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e729190614784565b90508015610edc57610e8e6001600160a01b0383168583611d9a565b816001600160a01b0316846001600160a01b03167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ed391815260200190565b60405180910390a35b5050600101610dc3565b505050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f93919061479d565b9392505050565b610fa2611e1a565b610fac8282611e76565b5050565b6001546001600160a01b0316331461100a5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610962565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120600201549091610d21917401000000000000000000000000000000000000000090041660016147ba565b6110c5611e1a565b6110ce81612256565b50565b6110d9611e1a565b6110ce81612849565b6110ea611e1a565b6110ce81612926565b67ffffffffffffffff841660009081526006602052604081208161111a8288888888612b3f565b905060005b8161014001515181101561151157600061113c6040890189614592565b8381811061114c5761114c614755565b90506040020180360381019061116291906147e2565b905080602001516000036111a2576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111b28a8360000151610eeb565b90506001600160a01b038116158061126857506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611266919061481c565b155b156112ad5781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b6000816001600160a01b0316639a4575b96040518060a001604052808d80600001906112d99190614544565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff8f166020808301919091526001600160a01b03808e16604080850191909152918901516060840152885116608090920191909152517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526113849190600401614839565b6000604051808303816000875af11580156113a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113cb9190810190614906565b9050602081602001515111801561142c575067ffffffffffffffff8b16600090815260086020908152604080832086516001600160a01b0316845282529091205490820151516e01000000000000000000000000000090910463ffffffff16105b156114715782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b805161147c906133f7565b5060408051606081019091526001600160a01b03831660808201528060a0810160405160208183030381529060405281526020018260000151815260200182602001518152506040516020016114d29190614997565b60405160208183030381529060405285610160015185815181106114f8576114f8614755565b602002602001018190525050505080600101905061111f565b50611520818360030154613452565b61018082015260405167ffffffffffffffff8816907fc79f9c3e610deac14de4e704195fe17eab0983ee9916866bc04d16a00f54daa690611562908490614aa2565b60405180910390a261018001519150505b949350505050565b611583611e1a565b6110ce816135ad565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260008082526020820152600083900361160157506040805180820190915267ffffffffffffffff8216815260006020820152610f93565b600061160d8486614bd7565b90507fe7e230f0000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161167a576116658460048188614c1f565b8101906116729190614c49565b915050610f93565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016116fb5760408051808201909152806116db866004818a614c1f565b8101906116e89190614c81565b815260006020909101529150610f939050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8516600090815260066020526040902080546301000000900463ffffffff168511156117a65780546040517f86933789000000000000000000000000000000000000000000000000000000008152630100000090910463ffffffff16600482015260248101869052604401610962565b8054670100000000000000900463ffffffff168411156117f2576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8054610100900461ffff16831115611836576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018101547801000000000000000000000000000000000000000000000000900460ff168015611864575081155b1561189b576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000808083815b81811015611c875760008787838181106118c6576118c6614755565b9050604002018036038101906118dc91906147e2565b905060006001600160a01b03166118f78c8360000151610eeb565b6001600160a01b0316036119455780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b67ffffffffffffffff8b16600090815260086020908152604080832084516001600160a01b03168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052611ab35767ffffffffffffffff8c1660009081526006602052604090208054611a5390790100000000000000000000000000000000000000000000000000900461ffff16662386f26fc10000614661565b611a5d9089614678565b8154909850611a91907b01000000000000000000000000000000000000000000000000000000900463ffffffff1688614c9a565b6001820154909750611aa99063ffffffff1687614c9a565b9550505050611c7f565b604081015160009061ffff1615611bcf5760008c6001600160a01b031684600001516001600160a01b031614611b725760035484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015611b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6b9190614cb7565b9050611b75565b508a5b620186a0836040015161ffff16611bb78660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661366e90919063ffffffff16565b611bc19190614661565b611bcb919061468b565b9150505b6060820151611bde9088614c9a565b9650816080015186611bf09190614c9a565b8251909650600090611c0f9063ffffffff16662386f26fc10000614661565b905080821015611c2e57611c23818a614678565b985050505050611c7f565b6000836020015163ffffffff16662386f26fc10000611c4d9190614661565b905080831115611c6d57611c61818b614678565b99505050505050611c7f565b611c77838b614678565b995050505050505b6001016118aa565b5050955095509592505050565b60008063ffffffff8316611ca9608086614661565b611cb587610220614678565b611cbf9190614678565b611cc99190614678565b67ffffffffffffffff8816600090815260066020526040812080549293509171010000000000000000000000000000000000810463ffffffff1690611d2b907501000000000000000000000000000000000000000000900461ffff1685614661565b611d359190614678565b825490915077010000000000000000000000000000000000000000000000900461ffff16611d736dffffffffffffffffffffffffffff8a1683614661565b611d7d9190614661565b611d8d90655af3107a4000614661565b9998505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610ee69084906136ab565b6000546001600160a01b03163314611e745760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610962565b565b60005b825181101561217f576000838281518110611e9657611e96614755565b6020026020010151905060008160000151905060005b82602001515181101561217157600083602001518281518110611ed157611ed1614755565b6020026020010151602001519050600084602001518381518110611ef757611ef7614755565b60200260200101516000015190506020826080015163ffffffff161015611f675760808201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015263ffffffff9091166024820152604401610962565b67ffffffffffffffff841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59061215f908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101611eac565b505050806001019050611e79565b5060005b8151811015610ee65760008282815181106121a0576121a0614755565b602002602001015160000151905060008383815181106121c2576121c2614755565b60209081029190910181015181015167ffffffffffffffff841660008181526008845260408082206001600160a01b038516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917ffa22e84f9c809b5b7e94f084eb45cf17a5e4703cecef8f27ed35e54b719bffcd9190a35050600101612183565b60005b8151811015610fac57600082828151811061227657612276614755565b60200260200101519050600083838151811061229457612294614755565b60200260200101516000015190508067ffffffffffffffff16600014806122cc57506020820151610180015167ffffffffffffffff16155b1561230f576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610962565b6000600660008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff02191690831515021790555090505082600301546000801b0361273957604080517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b038216156126f2576002830180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555b8367ffffffffffffffff167f4be92415590c4554edbd7d3fbf308eeb6e5d00ababade0791f835b4a18416ed68460405161272c9190614cd2565b60405180910390a2612839565b60028301546001600160a01b0383811691161461278e576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610962565b60208560200151610160015163ffffffff1610156127f257602085015161016001516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610962565b8367ffffffffffffffff167f1173725509a61aed633c58cd12e31c104cd26ca24f6c270c8ac81c5f6f12e8e986602001516040516128309190614e73565b60405180910390a25b5050505050806001019050612259565b60005b8151811015610fac57600082828151811061286957612869614755565b6020026020010151600001519050600083838151811061288b5761288b614755565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161284c565b60208101516001600160a01b0316158061294b575060608101516001600160a01b0316155b15612982576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556020808401516003805484169185169190911790556040808501516004805485169186169190911790556060808601516005805490951690861617909355805160c0810182527f0000000000000000000000000000000000000000000000000000000000000000851681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16928101929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16828201527f00000000000000000000000000000000000000000000000000000000000000008416928201929092527f0000000000000000000000000000000000000000000000000000000000000000831660808201527f000000000000000000000000000000000000000000000000000000000000000090921660a0830152517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa91612b34918490614e82565b60405180910390a150565b604080516101a08101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820181905261014082018190526101608201526101808101919091526040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608086901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c66919061481c565b15612ca9576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610962565b6001600160a01b038216612ce9576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546001600160a01b03163314612d2d576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460ff16612d74576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610962565b6000612da2612d866080870187614544565b60018a0154640100000000900467ffffffffffffffff166115c0565b90506000612db36040870187614592565b9150612dda905087612dc86020890189614544565b9050846000015184866020015161172d565b8015612ece576004546001600160a01b03168015612ecc576040517fe0a0e5060000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063e0a0e50690612e39908b908b90600401614fe4565b600060405180830381600087803b158015612e5357600080fd5b505af1925050508015612e64575060015b612ecc573d808015612e92576040519150601f19603f3d011682016040523d82523d6000602084013e612e97565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016109629190613a1e565b505b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612f0a6080890160608a01613945565b6001600160a01b031603612f1f575084612ff2565b6003546001600160a01b03166241e5be612f3f60808a0160608b01613945565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039182166004820152602481018a90527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015612fcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fef9190614784565b90505b6130026080880160608901613945565b6001600160a01b03167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8260405161303c91815260200190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff168111156130e3576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018290526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610962565b604080516101a08101825267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526001600160a01b038716602082015290810161317461313a8a80614544565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133f792505050565b6001600160a01b031681526020018a600201601481819054906101000a900467ffffffffffffffff166131a690615102565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020018460000151815260200160001515815260200184602001516132b0576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526001600160a01b0388811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015613287573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ab9190615129565b6132b3565b60005b67ffffffffffffffff1681526020016132d260808a0160608b01613945565b6001600160a01b031681526020018781526020018880602001906132f69190614544565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161333d60408a018a614592565b808060200260200160405190810160405280939291908181526020016000905b828210156133895761337a604083028601368190038101906147e2565b8152602001906001019061335d565b505050505081526020018367ffffffffffffffff8111156133ac576133ac613cca565b6040519080825280602002602001820160405280156133df57816020015b60608152602001906001900390816133ca5790505b50815260006020909101529998505050505050505050565b6000815160201461343657816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109629190613a1e565b610d218280602001905181019061344d9190614784565b613790565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016134e89897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016135219190615146565b6040516020818303038152906040528051906020012087610160015160405160200161354d9190615159565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b336001600160a01b038216036136055760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610962565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a76400006136a1837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616614661565b610f93919061468b565b6000613700826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137fd9092919063ffffffff16565b805190915015610ee6578080602001905181019061371e919061481c565b610ee65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610962565b60006001600160a01b038211806137a8575061040082105b156137f95760408051602081018490520160408051601f19818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261096291600401613a1e565b5090565b6060611573848460008585600080866001600160a01b03168587604051613824919061516c565b60006040518083038185875af1925050503d8060008114613861576040519150601f19603f3d011682016040523d82523d6000602084013e613866565b606091505b509150915061387787838387613882565b979650505050505050565b606083156138f15782516000036138ea576001600160a01b0385163b6138ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610962565b5081611573565b61157383838151156139065781518083602001fd5b8060405162461bcd60e51b81526004016109629190613a1e565b6001600160a01b03811681146110ce57600080fd5b803561394081613920565b919050565b60006020828403121561395757600080fd5b8135610f9381613920565b60c08101610d2182846001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60005b838110156139e95781810151838201526020016139d1565b50506000910152565b60008151808452613a0a8160208601602086016139ce565b601f01601f19169290920160200192915050565b602081526000610f9360208301846139f2565b67ffffffffffffffff811681146110ce57600080fd5b803561394081613a31565b600060a08284031215613a6457600080fd5b50919050565b60008060408385031215613a7d57600080fd5b8235613a8881613a31565b9150602083013567ffffffffffffffff811115613aa457600080fd5b613ab085828601613a52565b9150509250929050565b60008060408385031215613acd57600080fd5b8235613ad881613a31565b91506020830135613ae881613920565b809150509250929050565b600060208284031215613b0557600080fd5b8135610f9381613a31565b8051151582526020810151613b2b602084018261ffff169052565b506040810151613b43604084018263ffffffff169052565b506060810151613b5b606084018263ffffffff169052565b506080810151613b73608084018263ffffffff169052565b5060a0810151613b8960a084018261ffff169052565b5060c0810151613ba160c084018263ffffffff169052565b5060e0810151613bb760e084018261ffff169052565b506101008181015161ffff9081169184019190915261012080830151909116908301526101408082015163ffffffff90811691840191909152610160808301518216908401526101808083015167ffffffffffffffff908116918501919091526101a080840151909116908401526101c080830151909116908301526101e0908101511515910152565b600061026082019050613c55828451613b10565b60208301516001600160a01b0316610200830152604083015167ffffffffffffffff166102208301526060909201516102409091015290565b60808101610d21828480516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b60405290565b60405160c0810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b6040516060810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b604051610200810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b604051601f8201601f1916810167ffffffffffffffff81118282101715613db557613db5613cca565b604052919050565b600067ffffffffffffffff821115613dd757613dd7613cca565b5060051b60200190565b803563ffffffff8116811461394057600080fd5b803561ffff8116811461394057600080fd5b80151581146110ce57600080fd5b803561394081613e07565b600082601f830112613e3157600080fd5b81356020613e46613e4183613dbd565b613d8c565b82815260069290921b84018101918181019086841115613e6557600080fd5b8286015b84811015613eb65760408189031215613e825760008081fd5b613e8a613cf9565b8135613e9581613a31565b815281850135613ea481613920565b81860152835291830191604001613e69565b509695505050505050565b60008060408385031215613ed457600080fd5b67ffffffffffffffff83351115613eea57600080fd5b83601f843585010112613efc57600080fd5b613f0c613e418435850135613dbd565b8335840180358083526020808401939260059290921b90910101861015613f3257600080fd5b602085358601015b85358601803560051b016020018110156141055767ffffffffffffffff81351115613f6457600080fd5b6040601f19823588358901018903011215613f7e57600080fd5b613f86613cf9565b613f996020833589358a01010135613a31565b863587018235016020810135825267ffffffffffffffff6040909101351115613fc157600080fd5b86358701823501604081013501603f81018913613fdd57600080fd5b613fed613e416020830135613dbd565b602082810135808352908201919060e00283016040018b101561400f57600080fd5b604083015b604060e06020860135028501018110156140ec5760e0818d03121561403857600080fd5b614040613cf9565b61404a8235613920565b8135815260c0601f19838f0301121561406257600080fd5b61406a613d22565b61407660208401613de1565b815261408460408401613de1565b602082015261409560608401613df5565b60408201526140a660808401613de1565b60608201526140b760a08401613de1565b60808201526140c960c0840135613e07565b60c083013560a0820152602082810191909152908452929092019160e001614014565b5060208481019190915292865250509283019201613f3a565b5092505067ffffffffffffffff6020840135111561412257600080fd5b6141328460208501358501613e20565b90509250929050565b6000602080838503121561414e57600080fd5b823567ffffffffffffffff81111561416557600080fd5b8301601f8101851361417657600080fd5b8035614184613e4182613dbd565b81815261024091820283018401918482019190888411156141a457600080fd5b938501935b8385101561433c57848903818112156141c25760008081fd5b6141ca613d45565b86356141d581613a31565b8152610200601f1983018113156141ec5760008081fd5b6141f4613d68565b9250614201898901613e15565b83526040614210818a01613df5565b8a8501526060614221818b01613de1565b828601526080614232818c01613de1565b8287015260a09150614245828c01613de1565b9086015260c06142568b8201613df5565b8287015260e09150614269828c01613de1565b9086015261010061427b8b8201613df5565b82870152610120915061428f828c01613df5565b908601526101406142a18b8201613df5565b8287015261016091506142b5828c01613de1565b908601526101806142c78b8201613de1565b828701526101a091506142db828c01613a47565b908601526101c06142ed8b8201613a47565b828701526101e09150614301828c01613de1565b908601526143108a8401613e15565b8186015250838a8401526143276102208a01613935565b908301525084525093840193918501916141a9565b50979650505050505050565b6000602080838503121561435b57600080fd5b823567ffffffffffffffff81111561437257600080fd5b8301601f8101851361438357600080fd5b8035614391613e4182613dbd565b81815260069190911b820183019083810190878311156143b057600080fd5b928401925b8284101561387757604084890312156143ce5760008081fd5b6143d6613cf9565b84356143e181613920565b8152848601356143f081613a31565b81870152825260409390930192908401906143b5565b60006080828403121561441857600080fd5b6040516080810181811067ffffffffffffffff8211171561443b5761443b613cca565b604052823561444981613920565b8152602083013561445981613920565b6020820152604083013561446c81613920565b6040820152606083013561447f81613920565b60608201529392505050565b600080600080608085870312156144a157600080fd5b84356144ac81613a31565b9350602085013567ffffffffffffffff8111156144c857600080fd5b6144d487828801613a52565b9350506040850135915060608501356144ec81613920565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b818110156145385783516001600160a01b031683529284019291840191600101614513565b50909695505050505050565b6000808335601e1984360301811261455b57600080fd5b83018035915067ffffffffffffffff82111561457657600080fd5b60200191503681900382131561458b57600080fd5b9250929050565b6000808335601e198436030181126145a957600080fd5b83018035915067ffffffffffffffff8211156145c457600080fd5b6020019150600681901b360382131561458b57600080fd5b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461394057600080fd5b6000806040838503121561461b57600080fd5b614624836145dc565b9150614132602084016145dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610d2157610d21614632565b80820180821115610d2157610d21614632565b6000826146c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208083850312156146d957600080fd5b825167ffffffffffffffff8111156146f057600080fd5b8301601f8101851361470157600080fd5b805161470f613e4182613dbd565b81815260059190911b8201830190838101908783111561472e57600080fd5b928401925b8284101561387757835161474681613920565b82529284019290840190614733565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561479657600080fd5b5051919050565b6000602082840312156147af57600080fd5b8151610f9381613920565b67ffffffffffffffff8181168382160190808211156147db576147db614632565b5092915050565b6000604082840312156147f457600080fd5b6147fc613cf9565b823561480781613920565b81526020928301359281019290925250919050565b60006020828403121561482e57600080fd5b8151610f9381613e07565b602081526000825160a0602084015261485560c08401826139f2565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f8301126148b357600080fd5b815167ffffffffffffffff8111156148cd576148cd613cca565b6148e06020601f19601f84011601613d8c565b8181528460208386010111156148f557600080fd5b6115738260208301602087016139ce565b60006020828403121561491857600080fd5b815167ffffffffffffffff8082111561493057600080fd5b908301906040828603121561494457600080fd5b61494c613cf9565b82518281111561495b57600080fd5b614967878286016148a2565b82525060208301518281111561497c57600080fd5b614988878286016148a2565b60208301525095945050505050565b6020815260008251606060208401526149b360808401826139f2565b90506020840151601f19808584030160408601526149d183836139f2565b92506040860151915080858403016060860152506149ef82826139f2565b95945050505050565b60008151808452602080850194506020840160005b83811015614a3d57815180516001600160a01b031688528301518388015260409096019590820190600101614a0d565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015614a9557601f19868403018952614a838383516139f2565b98840198925090830190600101614a67565b5090979650505050505050565b60208152614abd60208201835167ffffffffffffffff169052565b60006020830151614ad960408401826001600160a01b03169052565b5060408301516001600160a01b038116606084015250606083015167ffffffffffffffff8116608084015250608083015160a083015260a0830151614b2260c084018215159052565b5060c083015167ffffffffffffffff811660e08401525060e0830151610100614b55818501836001600160a01b03169052565b840151610120848101919091528401516101a061014080860182905291925090614b836101c08601846139f2565b9250808601519050601f19610160818786030181880152614ba485846149f8565b945080880151925050610180818786030181880152614bc38584614a48565b970151959092019490945250929392505050565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614c175780818660040360031b1b83161692505b505092915050565b60008085851115614c2f57600080fd5b83861115614c3c57600080fd5b5050820193919092039150565b600060408284031215614c5b57600080fd5b614c63613cf9565b823581526020830135614c7581613e07565b60208201529392505050565b600060208284031215614c9357600080fd5b5035919050565b63ffffffff8181168382160190808211156147db576147db614632565b600060208284031215614cc957600080fd5b610f93826145dc565b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c81166040860152614d1960608601828560381c1663ffffffff169052565b614d3060808601828560581c1663ffffffff169052565b614d4560a08601838560781c1661ffff169052565b614d5c60c08601828560881c1663ffffffff169052565b614d7160e08601838560a81c1661ffff169052565b614d876101008601838560b81c1661ffff169052565b614d9d6101208601838560c81c1661ffff169052565b614db56101408601828560d81c1663ffffffff169052565b600186015463ffffffff82821616610160870152925067ffffffffffffffff602084901c81166101808701529150614dff6101a08601838560601c1667ffffffffffffffff169052565b614e176101c08601828560a01c1663ffffffff169052565b50614e2d6101e0850160ff8460c01c1615159052565b60028501546001600160a01b0381166102008601529150614e606102208501828460a01c1667ffffffffffffffff169052565b5050600383015461024083015292915050565b6102008101610d218284613b10565b6101408101614eef82856001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b82516001600160a01b0390811660c08401526020840151811660e084015260408401518116610100840152606084015116610120830152610f93565b6000808335601e19843603018112614f4257600080fd5b830160208101925035905067ffffffffffffffff811115614f6257600080fd5b80360382131561458b57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8183526000602080850194508260005b85811015614a3d578135614fbf81613920565b6001600160a01b03168752818301358388015260409687019690910190600101614fac565b600067ffffffffffffffff8085168352604060208401526150058485614f2b565b60a0604086015261501a60e086018284614f71565b91505061502a6020860186614f2b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152615060848385614f71565b935060408801359250601e1988360301831261507b57600080fd5b6020928801928301923591508482111561509457600080fd5b8160061b36038313156150a657600080fd5b808785030160808801526150bb848385614f9c565b94506150c960608901613935565b6001600160a01b03811660a089015293506150e76080890189614f2b565b94509250808786030160c08801525050613877838383614f71565b600067ffffffffffffffff80831681810361511f5761511f614632565b6001019392505050565b60006020828403121561513b57600080fd5b8151610f9381613a31565b602081526000610f9360208301846149f8565b602081526000610f936020830184614a48565b6000825161517e8184602087016139ce565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"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\":[{\"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\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainDynamicConfigUpdated\",\"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\"},{\"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\":\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"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\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":[{\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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: "0x6101406040523480156200001257600080fd5b5060405162006b4538038062006b458339810160408190526200003591620014af565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000214565b505085516001600160a01b031615905080620000e6575060208501516001600160401b0316155b80620000fd575060608501516001600160a01b0316155b8062000114575060808501516001600160a01b0316155b806200012b575060a08501516001600160a01b0316155b156200014a576040516306b7c75960e31b815260040160405180910390fd5b84516001600160a01b0390811660a090815260208701516001600160401b031660c05260408701516001600160601b031660809081526060880151831660e0528701518216610100528601511661012052620001a684620002bf565b620001b18362000482565b620001bc8262000a00565b60408051600080825260208201909252620002099183919062000202565b6040805180820190915260008082526020820152815260200190600190039081620001da5790505b5062000acc565b5050505050620018f7565b336001600160a01b038216036200026e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b03161580620002e5575060608101516001600160a01b0316155b1562000304576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b039283166001600160a01b0319918216179091556020808401516003805491851691841691909117905560408085015160048054918616918516919091179055606080860151600580549187169190951617909355805160c0808201835260a080518716835290516001600160401b031693820193909352608080516001600160601b03168284015260e05186169482019490945261010051851693810193909352610120519093169082015290517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916200047791849082516001600160a01b0390811682526020808501516001600160401b0316818401526040808601516001600160601b03168185015260608087015184168186015260808088015185169086015260a0968701518416968501969096528451831660c085015290840151821660e084015283015181166101008301529190920151166101208201526101400190565b60405180910390a150565b60005b8151811015620009fc576000828281518110620004a657620004a6620015f5565b602002602001015190506000838381518110620004c757620004c7620015f5565b6020026020010151600001519050806001600160401b031660001480620004fe5750602082015161018001516001600160401b0316155b15620005295760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b600060066000836001600160401b03166001600160401b0316815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a90046001600160401b03166001600160401b031681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff02191690831515021790555090505082600301546000801b03620009195760c051604080517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b360208201526001600160401b0392831691810191909152908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b03821615620008d0576002830180546001600160a01b0319166001600160a01b0384161790555b836001600160401b03167f4be92415590c4554edbd7d3fbf308eeb6e5d00ababade0791f835b4a18416ed6846040516200090b91906200160b565b60405180910390a2620009eb565b60028301546001600160a01b03838116911614620009565760405163c35aa79d60e01b81526001600160401b038516600482015260240162000083565b60208560200151610160015163ffffffff161015620009a357602085015161016001516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000083565b836001600160401b03167f1173725509a61aed633c58cd12e31c104cd26ca24f6c270c8ac81c5f6f12e8e98660200151604051620009e29190620017b5565b60405180910390a25b505050505080600101905062000485565b5050565b60005b8151811015620009fc57600082828151811062000a245762000a24620015f5565b6020026020010151600001519050600083838151811062000a495762000a49620015f5565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a03565b60005b825181101562000d3957600083828151811062000af05762000af0620015f5565b6020026020010151905060008160000151905060005b82602001515181101562000d2a5760008360200151828151811062000b2f5762000b2f620015f5565b602002602001015160200151905060008460200151838151811062000b585762000b58620015f5565b60200260200101516000015190506020826080015163ffffffff16101562000bb15760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d17908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b06565b50505080600101905062000acf565b5060005b815181101562000dff57600082828151811062000d5e5762000d5e620015f5565b6020026020010151600001519050600083838151811062000d835762000d83620015f5565b6020908102919091018101518101516001600160401b03841660008181526008845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d3d565b505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000e3f5762000e3f62000e04565b60405290565b60405161020081016001600160401b038111828210171562000e3f5762000e3f62000e04565b604080519081016001600160401b038111828210171562000e3f5762000e3f62000e04565b60405160c081016001600160401b038111828210171562000e3f5762000e3f62000e04565b604051601f8201601f191681016001600160401b038111828210171562000ee05762000ee062000e04565b604052919050565b80516001600160a01b038116811462000f0057600080fd5b919050565b80516001600160401b038116811462000f0057600080fd5b60006080828403121562000f3057600080fd5b604051608081016001600160401b038111828210171562000f555762000f5562000e04565b60405290508062000f668362000ee8565b815262000f766020840162000ee8565b602082015262000f896040840162000ee8565b604082015262000f9c6060840162000ee8565b60608201525092915050565b60006001600160401b0382111562000fc45762000fc462000e04565b5060051b60200190565b8051801515811462000f0057600080fd5b805161ffff8116811462000f0057600080fd5b805163ffffffff8116811462000f0057600080fd5b600082601f8301126200101957600080fd5b81516020620010326200102c8362000fa8565b62000eb5565b82815261024092830285018201928282019190878511156200105357600080fd5b8387015b85811015620012125780890382811215620010725760008081fd5b6200107c62000e1a565b620010878362000f05565b815261020080601f19840112156200109f5760008081fd5b620010a962000e45565b9250620010b888850162000fce565b83526040620010c981860162000fdf565b898501526060620010dc81870162000ff2565b828601526080620010ef81880162000ff2565b8287015260a091506200110482880162000ff2565b9086015260c06200111787820162000fdf565b8287015260e091506200112c82880162000ff2565b908601526101006200114087820162000fdf565b8287015261012091506200115682880162000fdf565b908601526101406200116a87820162000fdf565b8287015261016091506200118082880162000ff2565b908601526101806200119487820162000ff2565b828701526101a09150620011aa82880162000f05565b908601526101c0620011be87820162000f05565b828701526101e09150620011d482880162000ff2565b90860152620011e586840162000fce565b81860152508389840152620011fe610220860162000ee8565b908301525085525092840192810162001057565b5090979650505050505050565b600082601f8301126200123157600080fd5b81516020620012446200102c8362000fa8565b82815260069290921b840181019181810190868411156200126457600080fd5b8286015b84811015620012ba5760408189031215620012835760008081fd5b6200128d62000e6b565b620012988262000ee8565b8152620012a785830162000f05565b8186015283529183019160400162001268565b509695505050505050565b600082601f830112620012d757600080fd5b81516020620012ea6200102c8362000fa8565b82815260059290921b840181019181810190868411156200130a57600080fd5b8286015b84811015620012ba5780516001600160401b03808211156200132f57600080fd5b908801906040601f19838c0381018213156200134a57600080fd5b6200135462000e6b565b6200136189860162000f05565b815282850151848111156200137557600080fd5b8086019550508c603f8601126200138b57600080fd5b888501519350620013a06200102c8562000fa8565b84815260e09094028501830193898101908e861115620013bf57600080fd5b958401955b858710156200149857868f0360e0811215620013df57600080fd5b620013e962000e6b565b620013f48962000ee8565b815260c086830112156200140757600080fd5b6200141162000e90565b9150620014208d8a0162000ff2565b82526200142f878a0162000ff2565b8d8301526200144160608a0162000fdf565b878301526200145360808a0162000ff2565b60608301526200146660a08a0162000ff2565b60808301526200147960c08a0162000fce565b60a0830152808d0191909152825260e09690960195908a0190620013c4565b828b0152508752505050928401925083016200130e565b60008060008060008587036101a0811215620014ca57600080fd5b60c0811215620014d957600080fd5b50620014e462000e90565b620014ef8762000ee8565b8152620014ff6020880162000f05565b602082015260408701516001600160601b03811681146200151f57600080fd5b6040820152620015326060880162000ee8565b6060820152620015456080880162000ee8565b60808201526200155860a0880162000ee8565b60a082015294506200156e8760c0880162000f1d565b6101408701519094506001600160401b03808211156200158d57600080fd5b6200159b89838a0162001007565b9450610160880151915080821115620015b357600080fd5b620015c189838a016200121f565b9350610180880151915080821115620015d957600080fd5b50620015e888828901620012c5565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c811660408601526200165360608601828560381c1663ffffffff169052565b6200166b60808601828560581c1663ffffffff169052565b6200168160a08601838560781c1661ffff169052565b6200169960c08601828560881c1663ffffffff169052565b620016af60e08601838560a81c1661ffff169052565b620016c66101008601838560b81c1661ffff169052565b620016dd6101208601838560c81c1661ffff169052565b620016f66101408601828560d81c1663ffffffff169052565b600186015463ffffffff8282161661016087015292506001600160401b03602084901c811661018087015291506200173f6101a08601838560601c166001600160401b03169052565b620017586101c08601828560a01c1663ffffffff169052565b506200176f6101e0850160ff8460c01c1615159052565b60028501546001600160a01b0381166102008601529150620017a26102208501828460a01c166001600160401b03169052565b5050600383015461024083015292915050565b81511515815261020081016020830151620017d6602084018261ffff169052565b506040830151620017ef604084018263ffffffff169052565b50606083015162001808606084018263ffffffff169052565b50608083015162001821608084018263ffffffff169052565b5060a08301516200183860a084018261ffff169052565b5060c08301516200185160c084018263ffffffff169052565b5060e08301516200186860e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b03908116918501919091526101a080860151909116908401526101c080850151909116908301526101e0928301511515929091019190915290565b60805160a05160c05160e0516101005161012051615195620019b0600039600081816102da01528181610f260152612adf0152600081816102ab01528181612ab7015261323e01526000818161027c01528181612a8d0152612bf30152600081816102180152818161265001528181612a2801526130f90152600081816101e901528181612a0301528181612eda0152612f8401526000818161024801528181612a5a0152818161304601526130b601526151956000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063a69c64c011610081578063df0aa9e911610066578063df0aa9e9146108c0578063f2fde38b146108d3578063fbca3b74146108e657600080fd5b8063a69c64c01461089a578063a6f3ab6c146108ad57600080fd5b80638da5cb5b116100b25780638da5cb5b146108635780639041be3d14610874578063932e53c81461088757600080fd5b806379ba5097146106f857806382b49eb01461070057600080fd5b80633a019940116101245780636def4ce7116101095780636def4ce7146103b65780637437ff9f14610672578063770e2dc4146106e557600080fd5b80633a0199401461038157806348a98aa41461038b57600080fd5b8063061877e31461015657806306285c69146101a7578063181f5a771461031757806320487ded14610360575b600080fd5b610189610164366004613945565b6001600160a01b031660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61030a6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161019e9190613962565b6103536040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161019e9190613a1e565b61037361036e366004613a6a565b610906565b60405190815260200161019e565b610389610d27565b005b61039e610399366004613aba565b610eeb565b6040516001600160a01b03909116815260200161019e565b6106656103c4366004613af3565b604080516102808101825260006080820181815260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e08301829052610200830182905261022083018290526102408301829052610260830182905282526020820181905291810182905260608101919091525067ffffffffffffffff908116600090815260066020908152604091829020825161028081018452815460ff80821615156080840190815261ffff610100808504821660a087015263ffffffff63010000008604811660c08801526701000000000000008604811660e08801526b01000000000000000000000086048116918701919091526f01000000000000000000000000000000850482166101208701527101000000000000000000000000000000000085048116610140870152750100000000000000000000000000000000000000000085048216610160870152770100000000000000000000000000000000000000000000008504821661018087015279010000000000000000000000000000000000000000000000000085049091166101a08601527b0100000000000000000000000000000000000000000000000000000090930483166101c085015260018501548084166101e0860152640100000000810489166102008601526c010000000000000000000000008104891661022086015274010000000000000000000000000000000000000000808204909416610240860152780100000000000000000000000000000000000000000000000090049091161515610260840152825260028301546001600160a01b0381169483019490945290920490931691810191909152600390910154606082015290565b60405161019e9190613c41565b6106d860408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526002546001600160a01b03908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161019e9190613c8e565b6103896106f3366004613ec1565b610f9a565b610389610fb0565b61080361070e366004613aba565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff9190911660009081526008602090815260408083206001600160a01b0394909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b60405161019e9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b6000546001600160a01b031661039e565b610189610882366004613af3565b611079565b61038961089536600461413b565b6110bd565b6103896108a8366004614348565b6110d1565b6103896108bb366004614406565b6110e2565b6103736108ce36600461448b565b6110f3565b6103896108e1366004613945565b61157b565b6108f96108f4366004613af3565b61158c565b60405161019e91906144f7565b67ffffffffffffffff82166000908152600660205260408120805460ff1661096b576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b600061099961097d6080860186614544565b6001850154640100000000900467ffffffffffffffff166115c0565b90506109ca856109ac6020870187614544565b84519091506109be6040890189614592565b9050856020015161172d565b60006007816109df6080880160608901613945565b6001600160a01b03168152602081019190915260400160009081205467ffffffffffffffff169150819003610a5c57610a1e6080860160608701613945565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b60035460009081906001600160a01b031663ffdb4b37610a8260808a0160608b01613945565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8b1660248201526044016040805180830381865afa158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b119190614608565b90925090506000808080610b2860408c018c614592565b90501115610b6357610b578b610b4460808d0160608e01613945565b87610b5260408f018f614592565b6118a3565b91945092509050610b9a565b6001880154610b979074010000000000000000000000000000000000000000900463ffffffff16662386f26fc10000614661565b92505b875460009077010000000000000000000000000000000000000000000000900461ffff1615610c0657610c038c6dffffffffffffffffffffffffffff607088901c16610be960208f018f614544565b90508e8060400190610bfb9190614592565b905086611c94565b90505b600089600101600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff168463ffffffff168b600001600f9054906101000a900461ffff1661ffff168e8060200190610c599190614544565b610c64929150614661565b8c548c51610c87916b010000000000000000000000900463ffffffff1690614678565b610c919190614678565b610c9b9190614678565b610cb5906dffffffffffffffffffffffffffff8916614661565b610cbf9190614661565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff87168282610cf667ffffffffffffffff8c1689614661565b610d009190614678565b610d0a9190614678565b610d14919061468b565b9a50505050505050505050505b92915050565b600354604080517fcdc73d5100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163cdc73d5191600480830192869291908290030181865afa158015610d89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610db191908101906146c6565b6005549091506001600160a01b031660005b8251811015610ee6576000838281518110610de057610de0614755565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e729190614784565b90508015610edc57610e8e6001600160a01b0383168583611d9a565b816001600160a01b0316846001600160a01b03167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ed391815260200190565b60405180910390a35b5050600101610dc3565b505050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f93919061479d565b9392505050565b610fa2611e1a565b610fac8282611e76565b5050565b6001546001600160a01b0316331461100a5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610962565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120600201549091610d21917401000000000000000000000000000000000000000090041660016147ba565b6110c5611e1a565b6110ce81612256565b50565b6110d9611e1a565b6110ce81612849565b6110ea611e1a565b6110ce81612926565b67ffffffffffffffff841660009081526006602052604081208161111a8288888888612b3f565b905060005b8161014001515181101561151157600061113c6040890189614592565b8381811061114c5761114c614755565b90506040020180360381019061116291906147e2565b905080602001516000036111a2576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111b28a8360000151610eeb565b90506001600160a01b038116158061126857506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611266919061481c565b155b156112ad5781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b6000816001600160a01b0316639a4575b96040518060a001604052808d80600001906112d99190614544565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff8f166020808301919091526001600160a01b03808e16604080850191909152918901516060840152885116608090920191909152517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526113849190600401614839565b6000604051808303816000875af11580156113a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113cb9190810190614906565b9050602081602001515111801561142c575067ffffffffffffffff8b16600090815260086020908152604080832086516001600160a01b0316845282529091205490820151516e01000000000000000000000000000090910463ffffffff16105b156114715782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b805161147c906133f7565b5060408051606081019091526001600160a01b03831660808201528060a0810160405160208183030381529060405281526020018260000151815260200182602001518152506040516020016114d29190614997565b60405160208183030381529060405285610160015185815181106114f8576114f8614755565b602002602001018190525050505080600101905061111f565b50611520818360030154613452565b61018082015260405167ffffffffffffffff8816907fc79f9c3e610deac14de4e704195fe17eab0983ee9916866bc04d16a00f54daa690611562908490614aa2565b60405180910390a261018001519150505b949350505050565b611583611e1a565b6110ce816135ad565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260008082526020820152600083900361160157506040805180820190915267ffffffffffffffff8216815260006020820152610f93565b600061160d8486614bd7565b90507fe7e230f0000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161167a576116658460048188614c1f565b8101906116729190614c49565b915050610f93565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016116fb5760408051808201909152806116db866004818a614c1f565b8101906116e89190614c81565b815260006020909101529150610f939050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8516600090815260066020526040902080546301000000900463ffffffff168511156117a65780546040517f86933789000000000000000000000000000000000000000000000000000000008152630100000090910463ffffffff16600482015260248101869052604401610962565b8054670100000000000000900463ffffffff168411156117f2576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8054610100900461ffff16831115611836576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018101547801000000000000000000000000000000000000000000000000900460ff168015611864575081155b1561189b576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000808083815b81811015611c875760008787838181106118c6576118c6614755565b9050604002018036038101906118dc91906147e2565b905060006001600160a01b03166118f78c8360000151610eeb565b6001600160a01b0316036119455780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b67ffffffffffffffff8b16600090815260086020908152604080832084516001600160a01b03168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052611ab35767ffffffffffffffff8c1660009081526006602052604090208054611a5390790100000000000000000000000000000000000000000000000000900461ffff16662386f26fc10000614661565b611a5d9089614678565b8154909850611a91907b01000000000000000000000000000000000000000000000000000000900463ffffffff1688614c9a565b6001820154909750611aa99063ffffffff1687614c9a565b9550505050611c7f565b604081015160009061ffff1615611bcf5760008c6001600160a01b031684600001516001600160a01b031614611b725760035484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015611b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6b9190614cb7565b9050611b75565b508a5b620186a0836040015161ffff16611bb78660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661366e90919063ffffffff16565b611bc19190614661565b611bcb919061468b565b9150505b6060820151611bde9088614c9a565b9650816080015186611bf09190614c9a565b8251909650600090611c0f9063ffffffff16662386f26fc10000614661565b905080821015611c2e57611c23818a614678565b985050505050611c7f565b6000836020015163ffffffff16662386f26fc10000611c4d9190614661565b905080831115611c6d57611c61818b614678565b99505050505050611c7f565b611c77838b614678565b995050505050505b6001016118aa565b5050955095509592505050565b60008063ffffffff8316611ca9608086614661565b611cb587610220614678565b611cbf9190614678565b611cc99190614678565b67ffffffffffffffff8816600090815260066020526040812080549293509171010000000000000000000000000000000000810463ffffffff1690611d2b907501000000000000000000000000000000000000000000900461ffff1685614661565b611d359190614678565b825490915077010000000000000000000000000000000000000000000000900461ffff16611d736dffffffffffffffffffffffffffff8a1683614661565b611d7d9190614661565b611d8d90655af3107a4000614661565b9998505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610ee69084906136ab565b6000546001600160a01b03163314611e745760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610962565b565b60005b825181101561217f576000838281518110611e9657611e96614755565b6020026020010151905060008160000151905060005b82602001515181101561217157600083602001518281518110611ed157611ed1614755565b6020026020010151602001519050600084602001518381518110611ef757611ef7614755565b60200260200101516000015190506020826080015163ffffffff161015611f675760808201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015263ffffffff9091166024820152604401610962565b67ffffffffffffffff841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59061215f908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101611eac565b505050806001019050611e79565b5060005b8151811015610ee65760008282815181106121a0576121a0614755565b602002602001015160000151905060008383815181106121c2576121c2614755565b60209081029190910181015181015167ffffffffffffffff841660008181526008845260408082206001600160a01b038516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612183565b60005b8151811015610fac57600082828151811061227657612276614755565b60200260200101519050600083838151811061229457612294614755565b60200260200101516000015190508067ffffffffffffffff16600014806122cc57506020820151610180015167ffffffffffffffff16155b1561230f576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610962565b6000600660008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff02191690831515021790555090505082600301546000801b0361273957604080517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b038216156126f2576002830180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555b8367ffffffffffffffff167f4be92415590c4554edbd7d3fbf308eeb6e5d00ababade0791f835b4a18416ed68460405161272c9190614cd2565b60405180910390a2612839565b60028301546001600160a01b0383811691161461278e576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610962565b60208560200151610160015163ffffffff1610156127f257602085015161016001516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610962565b8367ffffffffffffffff167f1173725509a61aed633c58cd12e31c104cd26ca24f6c270c8ac81c5f6f12e8e986602001516040516128309190614e73565b60405180910390a25b5050505050806001019050612259565b60005b8151811015610fac57600082828151811061286957612869614755565b6020026020010151600001519050600083838151811061288b5761288b614755565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161284c565b60208101516001600160a01b0316158061294b575060608101516001600160a01b0316155b15612982576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556020808401516003805484169185169190911790556040808501516004805485169186169190911790556060808601516005805490951690861617909355805160c0810182527f0000000000000000000000000000000000000000000000000000000000000000851681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16928101929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16828201527f00000000000000000000000000000000000000000000000000000000000000008416928201929092527f0000000000000000000000000000000000000000000000000000000000000000831660808201527f000000000000000000000000000000000000000000000000000000000000000090921660a0830152517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa91612b34918490614e82565b60405180910390a150565b604080516101a08101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820181905261014082018190526101608201526101808101919091526040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608086901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c66919061481c565b15612ca9576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610962565b6001600160a01b038216612ce9576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546001600160a01b03163314612d2d576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460ff16612d74576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610962565b6000612da2612d866080870187614544565b60018a0154640100000000900467ffffffffffffffff166115c0565b90506000612db36040870187614592565b9150612dda905087612dc86020890189614544565b9050846000015184866020015161172d565b8015612ece576004546001600160a01b03168015612ecc576040517fe0a0e5060000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063e0a0e50690612e39908b908b90600401614fe4565b600060405180830381600087803b158015612e5357600080fd5b505af1925050508015612e64575060015b612ecc573d808015612e92576040519150601f19603f3d011682016040523d82523d6000602084013e612e97565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016109629190613a1e565b505b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612f0a6080890160608a01613945565b6001600160a01b031603612f1f575084612ff2565b6003546001600160a01b03166241e5be612f3f60808a0160608b01613945565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039182166004820152602481018a90527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015612fcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fef9190614784565b90505b6130026080880160608901613945565b6001600160a01b03167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8260405161303c91815260200190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff168111156130e3576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018290526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610962565b604080516101a08101825267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526001600160a01b038716602082015290810161317461313a8a80614544565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133f792505050565b6001600160a01b031681526020018a600201601481819054906101000a900467ffffffffffffffff166131a690615102565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020018460000151815260200160001515815260200184602001516132b0576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526001600160a01b0388811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015613287573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ab9190615129565b6132b3565b60005b67ffffffffffffffff1681526020016132d260808a0160608b01613945565b6001600160a01b031681526020018781526020018880602001906132f69190614544565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161333d60408a018a614592565b808060200260200160405190810160405280939291908181526020016000905b828210156133895761337a604083028601368190038101906147e2565b8152602001906001019061335d565b505050505081526020018367ffffffffffffffff8111156133ac576133ac613cca565b6040519080825280602002602001820160405280156133df57816020015b60608152602001906001900390816133ca5790505b50815260006020909101529998505050505050505050565b6000815160201461343657816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109629190613a1e565b610d218280602001905181019061344d9190614784565b613790565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016134e89897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016135219190615146565b6040516020818303038152906040528051906020012087610160015160405160200161354d9190615159565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b336001600160a01b038216036136055760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610962565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a76400006136a1837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616614661565b610f93919061468b565b6000613700826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137fd9092919063ffffffff16565b805190915015610ee6578080602001905181019061371e919061481c565b610ee65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610962565b60006001600160a01b038211806137a8575061040082105b156137f95760408051602081018490520160408051601f19818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261096291600401613a1e565b5090565b6060611573848460008585600080866001600160a01b03168587604051613824919061516c565b60006040518083038185875af1925050503d8060008114613861576040519150601f19603f3d011682016040523d82523d6000602084013e613866565b606091505b509150915061387787838387613882565b979650505050505050565b606083156138f15782516000036138ea576001600160a01b0385163b6138ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610962565b5081611573565b61157383838151156139065781518083602001fd5b8060405162461bcd60e51b81526004016109629190613a1e565b6001600160a01b03811681146110ce57600080fd5b803561394081613920565b919050565b60006020828403121561395757600080fd5b8135610f9381613920565b60c08101610d2182846001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60005b838110156139e95781810151838201526020016139d1565b50506000910152565b60008151808452613a0a8160208601602086016139ce565b601f01601f19169290920160200192915050565b602081526000610f9360208301846139f2565b67ffffffffffffffff811681146110ce57600080fd5b803561394081613a31565b600060a08284031215613a6457600080fd5b50919050565b60008060408385031215613a7d57600080fd5b8235613a8881613a31565b9150602083013567ffffffffffffffff811115613aa457600080fd5b613ab085828601613a52565b9150509250929050565b60008060408385031215613acd57600080fd5b8235613ad881613a31565b91506020830135613ae881613920565b809150509250929050565b600060208284031215613b0557600080fd5b8135610f9381613a31565b8051151582526020810151613b2b602084018261ffff169052565b506040810151613b43604084018263ffffffff169052565b506060810151613b5b606084018263ffffffff169052565b506080810151613b73608084018263ffffffff169052565b5060a0810151613b8960a084018261ffff169052565b5060c0810151613ba160c084018263ffffffff169052565b5060e0810151613bb760e084018261ffff169052565b506101008181015161ffff9081169184019190915261012080830151909116908301526101408082015163ffffffff90811691840191909152610160808301518216908401526101808083015167ffffffffffffffff908116918501919091526101a080840151909116908401526101c080830151909116908301526101e0908101511515910152565b600061026082019050613c55828451613b10565b60208301516001600160a01b0316610200830152604083015167ffffffffffffffff166102208301526060909201516102409091015290565b60808101610d21828480516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b60405290565b60405160c0810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b6040516060810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b604051610200810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b604051601f8201601f1916810167ffffffffffffffff81118282101715613db557613db5613cca565b604052919050565b600067ffffffffffffffff821115613dd757613dd7613cca565b5060051b60200190565b803563ffffffff8116811461394057600080fd5b803561ffff8116811461394057600080fd5b80151581146110ce57600080fd5b803561394081613e07565b600082601f830112613e3157600080fd5b81356020613e46613e4183613dbd565b613d8c565b82815260069290921b84018101918181019086841115613e6557600080fd5b8286015b84811015613eb65760408189031215613e825760008081fd5b613e8a613cf9565b8135613e9581613a31565b815281850135613ea481613920565b81860152835291830191604001613e69565b509695505050505050565b60008060408385031215613ed457600080fd5b67ffffffffffffffff83351115613eea57600080fd5b83601f843585010112613efc57600080fd5b613f0c613e418435850135613dbd565b8335840180358083526020808401939260059290921b90910101861015613f3257600080fd5b602085358601015b85358601803560051b016020018110156141055767ffffffffffffffff81351115613f6457600080fd5b6040601f19823588358901018903011215613f7e57600080fd5b613f86613cf9565b613f996020833589358a01010135613a31565b863587018235016020810135825267ffffffffffffffff6040909101351115613fc157600080fd5b86358701823501604081013501603f81018913613fdd57600080fd5b613fed613e416020830135613dbd565b602082810135808352908201919060e00283016040018b101561400f57600080fd5b604083015b604060e06020860135028501018110156140ec5760e0818d03121561403857600080fd5b614040613cf9565b61404a8235613920565b8135815260c0601f19838f0301121561406257600080fd5b61406a613d22565b61407660208401613de1565b815261408460408401613de1565b602082015261409560608401613df5565b60408201526140a660808401613de1565b60608201526140b760a08401613de1565b60808201526140c960c0840135613e07565b60c083013560a0820152602082810191909152908452929092019160e001614014565b5060208481019190915292865250509283019201613f3a565b5092505067ffffffffffffffff6020840135111561412257600080fd5b6141328460208501358501613e20565b90509250929050565b6000602080838503121561414e57600080fd5b823567ffffffffffffffff81111561416557600080fd5b8301601f8101851361417657600080fd5b8035614184613e4182613dbd565b81815261024091820283018401918482019190888411156141a457600080fd5b938501935b8385101561433c57848903818112156141c25760008081fd5b6141ca613d45565b86356141d581613a31565b8152610200601f1983018113156141ec5760008081fd5b6141f4613d68565b9250614201898901613e15565b83526040614210818a01613df5565b8a8501526060614221818b01613de1565b828601526080614232818c01613de1565b8287015260a09150614245828c01613de1565b9086015260c06142568b8201613df5565b8287015260e09150614269828c01613de1565b9086015261010061427b8b8201613df5565b82870152610120915061428f828c01613df5565b908601526101406142a18b8201613df5565b8287015261016091506142b5828c01613de1565b908601526101806142c78b8201613de1565b828701526101a091506142db828c01613a47565b908601526101c06142ed8b8201613a47565b828701526101e09150614301828c01613de1565b908601526143108a8401613e15565b8186015250838a8401526143276102208a01613935565b908301525084525093840193918501916141a9565b50979650505050505050565b6000602080838503121561435b57600080fd5b823567ffffffffffffffff81111561437257600080fd5b8301601f8101851361438357600080fd5b8035614391613e4182613dbd565b81815260069190911b820183019083810190878311156143b057600080fd5b928401925b8284101561387757604084890312156143ce5760008081fd5b6143d6613cf9565b84356143e181613920565b8152848601356143f081613a31565b81870152825260409390930192908401906143b5565b60006080828403121561441857600080fd5b6040516080810181811067ffffffffffffffff8211171561443b5761443b613cca565b604052823561444981613920565b8152602083013561445981613920565b6020820152604083013561446c81613920565b6040820152606083013561447f81613920565b60608201529392505050565b600080600080608085870312156144a157600080fd5b84356144ac81613a31565b9350602085013567ffffffffffffffff8111156144c857600080fd5b6144d487828801613a52565b9350506040850135915060608501356144ec81613920565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b818110156145385783516001600160a01b031683529284019291840191600101614513565b50909695505050505050565b6000808335601e1984360301811261455b57600080fd5b83018035915067ffffffffffffffff82111561457657600080fd5b60200191503681900382131561458b57600080fd5b9250929050565b6000808335601e198436030181126145a957600080fd5b83018035915067ffffffffffffffff8211156145c457600080fd5b6020019150600681901b360382131561458b57600080fd5b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461394057600080fd5b6000806040838503121561461b57600080fd5b614624836145dc565b9150614132602084016145dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610d2157610d21614632565b80820180821115610d2157610d21614632565b6000826146c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208083850312156146d957600080fd5b825167ffffffffffffffff8111156146f057600080fd5b8301601f8101851361470157600080fd5b805161470f613e4182613dbd565b81815260059190911b8201830190838101908783111561472e57600080fd5b928401925b8284101561387757835161474681613920565b82529284019290840190614733565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561479657600080fd5b5051919050565b6000602082840312156147af57600080fd5b8151610f9381613920565b67ffffffffffffffff8181168382160190808211156147db576147db614632565b5092915050565b6000604082840312156147f457600080fd5b6147fc613cf9565b823561480781613920565b81526020928301359281019290925250919050565b60006020828403121561482e57600080fd5b8151610f9381613e07565b602081526000825160a0602084015261485560c08401826139f2565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f8301126148b357600080fd5b815167ffffffffffffffff8111156148cd576148cd613cca565b6148e06020601f19601f84011601613d8c565b8181528460208386010111156148f557600080fd5b6115738260208301602087016139ce565b60006020828403121561491857600080fd5b815167ffffffffffffffff8082111561493057600080fd5b908301906040828603121561494457600080fd5b61494c613cf9565b82518281111561495b57600080fd5b614967878286016148a2565b82525060208301518281111561497c57600080fd5b614988878286016148a2565b60208301525095945050505050565b6020815260008251606060208401526149b360808401826139f2565b90506020840151601f19808584030160408601526149d183836139f2565b92506040860151915080858403016060860152506149ef82826139f2565b95945050505050565b60008151808452602080850194506020840160005b83811015614a3d57815180516001600160a01b031688528301518388015260409096019590820190600101614a0d565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015614a9557601f19868403018952614a838383516139f2565b98840198925090830190600101614a67565b5090979650505050505050565b60208152614abd60208201835167ffffffffffffffff169052565b60006020830151614ad960408401826001600160a01b03169052565b5060408301516001600160a01b038116606084015250606083015167ffffffffffffffff8116608084015250608083015160a083015260a0830151614b2260c084018215159052565b5060c083015167ffffffffffffffff811660e08401525060e0830151610100614b55818501836001600160a01b03169052565b840151610120848101919091528401516101a061014080860182905291925090614b836101c08601846139f2565b9250808601519050601f19610160818786030181880152614ba485846149f8565b945080880151925050610180818786030181880152614bc38584614a48565b970151959092019490945250929392505050565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614c175780818660040360031b1b83161692505b505092915050565b60008085851115614c2f57600080fd5b83861115614c3c57600080fd5b5050820193919092039150565b600060408284031215614c5b57600080fd5b614c63613cf9565b823581526020830135614c7581613e07565b60208201529392505050565b600060208284031215614c9357600080fd5b5035919050565b63ffffffff8181168382160190808211156147db576147db614632565b600060208284031215614cc957600080fd5b610f93826145dc565b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c81166040860152614d1960608601828560381c1663ffffffff169052565b614d3060808601828560581c1663ffffffff169052565b614d4560a08601838560781c1661ffff169052565b614d5c60c08601828560881c1663ffffffff169052565b614d7160e08601838560a81c1661ffff169052565b614d876101008601838560b81c1661ffff169052565b614d9d6101208601838560c81c1661ffff169052565b614db56101408601828560d81c1663ffffffff169052565b600186015463ffffffff82821616610160870152925067ffffffffffffffff602084901c81166101808701529150614dff6101a08601838560601c1667ffffffffffffffff169052565b614e176101c08601828560a01c1663ffffffff169052565b50614e2d6101e0850160ff8460c01c1615159052565b60028501546001600160a01b0381166102008601529150614e606102208501828460a01c1667ffffffffffffffff169052565b5050600383015461024083015292915050565b6102008101610d218284613b10565b6101408101614eef82856001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b82516001600160a01b0390811660c08401526020840151811660e084015260408401518116610100840152606084015116610120830152610f93565b6000808335601e19843603018112614f4257600080fd5b830160208101925035905067ffffffffffffffff811115614f6257600080fd5b80360382131561458b57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8183526000602080850194508260005b85811015614a3d578135614fbf81613920565b6001600160a01b03168752818301358388015260409687019690910190600101614fac565b600067ffffffffffffffff8085168352604060208401526150058485614f2b565b60a0604086015261501a60e086018284614f71565b91505061502a6020860186614f2b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152615060848385614f71565b935060408801359250601e1988360301831261507b57600080fd5b6020928801928301923591508482111561509457600080fd5b8160061b36038313156150a657600080fd5b808785030160808801526150bb848385614f9c565b94506150c960608901613935565b6001600160a01b03811660a089015293506150e76080890189614f2b565b94509250808786030160c08801525050613877838383614f71565b600067ffffffffffffffff80831681810361511f5761511f614632565b6001019392505050565b60006020828403121561513b57600080fd5b8151610f9381613a31565b602081526000610f9360208301846149f8565b602081526000610f936020830184614a48565b6000825161517e8184602087016139ce565b919091019291505056fea164736f6c6343000818000a", } var EVM2EVMMultiOnRampABI = EVM2EVMMultiOnRampMetaData.ABI @@ -1960,12 +1960,12 @@ func (it *EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator) Close() error } type EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted struct { - DestChainSelector *big.Int + DestChainSelector uint64 Token common.Address Raw types.Log } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []*big.Int, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { @@ -1983,7 +1983,7 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterTokenTransferFeeCon return &EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "TokenTransferFeeConfigDeleted", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, destChainSelector []*big.Int, token []common.Address) (event.Subscription, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { @@ -2245,7 +2245,7 @@ func (EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated) Topic() common.Hash { } func (EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted) Topic() common.Hash { - return common.HexToHash("0xfa22e84f9c809b5b7e94f084eb45cf17a5e4703cecef8f27ed35e54b719bffcd") + return common.HexToHash("0x4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b") } func (EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated) Topic() common.Hash { @@ -2355,9 +2355,9 @@ type EVM2EVMMultiOnRampInterface interface { ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated, error) - FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []*big.Int, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator, error) + FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator, error) - WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, destChainSelector []*big.Int, token []common.Address) (event.Subscription, error) + WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) ParseTokenTransferFeeConfigDeleted(log types.Log) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, error) diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index d777771ff1..f41fb552d4 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -33,25 +33,27 @@ type ClientEVMTokenAmount struct { Amount *big.Int } -type InternalEVM2EVMMessage struct { +type InternalAny2EVMRampMessage struct { + Header InternalRampMessageHeader + Sender []byte + Data []byte + Receiver common.Address + GasLimit *big.Int + TokenAmounts []ClientEVMTokenAmount + SourceTokenData [][]byte +} + +type InternalRampMessageHeader struct { + MessageId [32]byte SourceChainSelector uint64 - Sender common.Address - Receiver common.Address + DestChainSelector uint64 SequenceNumber uint64 - GasLimit *big.Int - Strict bool Nonce uint64 - FeeToken common.Address - FeeTokenAmount *big.Int - Data []byte - TokenAmounts []ClientEVMTokenAmount - SourceTokenData [][]byte - MessageId [32]byte } var MessageHasherMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"msg\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610771806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c9f1502914610030575b600080fd5b61004361003e3660046104d2565b610055565b60405190815260200160405180910390f35b60006100618383610068565b9392505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b610100015160405160200161010b98979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016101449190610631565b604051602081830303815290604052805190602001208761016001516040516020016101709190610696565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610240576102406101ee565b60405290565b6040516101a0810167ffffffffffffffff81118282101715610240576102406101ee565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156102b1576102b16101ee565b604052919050565b803567ffffffffffffffff811681146102d157600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146102d157600080fd5b803580151581146102d157600080fd5b600082601f83011261031b57600080fd5b813567ffffffffffffffff811115610335576103356101ee565b61036660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161026a565b81815284602083860101111561037b57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff8211156103b2576103b26101ee565b5060051b60200190565b600082601f8301126103cd57600080fd5b813560206103e26103dd83610398565b61026a565b82815260069290921b8401810191818101908684111561040157600080fd5b8286015b84811015610447576040818903121561041e5760008081fd5b61042661021d565b61042f826102d6565b81528185013585820152835291830191604001610405565b509695505050505050565b600082601f83011261046357600080fd5b813560206104736103dd83610398565b82815260059290921b8401810191818101908684111561049257600080fd5b8286015b8481101561044757803567ffffffffffffffff8111156104b65760008081fd5b6104c48986838b010161030a565b845250918301918301610496565b600080604083850312156104e557600080fd5b823567ffffffffffffffff808211156104fd57600080fd5b908401906101a0828703121561051257600080fd5b61051a610246565b610523836102b9565b8152610531602084016102d6565b6020820152610542604084016102d6565b6040820152610553606084016102b9565b60608201526080830135608082015261056e60a084016102fa565b60a082015261057f60c084016102b9565b60c082015261059060e084016102d6565b60e0820152610100838101359082015261012080840135838111156105b457600080fd5b6105c08982870161030a565b82840152505061014080840135838111156105da57600080fd5b6105e6898287016103bc565b828401525050610160808401358381111561060057600080fd5b61060c89828701610452565b9183019190915250610180928301359281019290925250946020939093013593505050565b602080825282518282018190526000919060409081850190868401855b82811015610689578151805173ffffffffffffffffffffffffffffffffffffffff16855286015186850152928401929085019060010161064e565b5091979650505050505050565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b83811015610756577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089870301855282518051808852835b81811015610711578281018a01518982018b015289016106f6565b508781018901849052601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169096018701955093860193918601916001016106be565b50939897505050505050505056fea164736f6c6343000818000a", + ABI: "[{\"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\"},{\"internalType\":\"bytes32\",\"name\":\"sourceTokenDataHash\",\"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\":[{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"name\":\"encodeSourceTokenDataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"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\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"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: "0x608060405234801561001057600080fd5b50610bb8806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063bf0619ad11610050578063bf0619ad146100d0578063c2cfa165146100e3578063cd34ba82146100f657600080fd5b80633b61b52e14610077578063a1e747df1461009d578063a91d3aeb146100bd575b600080fd5b61008a6100853660046106e3565b610109565b6040519081526020015b60405180910390f35b6100b06100ab366004610812565b61011c565b60405161009491906108de565b6100b06100cb3660046108f1565b61014e565b6100b06100de366004610972565b610186565b6100b06100f13660046109b5565b6101bd565b6100b06101043660046109f2565b6101e6565b600061011583836101f9565b9392505050565b6060848484846040516020016101359493929190610a27565b6040516020818303038152906040529050949350505050565b606086868686868660405160200161016b96959493929190610a64565b60405160208183030381529060405290509695505050505050565b604080516020810188905290810186905260608181018690526080820185905260a0820184905260c082018390529060e00161016b565b6060816040516020016101d09190610ac4565b6040516020818303038152906040529050919050565b6060816040516020016101d09190610b46565b81516020808201516040928301519251600093849361023f937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610a27565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976102a69794969395929491939101610a64565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016102dd9190610b46565b604051602081830303815290604052805190602001208760c001516040516020016103089190610ac4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156103d8576103d8610386565b60405290565b60405160e0810167ffffffffffffffff811182821017156103d8576103d8610386565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561044857610448610386565b604052919050565b803567ffffffffffffffff8116811461046857600080fd5b919050565b600060a0828403121561047f57600080fd5b60405160a0810181811067ffffffffffffffff821117156104a2576104a2610386565b604052823581529050806104b860208401610450565b60208201526104c960408401610450565b60408201526104da60608401610450565b60608201526104eb60808401610450565b60808201525092915050565b600082601f83011261050857600080fd5b813567ffffffffffffffff81111561052257610522610386565b61055360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610401565b81815284602083860101111561056857600080fd5b816020850160208301376000918101602001919091529392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461046857600080fd5b600067ffffffffffffffff8211156105c3576105c3610386565b5060051b60200190565b600082601f8301126105de57600080fd5b813560206105f36105ee836105a9565b610401565b82815260069290921b8401810191818101908684111561061257600080fd5b8286015b84811015610658576040818903121561062f5760008081fd5b6106376103b5565b61064082610585565b81528185013585820152835291830191604001610616565b509695505050505050565b600082601f83011261067457600080fd5b813560206106846105ee836105a9565b82815260059290921b840181019181810190868411156106a357600080fd5b8286015b8481101561065857803567ffffffffffffffff8111156106c75760008081fd5b6106d58986838b01016104f7565b8452509183019183016106a7565b600080604083850312156106f657600080fd5b823567ffffffffffffffff8082111561070e57600080fd5b90840190610160828703121561072357600080fd5b61072b6103de565b610735878461046d565b815260a08301358281111561074957600080fd5b610755888286016104f7565b60208301525060c08301358281111561076d57600080fd5b610779888286016104f7565b60408301525061078b60e08401610585565b60608201526101008301356080820152610120830135828111156107ae57600080fd5b6107ba888286016105cd565b60a083015250610140830135828111156107d357600080fd5b6107df88828601610663565b60c083015250935060208501359150808211156107fb57600080fd5b50610808858286016104f7565b9150509250929050565b6000806000806080858703121561082857600080fd5b8435935061083860208601610450565b925061084660408601610450565b9150606085013567ffffffffffffffff81111561086257600080fd5b61086e878288016104f7565b91505092959194509250565b6000815180845260005b818110156108a057602081850181015186830182015201610884565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610115602083018461087a565b60008060008060008060c0878903121561090a57600080fd5b86359550602087013567ffffffffffffffff81111561092857600080fd5b61093489828a016104f7565b95505061094360408801610585565b935061095160608801610450565b92506080870135915061096660a08801610450565b90509295509295509295565b60008060008060008060c0878903121561098b57600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b6000602082840312156109c757600080fd5b813567ffffffffffffffff8111156109de57600080fd5b6109ea84828501610663565b949350505050565b600060208284031215610a0457600080fd5b813567ffffffffffffffff811115610a1b57600080fd5b6109ea848285016105cd565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610a5a608083018461087a565b9695505050505050565b86815260c060208201526000610a7d60c083018861087a565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015610b39577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452610b2785835161087a565b94509285019290850190600101610aed565b5092979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015610b9e578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101610b63565b509197965050505050505056fea164736f6c6343000818000a", } var MessageHasherABI = MessageHasherMetaData.ABI @@ -190,9 +192,119 @@ func (_MessageHasher *MessageHasherTransactorRaw) Transact(opts *bind.TransactOp return _MessageHasher.Contract.contract.Transact(opts, method, params...) } -func (_MessageHasher *MessageHasherCaller) Hash(opts *bind.CallOpts, msg InternalEVM2EVMMessage, metadataHash [32]byte) ([32]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeFinalHashPreimage", leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash) +} + +func (_MessageHasher *MessageHasherCaller) EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeFixedSizeFieldsHashPreimage", messageId, sender, receiver, sequenceNumber, gasLimit, nonce) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeFixedSizeFieldsHashPreimage(messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { + return _MessageHasher.Contract.EncodeFixedSizeFieldsHashPreimage(&_MessageHasher.CallOpts, messageId, sender, receiver, sequenceNumber, gasLimit, nonce) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeFixedSizeFieldsHashPreimage(messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { + return _MessageHasher.Contract.EncodeFixedSizeFieldsHashPreimage(&_MessageHasher.CallOpts, messageId, sender, receiver, sequenceNumber, gasLimit, nonce) +} + +func (_MessageHasher *MessageHasherCaller) EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "hash", msg, metadataHash) + err := _MessageHasher.contract.Call(opts, &out, "encodeMetadataHashPreimage", any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeMetadataHashPreimage(any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeMetadataHashPreimage(any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) +} + +func (_MessageHasher *MessageHasherCaller) EncodeSourceTokenDataHashPreimage(opts *bind.CallOpts, sourceTokenData [][]byte) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeSourceTokenDataHashPreimage", sourceTokenData) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeSourceTokenDataHashPreimage(sourceTokenData [][]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeSourceTokenDataHashPreimage(&_MessageHasher.CallOpts, sourceTokenData) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeSourceTokenDataHashPreimage(sourceTokenData [][]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeSourceTokenDataHashPreimage(&_MessageHasher.CallOpts, sourceTokenData) +} + +func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmounts []ClientEVMTokenAmount) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeTokenAmountsHashPreimage", tokenAmounts) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeTokenAmountsHashPreimage(tokenAmounts []ClientEVMTokenAmount) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmounts) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeTokenAmountsHashPreimage(tokenAmounts []ClientEVMTokenAmount) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmounts) +} + +func (_MessageHasher *MessageHasherCaller) Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "hash", message, onRamp) if err != nil { return *new([32]byte), err @@ -204,12 +316,12 @@ func (_MessageHasher *MessageHasherCaller) Hash(opts *bind.CallOpts, msg Interna } -func (_MessageHasher *MessageHasherSession) Hash(msg InternalEVM2EVMMessage, metadataHash [32]byte) ([32]byte, error) { - return _MessageHasher.Contract.Hash(&_MessageHasher.CallOpts, msg, metadataHash) +func (_MessageHasher *MessageHasherSession) Hash(message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) { + return _MessageHasher.Contract.Hash(&_MessageHasher.CallOpts, message, onRamp) } -func (_MessageHasher *MessageHasherCallerSession) Hash(msg InternalEVM2EVMMessage, metadataHash [32]byte) ([32]byte, error) { - return _MessageHasher.Contract.Hash(&_MessageHasher.CallOpts, msg, metadataHash) +func (_MessageHasher *MessageHasherCallerSession) Hash(message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) { + return _MessageHasher.Contract.Hash(&_MessageHasher.CallOpts, message, onRamp) } func (_MessageHasher *MessageHasher) Address() common.Address { @@ -217,7 +329,17 @@ func (_MessageHasher *MessageHasher) Address() common.Address { } type MessageHasherInterface interface { - Hash(opts *bind.CallOpts, msg InternalEVM2EVMMessage, metadataHash [32]byte) ([32]byte, error) + EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) + + EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) + + EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) + + EncodeSourceTokenDataHashPreimage(opts *bind.CallOpts, sourceTokenData [][]byte) ([]byte, error) + + EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmounts []ClientEVMTokenAmount) ([]byte, error) + + Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, 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 d2d6fbcc2a..02a4b18652 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 @@ -9,14 +9,14 @@ ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../ commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin ddc26c10c2a52b59624faae9005827b09b98db4566887a736005e8cc37cf8a51 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 035e69cf7dc9682f720022e2c7a89566a849163bf8a043e3e0aea2b19cce4aa7 -evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin f62d32fffd8f9f1e6e48a6e146c29415d67b081d31b9667f701b088c558f3bcf +evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 09ac589a267ac59ae3fef7534bebe6da38c427c48b60b5304b9e55408e028337 +evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 8edc6f93d7d5f045776cd843c0fae8b94a73835d2c939b2f94fa906ca5f26b97 evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b6132cb22370d62b1b20174bbe832ec87df61f6ab65f7fe2515733bdd10a30f5 evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 383e9930fbc1b7fbb6554cc8857229d207fd6742e87c7fb1a37002347e8de8e2 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin c65c226e1e4d38414bd4a1b76fc8aca3cb3dd98df61268424c44564f455d3752 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin 8b929fab79d1caeea4c57e08cc523eb8ab45ec5c08f46da866b82c15ba94d9ad 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 595d2e1c5172dd1838c9f56c1da09c9243975b2be98c9174c1fcab6802585e20 +message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin b16f2182c6f262f4864315c90d35efc0342f5ee3580896e9bca50a5b98d51282 mock_arm_contract: ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.abi ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.bin e7a3a6c3eda5fb882e16bcc2b4340f78523acb67907bcdcaf3c8ffc51488688e mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin e0cf17a38b438239fc6294ddca88f86b6c39e4542aefd9815b2d92987191b8bd mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin 33bdad70822e889de7c720ed20085cf9cd3f8eba8b68f26bd6535197749595fe diff --git a/core/services/ocr3/plugins/ccipevm/msghasher.go b/core/services/ocr3/plugins/ccipevm/msghasher.go index 0b68ba4675..948775a7be 100644 --- a/core/services/ocr3/plugins/ccipevm/msghasher.go +++ b/core/services/ocr3/plugins/ccipevm/msghasher.go @@ -2,107 +2,132 @@ package ccipevm import ( "context" + "encoding/hex" "fmt" - "math/big" "strings" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "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/evm_2_evm_multi_onramp" + "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) ) // MessageHasherV1 implements the MessageHasher interface. // Compatible with: // - "EVM2EVMMultiOnRamp 1.6.0-dev" type MessageHasherV1 struct { - metaDataHash [32]byte - leafDomainSeparator [32]byte - - // ABIs and types for encoding the message data similar to on-chain implementation: - // https://github.com/smartcontractkit/ccip/blob/54ee4f13143d3e414627b6a0b9f71d5dfade76c5/contracts/src/v0.8/ccip/libraries/Internal.sol#L135 - bytesArrayType abi.Type - tokensAbi abi.ABI - fixedSizeValuesAbi abi.ABI - packedValuesAbi abi.ABI + // TODO: move these to CCIPMsg instead? + destChainSelector cciptypes.ChainSelector + onrampAddress []byte } -func NewMessageHasherV1(metaDataHash [32]byte) *MessageHasherV1 { - bytesArray, err := abi.NewType("bytes[]", "bytes[]", nil) - if err != nil { - panic(fmt.Sprintf("failed to create bytes[] type: %v", err)) - } - +func NewMessageHasherV1( + onrampAddress []byte, + destChainSelector cciptypes.ChainSelector, +) *MessageHasherV1 { return &MessageHasherV1{ - metaDataHash: metaDataHash, - leafDomainSeparator: [32]byte{}, - - bytesArrayType: bytesArray, - tokensAbi: mustParseInputsAbi(`[{"components": [{"name":"token","type":"address"}, - {"name":"amount","type":"uint256"}], "type":"tuple[]"}]`), - fixedSizeValuesAbi: mustParseInputsAbi(`[{"name": "sender", "type":"address"}, - {"name": "receiver", "type":"address"}, - {"name": "sequenceNumber", "type":"uint64"}, - {"name": "gasLimit", "type":"uint256"}, - {"name": "strict", "type":"bool"}, - {"name": "nonce", "type":"uint64"}, - {"name": "feeToken","type": "address"}, - {"name": "feeTokenAmount","type": "uint256"}]`), - packedValuesAbi: mustParseInputsAbi(`[{"name": "leafDomainSeparator","type":"bytes32"}, - {"name": "metadataHash", "type":"bytes32"}, - {"name": "fixedSizeValuesHash", "type":"bytes32"}, - {"name": "dataHash", "type":"bytes32"}, - {"name": "tokenAmountsHash", "type":"bytes32"}, - {"name": "sourceTokenDataHash", "type":"bytes32"}]`), + destChainSelector: destChainSelector, + onrampAddress: onrampAddress, } } +// 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(encodedTokenAmounts), + keccak256(encodedSourceTokenData), + ) +*/ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.CCIPMsg) (cciptypes.Bytes32, error) { - type tokenAmount struct { - Token common.Address - Amount *big.Int - } - tokenAmounts := make([]tokenAmount, len(msg.TokenAmounts)) + tokenAmounts := make([]evm_2_evm_multi_onramp.ClientEVMTokenAmount, len(msg.TokenAmounts)) for i, ta := range msg.TokenAmounts { - tokenAmounts[i] = tokenAmount{ + tokenAmounts[i] = evm_2_evm_multi_onramp.ClientEVMTokenAmount{ Token: common.HexToAddress(string(ta.Token)), Amount: ta.Amount, } } - encodedTokens, err := h.abiEncode(h.tokensAbi, tokenAmounts) + encodedTokens, err := h.abiEncode("encodeTokenAmountsHashPreimage", tokenAmounts) if err != nil { return [32]byte{}, fmt.Errorf("abi encode token amounts: %w", err) } - encodedSourceTokenData, err := abi.Arguments{abi.Argument{Type: h.bytesArrayType}}. - PackValues([]interface{}{msg.SourceTokenData}) + encodedSourceTokenData, err := h.abiEncode("encodeSourceTokenDataHashPreimage", msg.SourceTokenData) if err != nil { return [32]byte{}, fmt.Errorf("pack source token data: %w", err) } - packedFixedSizeValues, err := h.abiEncode( - h.fixedSizeValuesAbi, - common.HexToAddress(string(msg.Sender)), + metaDataHashInput, err := h.abiEncode( + "encodeMetadataHashPreimage", + ANY_2_EVM_MESSAGE_HASH, + uint64(msg.SourceChain), + uint64(h.destChainSelector), + h.onrampAddress, + ) + if err != nil { + return [32]byte{}, fmt.Errorf("abi encode metadata hash input: %w", err) + } + + var msgID [32]byte + decoded, err := hex.DecodeString(msg.ID) + if err != nil { + return [32]byte{}, fmt.Errorf("decode message ID: %w", err) + } + if len(decoded) != 32 { + return [32]byte{}, fmt.Errorf("message ID must be 32 bytes") + } + copy(msgID[:], decoded) + + // NOTE: msg.Sender is not necessarily an EVM address since this is Any2EVM. + // Accordingly, sender is defined as "bytes" in the onchain message definition + // rather than "address". + // However, its not clear how best to translate from Sender being a string representation + // to bytes. For now, we assume that the string is hex encoded, but ideally Sender would + // just be a byte array in the CCIPMsg struct that represents a sender encoded in the + // source chain family encoding scheme. + decodedSender, err := hex.DecodeString( + strings.TrimPrefix(string(msg.Sender), "0x"), + ) + if err != nil { + return [32]byte{}, fmt.Errorf("decode sender '%s': %w", msg.Sender, err) + } + fixedSizeFieldsEncoded, err := h.abiEncode( + "encodeFixedSizeFieldsHashPreimage", + msgID, + decodedSender, common.HexToAddress(string(msg.Receiver)), uint64(msg.SeqNum), msg.ChainFeeLimit.Int, - msg.Strict, msg.Nonce, - common.HexToAddress(string(msg.FeeToken)), - msg.FeeTokenAmount.Int, ) if err != nil { return [32]byte{}, fmt.Errorf("abi encode fixed size values: %w", err) } - fixedSizeValuesHash := utils.Keccak256Fixed(packedFixedSizeValues) packedValues, err := h.abiEncode( - h.packedValuesAbi, - h.leafDomainSeparator, - h.metaDataHash, - fixedSizeValuesHash, + "encodeFinalHashPreimage", + leafDomainSeparator, + utils.Keccak256Fixed(metaDataHashInput), + utils.Keccak256Fixed(fixedSizeFieldsEncoded), utils.Keccak256Fixed(msg.Data), utils.Keccak256Fixed(encodedTokens), utils.Keccak256Fixed(encodedSourceTokenData), @@ -114,22 +139,14 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.CCIPMsg) (ccipty return utils.Keccak256Fixed(packedValues), nil } -func (h *MessageHasherV1) abiEncode(theAbi abi.ABI, values ...interface{}) ([]byte, error) { - res, err := theAbi.Pack("method", values...) +func (h *MessageHasherV1) 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 } -func mustParseInputsAbi(s string) abi.ABI { - inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "inputs": %s}]`, s) - inAbi, err := abi.JSON(strings.NewReader(inDef)) - if err != nil { - panic(fmt.Errorf("failed to create %s ABI: %v", s, err)) - } - return inAbi -} - // Interface compliance check var _ cciptypes.MessageHasher = (*MessageHasherV1)(nil) diff --git a/core/services/ocr3/plugins/ccipevm/msghasher_test.go b/core/services/ocr3/plugins/ccipevm/msghasher_test.go index 3a49d78f9a..0bdf2c04b9 100644 --- a/core/services/ocr3/plugins/ccipevm/msghasher_test.go +++ b/core/services/ocr3/plugins/ccipevm/msghasher_test.go @@ -1,6 +1,7 @@ package ccipevm import ( + "context" cryptorand "crypto/rand" "encoding/hex" "fmt" @@ -13,42 +14,85 @@ import ( "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" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "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" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestMessageHasher_e2e(t *testing.T) { - // Deploy messageHasher contract ctx := testutils.Context(t) d := testSetup(t) + // low budget "fuzz" test. + // TODO: should actually write a real fuzz test. + for i := 0; i < 5; i++ { + testHasher(ctx, t, d) + } +} + +func testHasher(ctx context.Context, t *testing.T, d *testSetupData) { + destChainSelector := rand.Uint64() + onRampAddress := testutils.NewAddress().Bytes() + ccipMsg := createCCIPMsg(t) + + evmTokenAmounts := make([]message_hasher.ClientEVMTokenAmount, 0, len(ccipMsg.TokenAmounts)) + for _, ta := range ccipMsg.TokenAmounts { + evmTokenAmounts = append(evmTokenAmounts, message_hasher.ClientEVMTokenAmount{ + Token: common.HexToAddress(string(ta.Token)), + Amount: ta.Amount, + }) + } + evmMsg := message_hasher.InternalAny2EVMRampMessage{ + Header: message_hasher.InternalRampMessageHeader{ + MessageId: mustMessageID(t, ccipMsg.ID), + SourceChainSelector: uint64(ccipMsg.SourceChain), + DestChainSelector: destChainSelector, + SequenceNumber: uint64(ccipMsg.SeqNum), + Nonce: ccipMsg.Nonce, + }, + Sender: common.HexToAddress(string(ccipMsg.Sender)).Bytes(), + Receiver: common.HexToAddress(string(ccipMsg.Receiver)), + GasLimit: ccipMsg.ChainFeeLimit.Int, + Data: ccipMsg.Data, + TokenAmounts: evmTokenAmounts, + SourceTokenData: ccipMsg.SourceTokenData, + } + + expectedHash, err := d.contract.Hash(&bind.CallOpts{Context: ctx}, evmMsg, onRampAddress) + require.NoError(t, err) + + evmMsgHasher := NewMessageHasherV1(onRampAddress, cciptypes.ChainSelector(destChainSelector)) + actualHash, err := evmMsgHasher.Hash(ctx, ccipMsg) + require.NoError(t, err) + + require.Equal(t, fmt.Sprintf("%x", expectedHash), strings.TrimPrefix(actualHash.String(), "0x")) +} + +// TODO: fix this once messageID is part of CCIPMsg +func createCCIPMsg(t *testing.T) cciptypes.CCIPMsg { // Setup random msg data - metadataHash := utils.RandomBytes32() + messageID := utils.RandomBytes32() sourceTokenData := make([]byte, rand.Intn(2048)) _, err := cryptorand.Read(sourceTokenData) - assert.NoError(t, err) + require.NoError(t, err) sourceChain := rand.Uint64() seqNum := rand.Uint64() chainFeeLimit := rand.Uint64() nonce := rand.Uint64() - strict := rand.Intn(2) == 1 - feeTokenAmount := rand.Uint64() - data := make([]byte, rand.Intn(2048)) - _, err = cryptorand.Read(data) - assert.NoError(t, err) + messageData := make([]byte, rand.Intn(2048)) + _, err = cryptorand.Read(messageData) + require.NoError(t, err) sourceTokenDatas := make([][]byte, rand.Intn(10)) for i := range sourceTokenDatas { @@ -63,53 +107,34 @@ func TestMessageHasher_e2e(t *testing.T) { Amount: big.NewInt(0).SetUint64(rand.Uint64()), }) } - ccipMsg := cciptypes.CCIPMsg{ + return cciptypes.CCIPMsg{ CCIPMsgBaseDetails: cciptypes.CCIPMsgBaseDetails{ + ID: hex.EncodeToString(messageID[:]), SourceChain: cciptypes.ChainSelector(sourceChain), SeqNum: cciptypes.SeqNum(seqNum), }, - ChainFeeLimit: cciptypes.NewBigInt(big.NewInt(0).SetUint64(chainFeeLimit)), - Nonce: nonce, - Sender: types.Account(utils.RandomAddress().String()), - Receiver: types.Account(utils.RandomAddress().String()), - Strict: strict, - FeeToken: types.Account(utils.RandomAddress().String()), - FeeTokenAmount: cciptypes.NewBigInt(big.NewInt(0).SetUint64(feeTokenAmount)), - Data: data, + ChainFeeLimit: cciptypes.NewBigInt(big.NewInt(0).SetUint64(chainFeeLimit)), + Nonce: nonce, + Sender: types.Account(utils.RandomAddress().String()), + Receiver: types.Account(utils.RandomAddress().String()), + // TODO: remove this field if not needed, not used by the hasher + // Strict: strict, + // NOTE: not used by the hasher + // FeeToken: types.Account(utils.RandomAddress().String()), + // FeeTokenAmount: cciptypes.NewBigInt(big.NewInt(0).SetUint64(feeTokenAmount)), + Data: messageData, TokenAmounts: tokenAmounts, SourceTokenData: sourceTokenDatas, } +} - evmTokenAmounts := make([]message_hasher.ClientEVMTokenAmount, 0, len(ccipMsg.TokenAmounts)) - for _, ta := range ccipMsg.TokenAmounts { - evmTokenAmounts = append(evmTokenAmounts, message_hasher.ClientEVMTokenAmount{ - Token: common.HexToAddress(string(ta.Token)), - Amount: ta.Amount, - }) - } - evmMsg := message_hasher.InternalEVM2EVMMessage{ - SourceChainSelector: uint64(ccipMsg.SourceChain), - Sender: common.HexToAddress(string(ccipMsg.Sender)), - Receiver: common.HexToAddress(string(ccipMsg.Receiver)), - SequenceNumber: uint64(ccipMsg.SeqNum), - GasLimit: ccipMsg.ChainFeeLimit.Int, - Strict: ccipMsg.Strict, - Nonce: ccipMsg.Nonce, - FeeToken: common.HexToAddress(string(ccipMsg.FeeToken)), - FeeTokenAmount: ccipMsg.FeeTokenAmount.Int, - Data: ccipMsg.Data, - TokenAmounts: evmTokenAmounts, - SourceTokenData: ccipMsg.SourceTokenData, - } - - h, err := d.contract.Hash(&bind.CallOpts{Context: ctx}, evmMsg, metadataHash) - assert.NoError(t, err) - - evmMsgHasher := NewMessageHasherV1(metadataHash) - h2, err := evmMsgHasher.Hash(ctx, ccipMsg) - assert.NoError(t, err) - - assert.Equal(t, fmt.Sprintf("%x", h), strings.TrimPrefix(h2.String(), "0x")) +func mustMessageID(t *testing.T, msgIDHex string) [32]byte { + msgID, err := hex.DecodeString(msgIDHex) + require.NoError(t, err) + require.Len(t, msgID, 32) + var msgID32 [32]byte + copy(msgID32[:], msgID) + return msgID32 } type testSetupData struct { @@ -119,211 +144,25 @@ type testSetupData struct { auth *bind.TransactOpts } -const chainID = 1337 - func testSetup(t *testing.T) *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) + 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(auth, simulatedBackend) - assert.NoError(t, err) + address, _, _, err := message_hasher.DeployMessageHasher(transactor, simulatedBackend) + require.NoError(t, err) simulatedBackend.Commit() // Setup contract client contract, err := message_hasher.NewMessageHasher(address, simulatedBackend) - assert.NoError(t, err) + require.NoError(t, err) return &testSetupData{ contractAddr: address, contract: contract, sb: simulatedBackend, - auth: auth, - } -} - -func TestMessageHasher_Hash(t *testing.T) { - ctx := testutils.Context(t) - - largeNumber, ok := big.NewInt(0).SetString("1000000000000000000", 10) // 1e18 - require.True(t, ok) - - msgData, err := hex.DecodeString("64617461") - require.NoError(t, err) - - sourceTokenData1, err := hex.DecodeString("000000000000000000000000000000000000000000000000000000000000002000" + - "000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000" + - "0000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000" + - "0000000000000000000000000000000000000000000200000000000000000000000009e7218a11a2cda657ae50bd9cc5f953174aa" + - "e2a50000000000000000000000000000000000000000000000000000000000000020000000000000000000000000e4eebe19216af8" + - "6b9a996f53bd80b8365f832be80000000000000000000000000000000000000000000000000000000000000000") - require.NoError(t, err) - - sourceTokenData2, err := hex.DecodeString("000000000000000000000000000000000000000000000000000000000000002" + - "00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000" + - "00000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000" + - "000000000000000000000000000000000000000000000020000000000000000000000000e2c2bb2f43b91f65b5519708e34031039" + - "4c72d8f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000bd2f7046d10" + - "59abfe5316b48f050684a4676710f0000000000000000000000000000000000000000000000000000000000000000") - require.NoError(t, err) - - // metadataHash used in this test is copied from on-chain tests - // keccak256(abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))) - metadataHash := [32]byte{39, 130, 244, 70, 94, 31, 113, 169, 251, 136, 123, 6, 255, 77, 50, 91, 73, - 144, 94, 70, 13, 16, 47, 1, 171, 201, 40, 185, 144, 12, 103, 129} - - testCases := []struct { - name string - msg cciptypes.CCIPMsg - exp string - expErr bool - }{ - { - name: "empty msg", - msg: cciptypes.CCIPMsg{ - ChainFeeLimit: cciptypes.NewBigIntFromInt64(0), - FeeTokenAmount: cciptypes.NewBigIntFromInt64(0), - }, - exp: "0x3682d9965b91efa44c6274446a362dca2ea526bf3858bf54d52ec56be716f6be", - expErr: false, - }, - { - name: "base msg", - msg: cciptypes.CCIPMsg{ - CCIPMsgBaseDetails: cciptypes.CCIPMsgBaseDetails{ - SourceChain: 1, - SeqNum: 1, - }, - ChainFeeLimit: cciptypes.NewBigIntFromInt64(400000), - Nonce: 1, - Sender: "0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e", - Receiver: "0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e", - Strict: false, - FeeToken: "0xcE4ec7b524851E51d5C55eeFbBb8E58E8Ce2515F", - FeeTokenAmount: cciptypes.NewBigIntFromInt64(1234567890), - Data: []byte{}, - TokenAmounts: []cciptypes.TokenAmount{}, - SourceTokenData: [][]byte{}, - Metadata: cciptypes.CCIPMsgMetadata{}, - }, - exp: "0x23bf76c493e9bf58346b7cac0e9f357f5879f3d673819e5f27fc443cf9c907b9", - expErr: false, - }, - { - name: "full msg", - msg: cciptypes.CCIPMsg{ - CCIPMsgBaseDetails: cciptypes.CCIPMsgBaseDetails{ - SourceChain: 1, - SeqNum: 1, - }, - ChainFeeLimit: cciptypes.NewBigIntFromInt64(400000), - Nonce: 1, - Sender: "0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e", - Receiver: "0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e", - Strict: false, - FeeToken: "0xcE4ec7b524851E51d5C55eeFbBb8E58E8Ce2515F", - FeeTokenAmount: cciptypes.NewBigIntFromInt64(1234567890), - Data: msgData, - TokenAmounts: []cciptypes.TokenAmount{ - { - Token: "0xcE4ec7b524851E51d5C55eeFbBb8E58E8Ce2515F", - Amount: largeNumber, - }, - }, - SourceTokenData: [][]byte{sourceTokenData1}, - Metadata: cciptypes.CCIPMsgMetadata{}, - }, - exp: "0xe04ade4e6a1121155ca1e89f17c9df6c9236fdcfdf38b97594594d0540345d60", - expErr: false, - }, - { - name: "full msg 2 - two source token data items", - msg: cciptypes.CCIPMsg{ - CCIPMsgBaseDetails: cciptypes.CCIPMsgBaseDetails{ - SourceChain: 1, - SeqNum: 1, - }, - ChainFeeLimit: cciptypes.NewBigIntFromInt64(400000), - Nonce: 1, - Sender: "0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e", - Receiver: "0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e", - Strict: false, - FeeToken: "0xcE4ec7b524851E51d5C55eeFbBb8E58E8Ce2515F", - FeeTokenAmount: cciptypes.NewBigIntFromInt64(1234567890), - Data: msgData, - TokenAmounts: []cciptypes.TokenAmount{ - { - Token: "0xcE4ec7b524851E51d5C55eeFbBb8E58E8Ce2515F", - Amount: largeNumber, - }, - { - Token: "0x3c78e47de47B765dcEE2F30F31B3CF5F10B42d1F", - Amount: largeNumber, - }, - }, - SourceTokenData: [][]byte{sourceTokenData1, sourceTokenData2}, - Metadata: cciptypes.CCIPMsgMetadata{}, - }, - exp: "0x30123234e5d9e0cd94610e83be2e0128167b9ab072e8e9450f1f7704b9901589", - expErr: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - m := NewMessageHasherV1(metadataHash) - hash, err := m.Hash(ctx, tc.msg) - if tc.expErr { - assert.Error(t, err) - return - } - - assert.NoError(t, err) - assert.Equal(t, tc.exp, hash.String()) - }) - } -} - -func BenchmarkMessageHasher_Hash(b *testing.B) { - ctx := testutils.Context(b) - msg := cciptypes.CCIPMsg{ - CCIPMsgBaseDetails: cciptypes.CCIPMsgBaseDetails{ - SourceChain: 1, - SeqNum: 1, - }, - ChainFeeLimit: cciptypes.NewBigIntFromInt64(400000), - Nonce: 1, - Sender: types.Account(utils.RandomAddress().String()), - Receiver: types.Account(utils.RandomAddress().String()), - Strict: false, - FeeToken: types.Account(utils.RandomAddress().String()), - FeeTokenAmount: cciptypes.NewBigIntFromInt64(1234567890), - Data: make([]byte, 2048), - TokenAmounts: []cciptypes.TokenAmount{ - { - Token: types.Account(utils.RandomAddress().String()), - Amount: utils.RandUint256(), - }, - }, - SourceTokenData: [][]byte{make([]byte, 2048)}, - } - metadataHash := utils.RandomBytes32() - - m := NewMessageHasherV1(metadataHash) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := m.Hash(ctx, msg) - require.NoError(b, err) + auth: transactor, } } From 54127b1fbc214cf35b150fed03706598267051a6 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:10:15 +0530 Subject: [PATCH 49/61] Disable LM smoke tests on CI (#1131) ## Motivation https://smartcontract-it.atlassian.net/browse/LM-176 ## Solution --- .github/workflows/integration-tests.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 194b095298..79053bd072 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -303,12 +303,13 @@ jobs: fail-fast: false matrix: product: - - name: ccip-lm-smoke - nodes: 1 - os: ubuntu-latest - file: lm - dir: ccip-tests/smoke - run: -run ^TestLmBasic$ +# LM Smoke Test is disabled since project is paused +# - name: ccip-lm-smoke +# nodes: 1 +# os: ubuntu-latest +# file: lm +# dir: ccip-tests/smoke +# run: -run ^TestLmBasic$ - name: ccip-smoke nodes: 1 os: ubuntu-latest From 3a01e27bcab5321ddf8e29fe759d20ca41e934b5 Mon Sep 17 00:00:00 2001 From: Makram Kamaleddine Date: Mon, 8 Jul 2024 15:19:21 +0300 Subject: [PATCH 50/61] fix lint, test --- .../ocr3impls/multichain_config_digester.go | 3 ++- docs/CONFIG.md | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/services/ocr2/plugins/liquiditymanager/ocr3impls/multichain_config_digester.go b/core/services/ocr2/plugins/liquiditymanager/ocr3impls/multichain_config_digester.go index 5b8fe164e8..83a3ceedb3 100644 --- a/core/services/ocr2/plugins/liquiditymanager/ocr3impls/multichain_config_digester.go +++ b/core/services/ocr2/plugins/liquiditymanager/ocr3impls/multichain_config_digester.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + ocr2plustypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -78,5 +79,5 @@ func (d MultichainConfigDigester) ConfigDigest(cc types.ContractConfig) (types.C } func (d MultichainConfigDigester) ConfigDigestPrefix() (types.ConfigDigestPrefix, error) { - return types.ConfigDigestPrefixEVM, nil + return ocr2plustypes.ConfigDigestPrefixEVMSimple, nil } diff --git a/docs/CONFIG.md b/docs/CONFIG.md index c9b117349c..e38fbdd6de 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -4017,6 +4017,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -4072,6 +4073,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -5036,6 +5039,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5091,6 +5095,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -5405,6 +5411,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -5460,6 +5467,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -6331,6 +6340,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 2 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6385,6 +6395,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 1 @@ -6606,6 +6618,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -6661,6 +6674,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 @@ -7538,6 +7553,7 @@ NonceAutoSync = true NoNewHeadsThreshold = '3m0s' RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 0 [Transactions] ForwardersEnabled = false @@ -7593,6 +7609,8 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = false +DeathDeclarationDelay = '10s' [OCR] ContractConfirmations = 4 From 053e93ad24e47720dfd64cb087b7cb5f8e41408b Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Mon, 8 Jul 2024 17:21:40 +0200 Subject: [PATCH 51/61] Returning messageVisibilityInterval always from commit roots cache (#1155) ## Motivation Commit's Roots cache stores block_timestamps for the CommitReports, but when reorgs happens block_timestamp can also change because TX could be included in a different block. Example scenario: CommitRoot with 10:30:00 UTC block timestamp is inserted with `AppendUnexecutedRoot` (so it's block_timestamp is persisted in the cache). Then reorg happens on the destination and the same CommitRoot is inserted into the blockchain but let's say with 10:29:00 UTC (different block_time), which is never updated. Commit Roots cache returns persisted 10:30:00 as the oldest block timestamp and we keep searching LogPoller using the wrong lower bound filter - this Commit Root never pops up in the execution because it's never returned from DB --- .../ccip/internal/cache/commit_roots.go | 61 +++--- .../ccip/internal/cache/commit_roots_test.go | 179 +++++++++--------- 2 files changed, 124 insertions(+), 116 deletions(-) diff --git a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go index 6f850ad39c..ae5fe8fcde 100644 --- a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go +++ b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go @@ -131,38 +131,41 @@ func (s *commitRootsCache) Snooze(merkleRoot [32]byte) { } func (s *commitRootsCache) OldestRootTimestamp() time.Time { - messageVisibilityInterval := time.Now().Add(-s.messageVisibilityInterval) - timestamp, ok := s.pickOldestRootBlockTimestamp(messageVisibilityInterval) - - if ok { - return timestamp - } - - s.rootsQueueMu.Lock() - defer s.rootsQueueMu.Unlock() - - // If rootsSearchFilter is before messageVisibilityInterval, it means that we have roots that are stuck forever and will never be executed - // In that case, we wipe out the entire queue. Next round should start from the messageVisibilityInterval and rebuild cache from scratch. - s.unexecutedRootsQueue = orderedmap.New[string, time.Time]() - return messageVisibilityInterval + return time.Now().Add(-s.messageVisibilityInterval) + // TODO we can't rely on block timestamps, because in case of re-org they can change and therefore affect + // the logic in the case. In the meantime, always fallback to the default behaviour and use permissionlessThresholdWindow + //timestamp, ok := s.pickOldestRootBlockTimestamp(messageVisibilityInterval) + // + //if ok { + // return timestamp + //} + // + //s.rootsQueueMu.Lock() + //defer s.rootsQueueMu.Unlock() + // + //// If rootsSearchFilter is before messageVisibilityInterval, it means that we have roots that are stuck forever and will never be executed + //// In that case, we wipe out the entire queue. Next round should start from the messageVisibilityInterval and rebuild cache from scratch. + //s.unexecutedRootsQueue = orderedmap.New[string, time.Time]() + //return messageVisibilityInterval } -func (s *commitRootsCache) pickOldestRootBlockTimestamp(messageVisibilityInterval time.Time) (time.Time, bool) { - s.rootsQueueMu.RLock() - defer s.rootsQueueMu.RUnlock() - - // If there are no roots in the queue, we can return the messageVisibilityInterval - if s.oldestRootTimestamp.IsZero() { - return messageVisibilityInterval, true - } +//func (s *commitRootsCache) pickOldestRootBlockTimestamp(messageVisibilityInterval time.Time) (time.Time, bool) { +// s.rootsQueueMu.RLock() +// defer s.rootsQueueMu.RUnlock() +// +// // If there are no roots in the queue, we can return the messageVisibilityInterval +// if s.oldestRootTimestamp.IsZero() { +// return messageVisibilityInterval, true +// } +// +// if s.oldestRootTimestamp.After(messageVisibilityInterval) { +// // Query used for fetching roots from the database is exclusive (block_timestamp > :timestamp) +// // so we need to subtract 1 second from the head timestamp to make sure that this root is included in the results +// return s.oldestRootTimestamp.Add(-time.Second), true +// } +// return time.Time{}, false +//} - if s.oldestRootTimestamp.After(messageVisibilityInterval) { - // Query used for fetching roots from the database is exclusive (block_timestamp > :timestamp) - // so we need to subtract 1 second from the head timestamp to make sure that this root is included in the results - return s.oldestRootTimestamp.Add(-time.Second), true - } - return time.Time{}, false -} func (s *commitRootsCache) AppendUnexecutedRoot(merkleRoot [32]byte, blockTimestamp time.Time) { prettyMerkleRoot := merkleRootToString(merkleRoot) 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 9dd8c365aa..f79e365d0c 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 @@ -67,60 +67,60 @@ func Test_UnexecutedRoots(t *testing.T) { roots: []rootWithTs{}, permissionLessThreshold: 1 * time.Hour, }, - { - name: "returns first root when all are not executed", - roots: []rootWithTs{ - {r1, t1}, - {r2, t2}, - {r3, t3}, - }, - permissionLessThreshold: 10 * time.Hour, - expectedTimestamp: t1, - }, - { - name: "returns first root when tail of queue is executed", - roots: []rootWithTs{ - {r1, t1}, - {r2, t2}, - {r3, t3}, - }, - executedRoots: [][32]byte{r2, r3}, - permissionLessThreshold: 10 * time.Hour, - expectedTimestamp: t1, - }, - { - name: "returns first not executed root", - roots: []rootWithTs{ - {r1, t1}, - {r2, t2}, - {r3, t3}, - }, - executedRoots: [][32]byte{r1, r2}, - permissionLessThreshold: 10 * time.Hour, - expectedTimestamp: t3, - }, - { - name: "returns r2 timestamp when r1 and r3 are executed", - roots: []rootWithTs{ - {r1, t1}, - {r2, t2}, - {r3, t3}, - }, - executedRoots: [][32]byte{r1, r3}, - permissionLessThreshold: 10 * time.Hour, - expectedTimestamp: t2, - }, - { - name: "returns oldest root even when all are executed", - roots: []rootWithTs{ - {r1, t1}, - {r2, t2}, - {r3, t3}, - }, - executedRoots: [][32]byte{r1, r2, r3}, - permissionLessThreshold: 10 * time.Hour, - expectedTimestamp: t3, - }, + //{ + // name: "returns first root when all are not executed", + // roots: []rootWithTs{ + // {r1, t1}, + // {r2, t2}, + // {r3, t3}, + // }, + // permissionLessThreshold: 10 * time.Hour, + // expectedTimestamp: t1, + //}, + //{ + // name: "returns first root when tail of queue is executed", + // roots: []rootWithTs{ + // {r1, t1}, + // {r2, t2}, + // {r3, t3}, + // }, + // executedRoots: [][32]byte{r2, r3}, + // permissionLessThreshold: 10 * time.Hour, + // expectedTimestamp: t1, + //}, + //{ + // name: "returns first not executed root", + // roots: []rootWithTs{ + // {r1, t1}, + // {r2, t2}, + // {r3, t3}, + // }, + // executedRoots: [][32]byte{r1, r2}, + // permissionLessThreshold: 10 * time.Hour, + // expectedTimestamp: t3, + //}, + //{ + // name: "returns r2 timestamp when r1 and r3 are executed", + // roots: []rootWithTs{ + // {r1, t1}, + // {r2, t2}, + // {r3, t3}, + // }, + // executedRoots: [][32]byte{r1, r3}, + // permissionLessThreshold: 10 * time.Hour, + // expectedTimestamp: t2, + //}, + //{ + // name: "returns oldest root even when all are executed", + // roots: []rootWithTs{ + // {r1, t1}, + // {r2, t2}, + // {r3, t3}, + // }, + // executedRoots: [][32]byte{r1, r2, r3}, + // permissionLessThreshold: 10 * time.Hour, + // expectedTimestamp: t3, + //}, { name: "returns permissionLessThreshold when all roots ale older that threshold", roots: []rootWithTs{ @@ -161,12 +161,12 @@ func Test_UnexecutedRootsScenario(t *testing.T) { k1 := [32]byte{1} k2 := [32]byte{2} k3 := [32]byte{3} - k4 := [32]byte{4} + //k4 := [32]byte{4} t1 := time.Now().Add(-4 * time.Hour) t2 := time.Now().Add(-3 * time.Hour) t3 := time.Now().Add(-2 * time.Hour) - t4 := time.Now().Add(-1 * time.Hour) + //t4 := time.Now().Add(-1 * time.Hour) // First check should return permissionLessThreshold window commitTs := c.OldestRootTimestamp() @@ -176,42 +176,47 @@ func Test_UnexecutedRootsScenario(t *testing.T) { c.AppendUnexecutedRoot(k2, t2) c.AppendUnexecutedRoot(k3, t3) - // After loading roots it should return the first one - commitTs = c.OldestRootTimestamp() - assert.Equal(t, t1.Add(-time.Second), commitTs) - - // Marking root in the middle as executed shouldn't change the commitTs - c.MarkAsExecuted(k2) - commitTs = c.OldestRootTimestamp() - assert.Equal(t, t1.Add(-time.Second), commitTs) - - // Marking k1 as executed when k2 is already executed should return timestamp of k3 - c.MarkAsExecuted(k1) - commitTs = c.OldestRootTimestamp() - assert.Equal(t, t3.Add(-time.Second), commitTs) - - // Marking all as executed should return timestamp of the latest - c.MarkAsExecuted(k3) commitTs = c.OldestRootTimestamp() - assert.Equal(t, t3.Add(-time.Second), commitTs) - - // Adding k4 should return timestamp of k4 - c.AppendUnexecutedRoot(k4, t4) - commitTs = c.OldestRootTimestamp() - assert.Equal(t, t4.Add(-time.Second), commitTs) - - c.MarkAsExecuted(k4) - commitTs = c.OldestRootTimestamp() - assert.Equal(t, t4.Add(-time.Second), commitTs) + assert.True(t, commitTs.Before(time.Now().Add(-permissionLessThreshold))) - // Appending already executed roots should be ignored - c.AppendUnexecutedRoot(k1, t1) - c.AppendUnexecutedRoot(k2, t2) - commitTs = c.OldestRootTimestamp() - assert.Equal(t, t4.Add(-time.Second), commitTs) + //// After loading roots it should return the first one + //commitTs = c.OldestRootTimestamp() + //assert.Equal(t, t1.Add(-time.Second), commitTs) + // + //// Marking root in the middle as executed shouldn't change the commitTs + //c.MarkAsExecuted(k2) + //commitTs = c.OldestRootTimestamp() + //assert.Equal(t, t1.Add(-time.Second), commitTs) + // + //// Marking k1 as executed when k2 is already executed should return timestamp of k3 + //c.MarkAsExecuted(k1) + //commitTs = c.OldestRootTimestamp() + //assert.Equal(t, t3.Add(-time.Second), commitTs) + // + //// Marking all as executed should return timestamp of the latest + //c.MarkAsExecuted(k3) + //commitTs = c.OldestRootTimestamp() + //assert.Equal(t, t3.Add(-time.Second), commitTs) + // + //// Adding k4 should return timestamp of k4 + //c.AppendUnexecutedRoot(k4, t4) + //commitTs = c.OldestRootTimestamp() + //assert.Equal(t, t4.Add(-time.Second), commitTs) + // + //c.MarkAsExecuted(k4) + //commitTs = c.OldestRootTimestamp() + //assert.Equal(t, t4.Add(-time.Second), commitTs) + // + //// Appending already executed roots should be ignored + //c.AppendUnexecutedRoot(k1, t1) + //c.AppendUnexecutedRoot(k2, t2) + //commitTs = c.OldestRootTimestamp() + //assert.Equal(t, t4.Add(-time.Second), commitTs) } func Test_UnexecutedRootsStaleQueue(t *testing.T) { + t.Skip("This test needs caching to properly handle re-orgs") + permissionLessThreshold := 5 * time.Hour c := newCommitRootsCache(logger.TestLogger(t), permissionLessThreshold, 1*time.Hour, 1*time.Millisecond, 1*time.Millisecond) From 5db8286a50df2a262c215273d3a2f58ef8869439 Mon Sep 17 00:00:00 2001 From: Patrick Date: Mon, 8 Jul 2024 11:44:45 -0400 Subject: [PATCH 52/61] Using a provider proxied commit store implementation in commit (#1080) ## Motivation Continues the work done in feature/ccip-1250 and adds a provider based implementation of a CommitStore ## Solution ![Provider Proxy Commit Store Approach](https://github.com/smartcontractkit/ccip/assets/16763321/b9bcab73-9289-4867-88bc-6a6019d86c1f) --------- Co-authored-by: ilija42 <57732589+ilija42@users.noreply.github.com> Co-authored-by: Aaron Lu <50029043+aalu1418@users.noreply.github.com> --- core/services/ocr2/delegate.go | 31 +-- .../ocr2/plugins/ccip/ccipcommit/factory.go | 1 - .../plugins/ccip/ccipcommit/initializers.go | 16 +- .../ocr2/plugins/ccip/exportinternal.go | 16 ++ .../internal/ccipdata/v1_2_0/commit_store.go | 6 +- .../plugins/ccip/prices/da_price_estimator.go | 4 +- .../ccip/prices/gas_price_estimator.go | 18 +- .../ocr2/plugins/ccip/proxycommitstore.go | 135 ++++++++++++ core/services/relay/evm/ccip.go | 205 ++++++++++++++++++ core/services/relay/evm/commit_provider.go | 29 ++- core/services/relay/evm/evm.go | 2 + 11 files changed, 397 insertions(+), 66 deletions(-) create mode 100644 core/services/ocr2/plugins/ccip/proxycommitstore.go create mode 100644 core/services/relay/evm/ccip.go diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 429a086fe0..32b91c3d93 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -9,7 +9,7 @@ import ( "strconv" "time" - chainselectors "github.com/smartcontractkit/chain-selectors" + "gopkg.in/guregu/null.v4" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink-common/pkg/types/core" @@ -18,12 +18,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" + chainselectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/libocr/commontypes" libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "google.golang.org/grpc" - "gopkg.in/guregu/null.v4" ocr2keepers20 "github.com/smartcontractkit/chainlink-automation/pkg/v2" ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" @@ -32,7 +32,6 @@ import ( ocr2keepers20runner "github.com/smartcontractkit/chainlink-automation/pkg/v2/runner" ocr2keepers21config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin" - commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins" @@ -41,7 +40,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink-vrf/altbn_128" dkgpkg "github.com/smartcontractkit/chainlink-vrf/dkg" "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" @@ -279,12 +277,12 @@ func (d *Delegate) JobType() job.Type { return job.OffchainReporting2 } -func (d *Delegate) BeforeJobCreated(spec job.Job) { +func (d *Delegate) BeforeJobCreated(_ job.Job) { // This is only called first time the job is created d.isNewlyCreatedJob = true } -func (d *Delegate) AfterJobCreated(spec job.Job) {} -func (d *Delegate) BeforeJobDeleted(spec job.Job) {} +func (d *Delegate) AfterJobCreated(_ job.Job) {} +func (d *Delegate) BeforeJobDeleted(_ job.Job) {} func (d *Delegate) OnDeleteJob(ctx context.Context, jb job.Job) error { // If the job spec is malformed in any way, we report the error but return nil so that // the job deletion itself isn't blocked. @@ -1287,10 +1285,10 @@ func (d *Delegate) newServicesOCR2VRF( lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) dkgReportingPluginFactoryDecorator := func(wrapped ocrtypes.ReportingPluginFactory) ocrtypes.ReportingPluginFactory { - return promwrapper.NewPromFactory(wrapped, "DKG", string(relay.NetworkEVM), chain.ID()) + return promwrapper.NewPromFactory(wrapped, "DKG", relay.NetworkEVM, chain.ID()) } vrfReportingPluginFactoryDecorator := func(wrapped ocrtypes.ReportingPluginFactory) ocrtypes.ReportingPluginFactory { - return promwrapper.NewPromFactory(wrapped, "OCR2VRF", string(relay.NetworkEVM), chain.ID()) + return promwrapper.NewPromFactory(wrapped, "OCR2VRF", relay.NetworkEVM, chain.ID()) } noopMonitoringEndpoint := telemetry.NoopAgent{} oracles, err2 := ocr2vrf.NewOCR2VRF(ocr2vrf.DKGVRFArgs{ @@ -1815,11 +1813,6 @@ func (d *Delegate) newServicesCCIPCommit(ctx context.Context, lggr logger.Sugare return nil, ErrJobSpecNoRelayer{Err: err, PluginName: string(spec.PluginType)} } - dstChain, err := d.legacyChains.Get(dstRid.ChainID) - if err != nil { - return nil, fmt.Errorf("ccip services; failed to get chain %s: %w", dstRid.ChainID, err) - } - logError := func(msg string) { lggr.ErrorIf(d.jobORM.RecordError(context.Background(), jb.ID, msg), "unable to record error") } @@ -1846,12 +1839,6 @@ func (d *Delegate) newServicesCCIPCommit(ctx context.Context, lggr logger.Sugare return nil, err } - srcChainIDstr := strconv.FormatUint(srcChainID, 10) - srcChain, err := d.legacyChains.Get(srcChainIDstr) - if err != nil { - return nil, fmt.Errorf("open source chain: %w", err) - } - oracleArgsNoPlugin := libocr2.OCR2OracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -1871,7 +1858,7 @@ func (d *Delegate) newServicesCCIPCommit(ctx context.Context, lggr logger.Sugare MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": jb.Name.ValueOrZero()}, prometheus.DefaultRegisterer), } - return ccipcommit.NewCommitServices(ctx, d.ds, srcProvider, dstProvider, srcChain, dstChain, d.legacyChains, jb, lggr, d.pipelineRunner, oracleArgsNoPlugin, d.isNewlyCreatedJob, int64(srcChainID), dstChainID, logError) + return ccipcommit.NewCommitServices(ctx, d.ds, srcProvider, dstProvider, d.legacyChains, jb, lggr, d.pipelineRunner, oracleArgsNoPlugin, d.isNewlyCreatedJob, int64(srcChainID), dstChainID, logError) } func newCCIPCommitPluginBytes(isSourceProvider bool, sourceStartBlock uint64, destStartBlock uint64) config.CommitPluginConfig { @@ -1985,7 +1972,7 @@ func (d *Delegate) ccipCommitGetSrcProvider(ctx context.Context, jb job.Job, plu func (d *Delegate) newServicesCCIPExecution(ctx context.Context, lggr logger.SugaredLogger, jb job.Job, bootstrapPeers []commontypes.BootstrapperLocator, kb ocr2key.KeyBundle, ocrDB *db, lc ocrtypes.LocalConfig, transmitterID string) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec if spec.Relay != relay.NetworkEVM { - return nil, fmt.Errorf("Non evm chains are not supported for CCIP execution") + return nil, fmt.Errorf("non evm chains are not supported for CCIP execution") } dstRid, err := spec.RelayID() diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go index d4f5e03221..95d6398f56 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go @@ -27,7 +27,6 @@ type CommitReportingPluginFactory struct { } // NewCommitReportingPluginFactory return a new CommitReportingPluginFactory. -// TODO: wire through a GasEstimatorProvider here to solve two relayer one provider problem for CommitStoreReader func NewCommitReportingPluginFactory(config CommitPluginStaticConfig) *CommitReportingPluginFactory { return &CommitReportingPluginFactory{ config: config, diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go index 0ba086bac6..0d8a5414dc 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go @@ -43,7 +43,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" ) -func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider commontypes.CCIPCommitProvider, dstProvider commontypes.CCIPCommitProvider, srcChain legacyevm.Chain, dstChain legacyevm.Chain, chainSet legacyevm.LegacyChainContainer, jb job.Job, lggr logger.Logger, pr pipeline.Runner, argsNoPlugin libocr2.OCR2OracleArgs, new bool, sourceChainID int64, destChainID int64, logError func(string)) ([]job.ServiceCtx, error) { +func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider commontypes.CCIPCommitProvider, dstProvider commontypes.CCIPCommitProvider, chainSet legacyevm.LegacyChainContainer, jb job.Job, lggr logger.Logger, pr pipeline.Runner, argsNoPlugin libocr2.OCR2OracleArgs, new bool, sourceChainID int64, destChainID int64, logError func(string)) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec var pluginConfig ccipconfig.CommitPluginJobSpecConfig @@ -52,25 +52,19 @@ func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider c return nil, err } - // TODO CCIP-2493 EVM family specific behavior leaked for CommitStore, which requires access to two relayers - versionFinder := factory.NewEvmVersionFinder() commitStoreAddress := common.HexToAddress(spec.ContractID) - sourceMaxGasPrice := srcChain.Config().EVM().GasEstimator().PriceMax().ToInt() - commitStoreReader, err := ccip.NewCommitStoreReader(lggr, versionFinder, ccipcalc.EvmAddrToGeneric(commitStoreAddress), dstChain.Client(), dstChain.LogPoller()) - if err != nil { - return nil, err - } - - err = commitStoreReader.SetGasEstimator(ctx, srcChain.GasEstimator()) + srcCommitStore, err := srcProvider.NewCommitStoreReader(ctx, ccipcalc.EvmAddrToGeneric(commitStoreAddress)) if err != nil { return nil, err } - err = commitStoreReader.SetSourceMaxGasPrice(ctx, sourceMaxGasPrice) + dstCommitStore, err := dstProvider.NewCommitStoreReader(ctx, ccipcalc.EvmAddrToGeneric(commitStoreAddress)) if err != nil { return nil, err } + var commitStoreReader ccipdata.CommitStoreReader + commitStoreReader = ccip.NewProviderProxyCommitStoreReader(srcCommitStore, dstCommitStore) commitLggr := lggr.Named("CCIPCommit").With("sourceChain", sourceChainID, "destChain", destChainID) var priceGetter pricegetter.PriceGetter diff --git a/core/services/ocr2/plugins/ccip/exportinternal.go b/core/services/ocr2/plugins/ccip/exportinternal.go index 26922abe47..035aa6f68a 100644 --- a/core/services/ocr2/plugins/ccip/exportinternal.go +++ b/core/services/ocr2/plugins/ccip/exportinternal.go @@ -3,6 +3,7 @@ package ccip import ( "context" "math/big" + "time" "github.com/ethereum/go-ethereum/common" @@ -17,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/pricegetter" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" ) @@ -101,3 +103,17 @@ func (c *ChainAgnosticPriceRegistry) NewPriceRegistryReader(ctx context.Context, func NewChainAgnosticPriceRegistry(provider ChainAgnosticPriceRegistryFactory) *ChainAgnosticPriceRegistry { return &ChainAgnosticPriceRegistry{provider} } + +type JSONCommitOffchainConfigV1_2_0 = v1_2_0.JSONCommitOffchainConfig +type CommitOnchainConfig = ccipdata.CommitOnchainConfig + +func NewCommitOffchainConfig( + gasPriceDeviationPPB uint32, + gasPriceHeartBeat time.Duration, + tokenPriceDeviationPPB uint32, + tokenPriceHeartBeat time.Duration, + inflightCacheExpiry time.Duration, + priceReportingDisabled bool, +) ccip.CommitOffchainConfig { + return ccipdata.NewCommitOffchainConfig(gasPriceDeviationPPB, gasPriceHeartBeat, tokenPriceDeviationPPB, tokenPriceHeartBeat, inflightCacheExpiry, priceReportingDisabled) +} 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 f94c8e1a7b..a21781e84c 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,7 +49,7 @@ type CommitStore struct { // Dynamic config configMu sync.RWMutex - gasPriceEstimator prices.DAGasPriceEstimator + gasPriceEstimator *prices.DAGasPriceEstimator offchainConfig cciptypes.CommitOffchainConfig } @@ -228,7 +228,6 @@ func (c JSONCommitOffchainConfig) Validate() error { return nil } -// TODO: Pass a Gas Estimator through to the plugin directly func (c *CommitStore) ChangeConfig(_ context.Context, onchainConfig []byte, offchainConfig []byte) (cciptypes.Address, error) { onchainConfigParsed, err := abihelpers.DecodeAbiStruct[ccipdata.CommitOnchainConfig](onchainConfig) if err != nil { @@ -250,7 +249,6 @@ func (c *CommitStore) ChangeConfig(_ context.Context, onchainConfig []byte, offc return "", fmt.Errorf("this CommitStore sourceMaxGasPrice is nil. SetSourceMaxGasPrice should be called before ChangeConfig") } - // TODO: do this in the factory c.gasPriceEstimator = prices.NewDAGasPriceEstimator( *c.estimator, c.sourceMaxGasPrice, @@ -450,6 +448,6 @@ func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, l // The fields below are initially empty and set on ChangeConfig method offchainConfig: cciptypes.CommitOffchainConfig{}, - gasPriceEstimator: prices.DAGasPriceEstimator{}, + gasPriceEstimator: nil, }, nil } 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 83869dc0ef..7c75b9bdd9 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go @@ -26,8 +26,8 @@ func NewDAGasPriceEstimator( maxGasPrice *big.Int, deviationPPB int64, daDeviationPPB int64, -) DAGasPriceEstimator { - return DAGasPriceEstimator{ +) *DAGasPriceEstimator { + return &DAGasPriceEstimator{ execEstimator: NewExecGasPriceEstimator(estimator, maxGasPrice, deviationPPB), l1Oracle: estimator.L1Oracle(), priceEncodingLength: daGasPriceEncodingLength, 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 610dc3b3da..c5cf9e1b86 100644 --- a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go @@ -54,25 +54,11 @@ func NewGasPriceEstimatorForCommitPlugin( daDeviationPPB int64, execDeviationPPB int64, ) (GasPriceEstimatorCommit, error) { - execEstimator := ExecGasPriceEstimator{ - estimator: estimator, - maxGasPrice: maxExecGasPrice, - deviationPPB: execDeviationPPB, - } - switch commitStoreVersion.String() { case "1.0.0", "1.1.0": - return execEstimator, nil + return NewExecGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB), nil case "1.2.0": - return DAGasPriceEstimator{ - execEstimator: execEstimator, - l1Oracle: estimator.L1Oracle(), - priceEncodingLength: daGasPriceEncodingLength, - daDeviationPPB: daDeviationPPB, - daOverheadGas: 0, - gasPerDAByte: 0, - daMultiplier: 0, - }, nil + return NewDAGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB, daDeviationPPB), nil default: return nil, errors.Errorf("Invalid commitStore version: %s", commitStoreVersion) } diff --git a/core/services/ocr2/plugins/ccip/proxycommitstore.go b/core/services/ocr2/plugins/ccip/proxycommitstore.go new file mode 100644 index 0000000000..b06f957bd5 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/proxycommitstore.go @@ -0,0 +1,135 @@ +package ccip + +import ( + "context" + "fmt" + "io" + "math/big" + "time" + + "go.uber.org/multierr" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" +) + +// The disjunct methods in IncompleteSourceCommitStoreReader and IncompleteDestCommitStoreReader satisfy the full +// CommitStoreReader iface in Union +var _ cciptypes.CommitStoreReader = (*ProviderProxyCommitStoreReader)(nil) + +// ProviderProxyCommitStoreReader is a CommitStoreReader that proxies to two custom provider grpc backed implementations +// of a CommitStoreReader. +// [ProviderProxyCommitStoreReader] lives in the memory space of the reporting plugin factory and reporting plugin, and should have no chain-specific details. +// Why? Historical implementations of a commit store consumed in reporting plugins mixed usage of a gas estimator from +// the source relayer and contract read and write abilities to a dest relayer. This is not valid in LOOP world. +type ProviderProxyCommitStoreReader struct { + srcCommitStoreReader IncompleteSourceCommitStoreReader + dstCommitStoreReader IncompleteDestCommitStoreReader +} + +// IncompleteSourceCommitStoreReader contains only the methods of CommitStoreReader that are serviced by the source chain/relayer. +type IncompleteSourceCommitStoreReader interface { + ChangeConfig(ctx context.Context, onchainConfig []byte, offchainConfig []byte) (cciptypes.Address, error) + GasPriceEstimator(ctx context.Context) (cciptypes.GasPriceEstimatorCommit, error) + OffchainConfig(ctx context.Context) (cciptypes.CommitOffchainConfig, error) + io.Closer +} + +// IncompleteDestCommitStoreReader contains only the methods of CommitStoreReader that are serviced by the dest chain/relayer. +type IncompleteDestCommitStoreReader interface { + DecodeCommitReport(ctx context.Context, report []byte) (cciptypes.CommitStoreReport, error) + EncodeCommitReport(ctx context.Context, report cciptypes.CommitStoreReport) ([]byte, error) + GetAcceptedCommitReportsGteTimestamp(ctx context.Context, ts time.Time, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) + GetCommitReportMatchingSeqNum(ctx context.Context, seqNum uint64, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) + GetCommitStoreStaticConfig(ctx context.Context) (cciptypes.CommitStoreStaticConfig, error) + GetExpectedNextSequenceNumber(ctx context.Context) (uint64, error) + GetLatestPriceEpochAndRound(ctx context.Context) (uint64, error) + IsBlessed(ctx context.Context, root [32]byte) (bool, error) + IsDestChainHealthy(ctx context.Context) (bool, error) + IsDown(ctx context.Context) (bool, error) + VerifyExecutionReport(ctx context.Context, report cciptypes.ExecReport) (bool, error) + io.Closer +} + +func NewProviderProxyCommitStoreReader(srcReader cciptypes.CommitStoreReader, dstReader cciptypes.CommitStoreReader) *ProviderProxyCommitStoreReader { + return &ProviderProxyCommitStoreReader{ + srcCommitStoreReader: srcReader, + dstCommitStoreReader: dstReader, + } +} + +// ChangeConfig updates the offchainConfig values for the source relayer gas estimator by calling ChangeConfig +// on the source relayer. Once this is called, GasPriceEstimator and OffchainConfig can be called. +func (p *ProviderProxyCommitStoreReader) ChangeConfig(ctx context.Context, onchainConfig []byte, offchainConfig []byte) (cciptypes.Address, error) { + return p.srcCommitStoreReader.ChangeConfig(ctx, onchainConfig, offchainConfig) +} + +func (p *ProviderProxyCommitStoreReader) DecodeCommitReport(ctx context.Context, report []byte) (cciptypes.CommitStoreReport, error) { + return p.dstCommitStoreReader.DecodeCommitReport(ctx, report) +} + +func (p *ProviderProxyCommitStoreReader) EncodeCommitReport(ctx context.Context, report cciptypes.CommitStoreReport) ([]byte, error) { + return p.dstCommitStoreReader.EncodeCommitReport(ctx, report) +} + +// GasPriceEstimator constructs a gas price estimator on the source relayer +func (p *ProviderProxyCommitStoreReader) GasPriceEstimator(ctx context.Context) (cciptypes.GasPriceEstimatorCommit, error) { + return p.srcCommitStoreReader.GasPriceEstimator(ctx) +} + +func (p *ProviderProxyCommitStoreReader) GetAcceptedCommitReportsGteTimestamp(ctx context.Context, ts time.Time, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { + return p.dstCommitStoreReader.GetAcceptedCommitReportsGteTimestamp(ctx, ts, confirmations) +} + +func (p *ProviderProxyCommitStoreReader) GetCommitReportMatchingSeqNum(ctx context.Context, seqNum uint64, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { + return p.dstCommitStoreReader.GetCommitReportMatchingSeqNum(ctx, seqNum, confirmations) +} + +func (p *ProviderProxyCommitStoreReader) GetCommitStoreStaticConfig(ctx context.Context) (cciptypes.CommitStoreStaticConfig, error) { + return p.dstCommitStoreReader.GetCommitStoreStaticConfig(ctx) +} + +func (p *ProviderProxyCommitStoreReader) GetExpectedNextSequenceNumber(ctx context.Context) (uint64, error) { + return p.dstCommitStoreReader.GetExpectedNextSequenceNumber(ctx) +} + +func (p *ProviderProxyCommitStoreReader) GetLatestPriceEpochAndRound(ctx context.Context) (uint64, error) { + return p.dstCommitStoreReader.GetLatestPriceEpochAndRound(ctx) +} + +func (p *ProviderProxyCommitStoreReader) IsBlessed(ctx context.Context, root [32]byte) (bool, error) { + return p.dstCommitStoreReader.IsBlessed(ctx, root) +} + +func (p *ProviderProxyCommitStoreReader) IsDestChainHealthy(ctx context.Context) (bool, error) { + return p.dstCommitStoreReader.IsDestChainHealthy(ctx) +} + +func (p *ProviderProxyCommitStoreReader) IsDown(ctx context.Context) (bool, error) { + return p.dstCommitStoreReader.IsDown(ctx) +} + +func (p *ProviderProxyCommitStoreReader) OffchainConfig(ctx context.Context) (cciptypes.CommitOffchainConfig, error) { + return p.srcCommitStoreReader.OffchainConfig(ctx) +} + +func (p *ProviderProxyCommitStoreReader) VerifyExecutionReport(ctx context.Context, report cciptypes.ExecReport) (bool, error) { + return p.dstCommitStoreReader.VerifyExecutionReport(ctx, report) +} + +// SetGasEstimator is invalid on ProviderProxyCommitStoreReader. The provider based impl's do not have SetGasEstimator +// defined, so this serves no purpose other than satisfying an interface. +func (p *ProviderProxyCommitStoreReader) SetGasEstimator(ctx context.Context, gpe gas.EvmFeeEstimator) error { + return fmt.Errorf("invalid usage of ProviderProxyCommitStoreReader") +} + +// SetSourceMaxGasPrice is invalid on ProviderProxyCommitStoreReader. The provider based impl's do not have SetSourceMaxGasPrice +// defined, so this serves no purpose other than satisfying an interface. +func (p *ProviderProxyCommitStoreReader) SetSourceMaxGasPrice(ctx context.Context, sourceMaxGasPrice *big.Int) error { + return fmt.Errorf("invalid usage of ProviderProxyCommitStoreReader") +} + +func (p *ProviderProxyCommitStoreReader) Close() error { + return multierr.Append(p.srcCommitStoreReader.Close(), p.dstCommitStoreReader.Close()) +} diff --git a/core/services/relay/evm/ccip.go b/core/services/relay/evm/ccip.go new file mode 100644 index 0000000000..34a732e145 --- /dev/null +++ b/core/services/relay/evm/ccip.go @@ -0,0 +1,205 @@ +package evm + +import ( + "context" + "fmt" + "math/big" + "time" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "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" + ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "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) +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 +} + +func NewIncompleteSourceCommitStoreReader(estimator gas.EvmFeeEstimator, sourceMaxGasPrice *big.Int) *IncompleteSourceCommitStoreReader { + return &IncompleteSourceCommitStoreReader{ + estimator: estimator, + sourceMaxGasPrice: sourceMaxGasPrice, + } +} + +func (i *IncompleteSourceCommitStoreReader) ChangeConfig(ctx context.Context, onchainConfig []byte, offchainConfig []byte) (cciptypes.Address, error) { + onchainConfigParsed, err := abihelpers.DecodeAbiStruct[ccip.CommitOnchainConfig](onchainConfig) + if err != nil { + return "", err + } + + offchainConfigParsed, err := ccipconfig.DecodeOffchainConfig[ccip.JSONCommitOffchainConfigV1_2_0](offchainConfig) + if err != nil { + return "", err + } + + i.gasPriceEstimator = prices.NewDAGasPriceEstimator( + i.estimator, + i.sourceMaxGasPrice, + int64(offchainConfigParsed.ExecGasPriceDeviationPPB), + int64(offchainConfigParsed.DAGasPriceDeviationPPB), + ) + i.offchainConfig = ccip.NewCommitOffchainConfig( + offchainConfigParsed.ExecGasPriceDeviationPPB, + offchainConfigParsed.GasPriceHeartBeat.Duration(), + offchainConfigParsed.TokenPriceDeviationPPB, + offchainConfigParsed.TokenPriceHeartBeat.Duration(), + offchainConfigParsed.InflightCacheExpiry.Duration(), + offchainConfigParsed.PriceReportingDisabled, + ) + + return cciptypes.Address(onchainConfigParsed.PriceRegistry.String()), nil +} + +func (i *IncompleteSourceCommitStoreReader) DecodeCommitReport(ctx context.Context, report []byte) (cciptypes.CommitStoreReport, error) { + return cciptypes.CommitStoreReport{}, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) EncodeCommitReport(ctx context.Context, report cciptypes.CommitStoreReport) ([]byte, error) { + return []byte{}, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +// GasPriceEstimator returns an ExecGasPriceEstimator to satisfy the GasPriceEstimatorCommit interface, +// with deviationPPB values hardcoded to 0 when this implementation is first constructed. +// When ChangeConfig is called, another call to this method must be made to fetch a GasPriceEstimator with updated values +func (i *IncompleteSourceCommitStoreReader) GasPriceEstimator(ctx context.Context) (cciptypes.GasPriceEstimatorCommit, error) { + return i.gasPriceEstimator, nil +} + +func (i *IncompleteSourceCommitStoreReader) GetAcceptedCommitReportsGteTimestamp(ctx context.Context, ts time.Time, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { + return nil, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) GetCommitReportMatchingSeqNum(ctx context.Context, seqNum uint64, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { + return nil, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) GetCommitStoreStaticConfig(ctx context.Context) (cciptypes.CommitStoreStaticConfig, error) { + return cciptypes.CommitStoreStaticConfig{}, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) GetExpectedNextSequenceNumber(ctx context.Context) (uint64, error) { + return 0, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) GetLatestPriceEpochAndRound(ctx context.Context) (uint64, error) { + return 0, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) IsBlessed(ctx context.Context, root [32]byte) (bool, error) { + return false, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) IsDestChainHealthy(ctx context.Context) (bool, error) { + return false, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) IsDown(ctx context.Context) (bool, error) { + return false, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) OffchainConfig(ctx context.Context) (cciptypes.CommitOffchainConfig, error) { + return i.offchainConfig, nil +} + +func (i *IncompleteSourceCommitStoreReader) VerifyExecutionReport(ctx context.Context, report cciptypes.ExecReport) (bool, error) { + return false, fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +func (i *IncompleteSourceCommitStoreReader) Close() error { + return fmt.Errorf("invalid usage of IncompleteSourceCommitStoreReader") +} + +// IncompleteDestCommitStoreReader is an implementation of CommitStoreReader with all valid methods except +// GasPriceEstimator, ChangeConfig, and OffchainConfig. +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) + if err != nil { + return nil, err + } + + return &IncompleteDestCommitStoreReader{ + cs: cs, + }, nil +} + +func (i *IncompleteDestCommitStoreReader) ChangeConfig(ctx context.Context, onchainConfig []byte, offchainConfig []byte) (cciptypes.Address, error) { + return "", fmt.Errorf("invalid usage of IncompleteDestCommitStoreReader") +} + +func (i *IncompleteDestCommitStoreReader) DecodeCommitReport(ctx context.Context, report []byte) (cciptypes.CommitStoreReport, error) { + return i.cs.DecodeCommitReport(ctx, report) +} + +func (i *IncompleteDestCommitStoreReader) EncodeCommitReport(ctx context.Context, report cciptypes.CommitStoreReport) ([]byte, error) { + return i.cs.EncodeCommitReport(ctx, report) +} + +func (i *IncompleteDestCommitStoreReader) GasPriceEstimator(ctx context.Context) (cciptypes.GasPriceEstimatorCommit, error) { + return nil, fmt.Errorf("invalid usage of IncompleteDestCommitStoreReader") +} + +func (i *IncompleteDestCommitStoreReader) GetAcceptedCommitReportsGteTimestamp(ctx context.Context, ts time.Time, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { + return i.cs.GetAcceptedCommitReportsGteTimestamp(ctx, ts, confirmations) +} + +func (i *IncompleteDestCommitStoreReader) GetCommitReportMatchingSeqNum(ctx context.Context, seqNum uint64, confirmations int) ([]cciptypes.CommitStoreReportWithTxMeta, error) { + return i.cs.GetCommitReportMatchingSeqNum(ctx, seqNum, confirmations) +} + +func (i *IncompleteDestCommitStoreReader) GetCommitStoreStaticConfig(ctx context.Context) (cciptypes.CommitStoreStaticConfig, error) { + return i.cs.GetCommitStoreStaticConfig(ctx) +} + +func (i *IncompleteDestCommitStoreReader) GetExpectedNextSequenceNumber(ctx context.Context) (uint64, error) { + return i.cs.GetExpectedNextSequenceNumber(ctx) +} + +func (i *IncompleteDestCommitStoreReader) GetLatestPriceEpochAndRound(ctx context.Context) (uint64, error) { + return i.cs.GetLatestPriceEpochAndRound(ctx) +} + +func (i *IncompleteDestCommitStoreReader) IsBlessed(ctx context.Context, root [32]byte) (bool, error) { + return i.cs.IsBlessed(ctx, root) +} + +func (i *IncompleteDestCommitStoreReader) IsDestChainHealthy(ctx context.Context) (bool, error) { + return i.cs.IsDestChainHealthy(ctx) +} + +func (i *IncompleteDestCommitStoreReader) IsDown(ctx context.Context) (bool, error) { + return i.cs.IsDown(ctx) +} + +func (i *IncompleteDestCommitStoreReader) OffchainConfig(ctx context.Context) (cciptypes.CommitOffchainConfig, error) { + return cciptypes.CommitOffchainConfig{}, fmt.Errorf("invalid usage of IncompleteDestCommitStoreReader") +} + +func (i *IncompleteDestCommitStoreReader) VerifyExecutionReport(ctx context.Context, report cciptypes.ExecReport) (bool, error) { + return i.cs.VerifyExecutionReport(ctx, report) +} + +func (i *IncompleteDestCommitStoreReader) Close() error { + return i.cs.Close() +} diff --git a/core/services/relay/evm/commit_provider.go b/core/services/relay/evm/commit_provider.go index cccf6b0276..f2a25842f0 100644 --- a/core/services/relay/evm/commit_provider.go +++ b/core/services/relay/evm/commit_provider.go @@ -22,10 +22,12 @@ var _ commontypes.CCIPCommitProvider = (*SrcCommitProvider)(nil) var _ commontypes.CCIPCommitProvider = (*DstCommitProvider)(nil) type SrcCommitProvider struct { - lggr logger.Logger - startBlock uint64 - client client.Client - lp logpoller.LogPoller + lggr logger.Logger + startBlock uint64 + client client.Client + lp logpoller.LogPoller + estimator gas.EvmFeeEstimator + maxGasPrice *big.Int } func NewSrcCommitProvider( @@ -33,12 +35,16 @@ func NewSrcCommitProvider( startBlock uint64, client client.Client, lp logpoller.LogPoller, + srcEstimator gas.EvmFeeEstimator, + maxGasPrice *big.Int, ) commontypes.CCIPCommitProvider { return &SrcCommitProvider{ - lggr: lggr, - startBlock: startBlock, - client: client, - lp: lp, + lggr: lggr, + startBlock: startBlock, + client: client, + lp: lp, + estimator: srcEstimator, + maxGasPrice: maxGasPrice, } } @@ -181,11 +187,14 @@ func (P DstCommitProvider) NewPriceGetter(ctx context.Context) (priceGetter ccip } func (P SrcCommitProvider) NewCommitStoreReader(ctx context.Context, commitStoreAddress cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { - return nil, fmt.Errorf("can't construct a commit store reader from one relayer") + commitStoreReader = NewIncompleteSourceCommitStoreReader(P.estimator, P.maxGasPrice) + return } func (P DstCommitProvider) NewCommitStoreReader(ctx context.Context, commitStoreAddress cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { - return nil, fmt.Errorf("can't construct a commit store reader from one relayer") + versionFinder := ccip.NewEvmVersionFinder() + commitStoreReader, err = NewIncompleteDestCommitStoreReader(P.lggr, versionFinder, commitStoreAddress, P.client, P.lp) + return } func (P SrcCommitProvider) NewOnRampReader(ctx context.Context, onRampAddress cciptypes.Address, sourceChainSelector uint64, destChainSelector uint64) (onRampReader cciptypes.OnRampReader, err error) { diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 7203c142f2..cd2f4010b4 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -412,6 +412,8 @@ func (r *Relayer) NewCCIPCommitProvider(rargs commontypes.RelayArgs, pargs commo sourceStartBlock, r.chain.Client(), r.chain.LogPoller(), + r.chain.GasEstimator(), + r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), ), nil } From 45ef889f3087f3862f4dcd7409c9f87b5c0ef06f Mon Sep 17 00:00:00 2001 From: Makram Kamaleddine Date: Mon, 8 Jul 2024 19:08:34 +0300 Subject: [PATCH 53/61] flakey LM test --- .../ocr2/plugins/liquiditymanager/internal/integration_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go b/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go index 2f2e5a3bd9..5701d29375 100644 --- a/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go +++ b/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go @@ -64,6 +64,7 @@ var ( ) func TestLiquidityManager_Integration(t *testing.T) { + t.Skip("flakey test") newTestUniverse(t, 2, false) } From d5ab3e6f646acb9a5153c9222988f71f0931a9c3 Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:34:39 -0700 Subject: [PATCH 54/61] Omit non required contracts (#1158) ## Motivation We don't need price registry for existing deployment ## Solution --- .../ccip-tests/actions/ccip_helpers.go | 46 ++++++++++--------- .../ccip-tests/testsetups/ccip.go | 6 +-- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index e2b9b70871..67dd80d7a9 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -1000,24 +1000,26 @@ func (ccipModule *CCIPCommon) DeployContracts( } // no need to have price registry for existing deployment, we consider that it's already deployed - if ccipModule.PriceRegistry == nil && !ccipModule.ExistingDeployment { - // we will update the price updates later based on source and dest PriceUpdates - ccipModule.PriceRegistry, err = cd.DeployPriceRegistry( - []common.Address{ - common.HexToAddress(ccipModule.FeeToken.Address()), - common.HexToAddress(ccipModule.WrappedNative.Hex()), - }) - if err != nil { - return fmt.Errorf("deploying PriceRegistry shouldn't fail %w", err) - } - err = ccipModule.ChainClient.WaitForEvents() - if err != nil { - return fmt.Errorf("error in waiting for PriceRegistry deployment %w", err) - } - } else { - ccipModule.PriceRegistry, err = cd.NewPriceRegistry(ccipModule.PriceRegistry.EthAddress) - if err != nil { - return fmt.Errorf("getting new PriceRegistry contract shouldn't fail %w", err) + if !ccipModule.ExistingDeployment { + if ccipModule.PriceRegistry == nil { + // we will update the price updates later based on source and dest PriceUpdates + ccipModule.PriceRegistry, err = cd.DeployPriceRegistry( + []common.Address{ + common.HexToAddress(ccipModule.FeeToken.Address()), + common.HexToAddress(ccipModule.WrappedNative.Hex()), + }) + if err != nil { + return fmt.Errorf("deploying PriceRegistry shouldn't fail %w", err) + } + err = ccipModule.ChainClient.WaitForEvents() + if err != nil { + return fmt.Errorf("error in waiting for PriceRegistry deployment %w", err) + } + } else { + ccipModule.PriceRegistry, err = cd.NewPriceRegistry(ccipModule.PriceRegistry.EthAddress) + if err != nil { + return fmt.Errorf("getting new PriceRegistry contract shouldn't fail %w", err) + } } } if ccipModule.MulticallContract == (common.Address{}) && ccipModule.MulticallEnabled { @@ -1210,9 +1212,11 @@ func NewCCIPCommonFromConfig( if err != nil { return nil, err } - newCCIPModule.PriceRegistry, err = newCCIPModule.Deployer.NewPriceRegistry(common.HexToAddress(newCCIPModule.PriceRegistry.Address())) - if err != nil { - return nil, err + if newCCIPModule.PriceRegistry != nil { + newCCIPModule.PriceRegistry, err = newCCIPModule.Deployer.NewPriceRegistry(common.HexToAddress(newCCIPModule.PriceRegistry.Address())) + if err != nil { + return nil, err + } } newCCIPModule.Router, err = newCCIPModule.Deployer.NewRouter(common.HexToAddress(newCCIPModule.Router.Address())) if err != nil { diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index 39e52164bc..68ef532ea2 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -1240,9 +1240,9 @@ func (o *CCIPTestSetUpOutputs) CreateEnvironment( func createEnvironmentConfig(t *testing.T, envName string, testConfig *CCIPTestConfig, reportPath string) *environment.Config { envConfig := &environment.Config{ - NamespacePrefix: envName, - Test: t, - PreventPodEviction: true, + NamespacePrefix: envName, + Test: t, + // PreventPodEviction: true, //TODO: enable this once we have a way to handle pod eviction } if pointer.GetBool(testConfig.TestGroupInput.StoreLaneConfig) { envConfig.ReportPath = reportPath From 6ac3cddfbcb311c82cdd2a33db7c6b6605d87d0d Mon Sep 17 00:00:00 2001 From: Ryan Stout Date: Tue, 9 Jul 2024 02:13:29 -0700 Subject: [PATCH 55/61] Commit NewReportingPlugin retries on error (#1160) Previously, if there was an error when starting the Commit Pluging (i.e. calling NewReportingPlugin), the Commit Plugin would remain in a non-started state. Now, NewReportingPlugin will retry until the Commit Plugin successfully starts. ## Motivation ## Solution Co-authored-by: dimitris --- .changeset/red-balloons-repeat.md | 5 + .../ocr2/plugins/ccip/ccipcommit/factory.go | 79 +++++++++----- .../plugins/ccip/ccipcommit/factory_test.go | 100 ++++++++++++++++++ .../plugins/ccip/ccipcommit/initializers.go | 26 +++-- .../ocr2/plugins/ccip/ccipcommit/ocr2.go | 3 +- 5 files changed, 174 insertions(+), 39 deletions(-) create mode 100644 .changeset/red-balloons-repeat.md create mode 100644 core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go diff --git a/.changeset/red-balloons-repeat.md b/.changeset/red-balloons-repeat.md new file mode 100644 index 0000000000..674cae9602 --- /dev/null +++ b/.changeset/red-balloons-repeat.md @@ -0,0 +1,5 @@ +--- +"ccip": patch +--- + +Commit NewReportingPlugin retries on error diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go index 95d6398f56..648f62a23a 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/factory.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/factory.go @@ -9,6 +9,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcommon" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" @@ -64,40 +65,60 @@ func (rf *CommitReportingPluginFactory) UpdateDynamicReaders(ctx context.Context return nil } -// NewReportingPlugin returns the ccip CommitReportingPlugin and satisfies the ReportingPluginFactory interface. +type reportingPluginAndInfo struct { + plugin types.ReportingPlugin + pluginInfo types.ReportingPluginInfo +} + +// NewReportingPlugin registers a new ReportingPlugin func (rf *CommitReportingPluginFactory) NewReportingPlugin(config types.ReportingPluginConfig) (types.ReportingPlugin, types.ReportingPluginInfo, error) { - ctx := context.Background() // todo: consider adding some timeout + initialRetryDelay := rf.config.newReportingPluginRetryConfig.InitialDelay + maxDelay := rf.config.newReportingPluginRetryConfig.MaxDelay - destPriceReg, err := rf.config.commitStore.ChangeConfig(ctx, config.OnchainConfig, config.OffchainConfig) + pluginAndInfo, err := ccipcommon.RetryUntilSuccess(rf.NewReportingPluginFn(config), initialRetryDelay, maxDelay) if err != nil { return nil, types.ReportingPluginInfo{}, err } + return pluginAndInfo.plugin, pluginAndInfo.pluginInfo, err +} - priceRegEvmAddr, err := ccipcalc.GenericAddrToEvm(destPriceReg) - if err != nil { - return nil, types.ReportingPluginInfo{}, err - } - if err = rf.UpdateDynamicReaders(ctx, priceRegEvmAddr); err != nil { - return nil, types.ReportingPluginInfo{}, err - } +// NewReportingPluginFn implements the NewReportingPlugin logic. It is defined as a function so that it can easily be +// retried via RetryUntilSuccess. NewReportingPlugin must return successfully in order for the Commit plugin to +// function, hence why we can only keep retrying it until it succeeds. +func (rf *CommitReportingPluginFactory) NewReportingPluginFn(config types.ReportingPluginConfig) func() (reportingPluginAndInfo, error) { + return func() (reportingPluginAndInfo, error) { + ctx := context.Background() // todo: consider adding some timeout - pluginOffChainConfig, err := rf.config.commitStore.OffchainConfig(ctx) - if err != nil { - return nil, types.ReportingPluginInfo{}, err - } + destPriceReg, err := rf.config.commitStore.ChangeConfig(ctx, config.OnchainConfig, config.OffchainConfig) + if err != nil { + return reportingPluginAndInfo{}, err + } - gasPriceEstimator, err := rf.config.commitStore.GasPriceEstimator(ctx) - if err != nil { - return nil, types.ReportingPluginInfo{}, err - } + priceRegEvmAddr, err := ccipcalc.GenericAddrToEvm(destPriceReg) + if err != nil { + return reportingPluginAndInfo{}, err + } + if err = rf.UpdateDynamicReaders(ctx, priceRegEvmAddr); err != nil { + return reportingPluginAndInfo{}, err + } - err = rf.config.priceService.UpdateDynamicConfig(ctx, gasPriceEstimator, rf.destPriceRegReader) - if err != nil { - return nil, types.ReportingPluginInfo{}, err - } + pluginOffChainConfig, err := rf.config.commitStore.OffchainConfig(ctx) + if err != nil { + return reportingPluginAndInfo{}, err + } + + gasPriceEstimator, err := rf.config.commitStore.GasPriceEstimator(ctx) + if err != nil { + return reportingPluginAndInfo{}, err + } - lggr := rf.config.lggr.Named("CommitReportingPlugin") - return &CommitReportingPlugin{ + err = rf.config.priceService.UpdateDynamicConfig(ctx, gasPriceEstimator, rf.destPriceRegReader) + if err != nil { + return reportingPluginAndInfo{}, err + } + + lggr := rf.config.lggr.Named("CommitReportingPlugin") + plugin := &CommitReportingPlugin{ sourceChainSelector: rf.config.sourceChainSelector, sourceNative: rf.config.sourceNative, onRampReader: rf.config.onRampReader, @@ -112,8 +133,9 @@ func (rf *CommitReportingPluginFactory) NewReportingPlugin(config types.Reportin metricsCollector: rf.config.metricsCollector, chainHealthcheck: rf.config.chainHealthcheck, priceService: rf.config.priceService, - }, - types.ReportingPluginInfo{ + } + + pluginInfo := types.ReportingPluginInfo{ Name: "CCIPCommit", UniqueReports: false, // See comment in CommitStore constructor. Limits: types.ReportingPluginLimits{ @@ -121,5 +143,8 @@ func (rf *CommitReportingPluginFactory) NewReportingPlugin(config types.Reportin MaxObservationLength: ccip.MaxObservationLength, MaxReportLength: MaxCommitReportLength, }, - }, nil + } + + return reportingPluginAndInfo{plugin, pluginInfo}, nil + } } diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go b/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go new file mode 100644 index 0000000000..825026bd17 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/ccipcommit/factory_test.go @@ -0,0 +1,100 @@ +package ccipcommit + +import ( + "errors" + "testing" + "time" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + + "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + ccipdataprovidermocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/ccipdataprovider/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" + dbMocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdb/mocks" +) + +// Assert that NewReportingPlugin keeps retrying until it succeeds. +// +// NewReportingPlugin makes several calls (e.g. CommitStoreReader.ChangeConfig) that can fail. We use mocks to cause the +// first call to each of these functions to fail, then all subsequent calls succeed. We assert that NewReportingPlugin +// retries a sufficient number of times to get through the transient errors and eventually succeed. +func TestNewReportingPluginRetriesUntilSuccess(t *testing.T) { + commitConfig := CommitPluginStaticConfig{} + + // For this unit test, ensure that there is no delay between retries + commitConfig.newReportingPluginRetryConfig = ccipdata.RetryConfig{ + InitialDelay: 0 * time.Nanosecond, + MaxDelay: 0 * time.Nanosecond, + } + + // Set up the OffRampReader mock + mockCommitStore := new(mocks.CommitStoreReader) + + // The first call is set to return an error, the following calls return a nil error + mockCommitStore. + On("ChangeConfig", mock.Anything, mock.Anything, mock.Anything). + Return(ccip.Address(""), errors.New("")). + Once() + mockCommitStore. + On("ChangeConfig", mock.Anything, mock.Anything, mock.Anything). + Return(ccip.Address("0x7c6e4F0BDe29f83BC394B75a7f313B7E5DbD2d77"), nil). + Times(5) + + mockCommitStore. + On("OffchainConfig", mock.Anything). + Return(ccip.CommitOffchainConfig{}, errors.New("")). + Once() + mockCommitStore. + On("OffchainConfig", mock.Anything). + Return(ccip.CommitOffchainConfig{}, nil). + Times(3) + + mockCommitStore. + On("GasPriceEstimator", mock.Anything). + Return(nil, errors.New("")). + Once() + mockCommitStore. + On("GasPriceEstimator", mock.Anything). + Return(nil, nil). + Times(2) + + commitConfig.commitStore = mockCommitStore + + mockPriceService := new(dbMocks.PriceService) + + mockPriceService. + On("UpdateDynamicConfig", mock.Anything, mock.Anything, mock.Anything). + Return(errors.New("")). + Once() + mockPriceService. + On("UpdateDynamicConfig", mock.Anything, mock.Anything, mock.Anything). + Return(nil) + + commitConfig.priceService = mockPriceService + + priceRegistryProvider := new(ccipdataprovidermocks.PriceRegistry) + priceRegistryProvider. + On("NewPriceRegistryReader", mock.Anything, mock.Anything). + Return(nil, errors.New("")). + Once() + priceRegistryProvider. + On("NewPriceRegistryReader", mock.Anything, mock.Anything). + Return(nil, nil). + Once() + commitConfig.priceRegistryProvider = priceRegistryProvider + + commitConfig.lggr, _ = logger.NewLogger() + + factory := NewCommitReportingPluginFactory(commitConfig) + reportingConfig := types.ReportingPluginConfig{} + reportingConfig.OnchainConfig = []byte{1, 2, 3} + reportingConfig.OffchainConfig = []byte{1, 2, 3} + + // Assert that NewReportingPlugin succeeds despite many transient internal failures (mocked out above) + _, _, err := factory.NewReportingPlugin(reportingConfig) + assert.Equal(t, nil, err) +} diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go index 0d8a5414dc..729d8ca5c1 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "strings" + "time" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/pricegetter" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" @@ -43,6 +44,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" ) +var defaultNewReportingPluginRetryConfig = ccipdata.RetryConfig{InitialDelay: time.Second, MaxDelay: 5 * time.Minute} + func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider commontypes.CCIPCommitProvider, dstProvider commontypes.CCIPCommitProvider, chainSet legacyevm.LegacyChainContainer, jb job.Job, lggr logger.Logger, pr pipeline.Runner, argsNoPlugin libocr2.OCR2OracleArgs, new bool, sourceChainID int64, destChainID int64, logError func(string)) ([]job.ServiceCtx, error) { spec := jb.OCR2OracleSpec @@ -171,17 +174,18 @@ func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider c ) wrappedPluginFactory := NewCommitReportingPluginFactory(CommitPluginStaticConfig{ - lggr: lggr, - onRampReader: onRampReader, - sourceChainSelector: staticConfig.SourceChainSelector, - sourceNative: sourceNative, - offRamp: offRampReader, - commitStore: commitStoreReader, - destChainSelector: staticConfig.ChainSelector, - priceRegistryProvider: ccip.NewChainAgnosticPriceRegistry(dstProvider), - metricsCollector: metricsCollector, - chainHealthcheck: chainHealthCheck, - priceService: priceService, + lggr: lggr, + newReportingPluginRetryConfig: defaultNewReportingPluginRetryConfig, + onRampReader: onRampReader, + sourceChainSelector: staticConfig.SourceChainSelector, + sourceNative: sourceNative, + offRamp: offRampReader, + commitStore: commitStoreReader, + destChainSelector: staticConfig.ChainSelector, + priceRegistryProvider: ccip.NewChainAgnosticPriceRegistry(dstProvider), + metricsCollector: metricsCollector, + chainHealthcheck: chainHealthCheck, + priceService: priceService, }) argsNoPlugin.ReportingPluginFactory = promwrapper.NewPromFactory(wrappedPluginFactory, "CCIPCommit", jb.OCR2OracleSpec.Relay, big.NewInt(0).SetInt64(destChainID)) argsNoPlugin.Logger = commonlogger.NewOCRWrapper(commitLggr, true, logError) diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go index 3c96940b8d..2f0fc4e795 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2.go @@ -50,7 +50,8 @@ type update struct { } type CommitPluginStaticConfig struct { - lggr logger.Logger + lggr logger.Logger + newReportingPluginRetryConfig ccipdata.RetryConfig // Source onRampReader ccipdata.OnRampReader sourceChainSelector uint64 From 7d7b54aad371d2da51449227503aa198475918b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Evaldas=20Lato=C5=A1kinas?= <34982762+elatoskinas@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:49:37 +0200 Subject: [PATCH 56/61] MultiOnRamp - family-agnostic messages (#1140) ## Motivation * Converts the `EVM2EVMMultiOnRamp` to an `EVM2Any` family-agnostic ramp to support non-EVM use-cases from a single multi-onramp. * Collapses `sourceTokenData` + `tokenAmounts` into one `RampTokenAmount` array (simplification to no longer require encoding / decoding on-chain) ## Solution * Message format changes: convert `EVM2EVMMessage` to `EVM2AnyRampMessage`, which contains a more generic `receiver` target and stores the family-specific args as bytes * Note: `hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage)` - the messages are now asymmetric * Note: `EVM2AnyRampMessage.messageId = hash(EVM2AnyRampMessage)`, but `messageId != hash(Any2EVMRampMessage)` due to the message asymmetry * Add a `familyTag` to the dest chain config, to group multiple chains under one family to perform validations * Convert `extraArgs` to bytes, implement conditional flows to retrieve EVM-specific fields * Add `RampTokenAmount` which is constructed from `Client.EVMTokenAmount` on the OnRamp. The struct unrolls `SourceTokenData` and `EVMTokenAmount` into one struct, no longer requiring additional decoding * Out-of-scope: moving family-specific fee & validation logic to `PriceRegistry` - to be done in next PR --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Co-authored-by: Makram --- contracts/gas-snapshots/ccip.gas-snapshot | 456 +++++++++--------- .../src/v0.8/ccip/libraries/Internal.sol | 81 +++- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 38 +- .../v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol | 185 ++++--- .../src/v0.8/ccip/test/NonceManager.t.sol | 33 +- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 17 +- .../helpers/EVM2EVMMultiOffRampHelper.sol | 15 +- .../test/helpers/EVM2EVMMultiOnRampHelper.sol | 15 +- .../v0.8/ccip/test/helpers/MessageHasher.sol | 15 +- .../test/offRamp/EVM2EVMMultiOffRamp.t.sol | 182 +++---- .../offRamp/EVM2EVMMultiOffRampSetup.t.sol | 51 +- .../ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol | 172 ++++++- .../test/onRamp/EVM2EVMMultiOnRampSetup.t.sol | 58 ++- .../evm_2_evm_multi_offramp.go | 24 +- .../evm_2_evm_multi_onramp.go | 45 +- .../message_hasher/message_hasher.go | 81 ++-- ...rapper-dependency-versions-do-not-edit.txt | 6 +- .../ocr3/plugins/ccipevm/msghasher.go | 27 +- .../ocr3/plugins/ccipevm/msghasher_test.go | 39 +- 19 files changed, 876 insertions(+), 664 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 54443aa4e2..d76d62a606 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -116,213 +116,229 @@ CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) DefensiveExampleTest:test_Recovery() (gas: 424253) E2E:test_E2E_3MessagesSuccess_gas() (gas: 1104821) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38361) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108455) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116907) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460360) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95427) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90249) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105403) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15651) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 12989) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 305737) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 247076) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 162376) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 195244) -EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 150011) -EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 535435) -EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10525) -EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 16096) -EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67080) -EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59630) -EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58710) -EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6574764) -EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 6157992) -EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 108329) -EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 118244) -EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 108372) -EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353646) -EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 161185) -EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136112) -EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136695) -EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 58978) -EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227569) -EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 119611) -EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77537) -EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 209029) -EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6569153) -EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47717) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 6158331) -EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 104384) -EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 100309) -EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 98180) -EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 106890) -EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 98079) -EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 98146) -EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17299) -EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1640074) -EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 350683) -EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 267647) -EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6627625) -EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6210572) -EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 28435) -EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 167667) -EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 151623) -EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6989700) -EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17174) -EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 19548) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 254458) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21806) -EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 206750) -EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50035) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 49556) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 234116) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 90376) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 287302) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 94638) -EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 36249) -EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23921) -EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 462794) -EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 55975) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 37072) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 156143) -EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 36483) -EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 184243) -EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 194605) -EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 49553) -EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 439123) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 256572) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 179039) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 198372) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 262344) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 131587) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 399804) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 67753) -EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 82478) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 546583) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 486844) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 36976) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 534156) -EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 531524) -EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 498454) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 131751) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 160626) -EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3633818) -EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118144) -EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87253) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81957) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27558) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 165891) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 212381) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27086) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 166703) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 512307) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2397801) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 214474) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 215037) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 692864) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 309081) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165102) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 26890) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 63495) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 44612) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 80519) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 185299) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 283897) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11420) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215247) -EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14223) -EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11729) -EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 13885) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55608) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33618) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 242740) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 251403) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 308206) -EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 285105) -EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176538) -EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178609) -EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141470) -EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51507) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 33833) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16646) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigNewPrevOnRampOnExistingChain_Revert() (gas: 30796) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero() (gas: 16696) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput() (gas: 12313) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 174714) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86785) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17084) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12268) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkChainSelectorEqZero_Revert() (gas: 142392) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkTokenEqAddressZero_Revert() (gas: 138007) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 140293) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 145314) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 140360) -EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 4895404) -EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 96382) -EVM2EVMMultiOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 102566) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 125845) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 156591) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 156102) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 156332) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 156357) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 155802) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 35086) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 35347) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38220) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108400) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116868) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460557) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95536) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12460) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90379) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105577) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15716) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13054) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 298930) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 240268) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 158987) +EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189548) +EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 147703) +EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 521990) +EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10456) +EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 15659) +EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67189) +EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59695) +EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58775) +EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6544263) +EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 6127493) +EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 108372) +EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 118374) +EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 108415) +EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353706) +EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 161272) +EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136244) +EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136825) +EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59043) +EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227655) +EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 119676) +EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77602) +EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 209115) +EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6538652) +EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47782) +EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 6127677) +EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 104335) +EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 100260) +EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 98131) +EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 106841) +EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 98030) +EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 98097) +EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17277) +EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1563033) +EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 343670) +EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 260538) +EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6594735) +EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6177684) +EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 27678) +EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 165299) +EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149255) +EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6956810) +EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17151) +EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18413) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249488) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20672) +EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 201787) +EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48860) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48381) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 232668) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 89262) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 278263) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 93485) +EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35083) +EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23910) +EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 451951) +EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54472) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35906) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154363) +EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35317) +EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 181628) +EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 190908) +EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48050) +EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 436547) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 252012) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 174226) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 193899) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259769) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 129695) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 391966) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65914) +EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80970) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 535883) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 480816) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35763) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 520826) +EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 518194) +EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 488330) +EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 128053) +EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 157265) +EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3650714) +EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118188) +EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87407) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75594) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26473) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 163355) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 207956) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26001) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152913) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 507883) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2308282) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 210050) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 210613) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 670625) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 300122) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 160712) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24152) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 59156) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 40402) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 76181) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 179068) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 278906) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11376) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215403) +EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14289) +EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11795) +EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 13951) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55630) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33640) +EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 238383) +EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 247046) +EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 300337) +EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 280699) +EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176601) +EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178672) +EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141533) +EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51505) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16917) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 34341) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16770) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigNewPrevOnRampOnExistingChain_Revert() (gas: 31306) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16842) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput() (gas: 12336) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 177813) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11449) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54003) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44785) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12302) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86917) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13111) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17106) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12290) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkChainSelectorEqZero_Revert() (gas: 143541) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkTokenEqAddressZero_Revert() (gas: 139156) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 141442) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 146463) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 141509) +EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 5447902) +EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsDefault_Success() (gas: 18235) +EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 22580) +EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 19677) +EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 19202) +EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsV1_Success() (gas: 19292) +EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsV2_Success() (gas: 19431) +EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EmptyExtraArgs_Success() (gas: 19657) +EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 105130) +EVM2EVMMultiOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 109612) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 138405) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 169217) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 168640) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 168046) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 168914) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 168275) +EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 31992) EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 27934) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 29913) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 31675) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 110363) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 152538) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 34127) -EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 23037) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 41465) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25882) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 204962) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 231235) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 142548) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 169489) -EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3778765) -EVM2EVMMultiOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 32857) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 44213) -EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 135415) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 281847) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 98476) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 274979) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 124845) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 11969) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 24662) -EVM2EVMMultiOnRamp_getFee:test_DestinationChainNotEnabled_Revert() (gas: 15458) -EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 92893) -EVM2EVMMultiOnRamp_getFee:test_HighGasMessage_Success() (gas: 249487) -EVM2EVMMultiOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 19150) -EVM2EVMMultiOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 97779) -EVM2EVMMultiOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 173747) -EVM2EVMMultiOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 22291) -EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 132322) -EVM2EVMMultiOnRamp_getFee:test_TooManyTokens_Revert() (gas: 20287) -EVM2EVMMultiOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 78672) -EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) -EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35261) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 47297) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35287) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28361) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 129897) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15253) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28169) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21263) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 41222) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28192) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40577) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 31690) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11334) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12934) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11291) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16243) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 60038) -EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97129) +EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidEVMAddressDestToken_Revert() (gas: 3525966) +EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidEVMAddress_Revert() (gas: 32232) +EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 37388) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 38351) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107541) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 152145) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 33678) +EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 23015) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 41487) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25860) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 244399) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 270405) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 152708) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 179642) +EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3821022) +EVM2EVMMultiOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 29961) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 44169) +EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 144163) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 250642) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 107224) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 283983) +EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 126323) +EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 12013) +EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 24974) +EVM2EVMMultiOnRamp_getFee:test_DestinationChainNotEnabled_Revert() (gas: 15422) +EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 102285) +EVM2EVMMultiOnRamp_getFee:test_HighGasMessage_Success() (gas: 258923) +EVM2EVMMultiOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 42468) +EVM2EVMMultiOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95014) +EVM2EVMMultiOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 183629) +EVM2EVMMultiOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 21863) +EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 141949) +EVM2EVMMultiOnRamp_getFee:test_TooManyTokens_Revert() (gas: 17439) +EVM2EVMMultiOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 84431) +EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) +EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 47357) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35335) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28409) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130389) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15255) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28217) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21265) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 41270) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28240) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40601) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 31720) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11378) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12978) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11335) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16331) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 60104) +EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10851) +EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6711) +EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6417) +EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97211) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38076) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 108251) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_revert_Revert() (gas: 116792) @@ -402,10 +418,6 @@ EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 146778) EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162464) EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16667) EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197660) -EVM2EVMOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11471) -EVM2EVMOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54025) -EVM2EVMOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44807) -EVM2EVMOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12324) EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5635586) EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35788) EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99488) @@ -637,22 +649,22 @@ 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) -MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1435700) +MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1457196) 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: 255244) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 257899) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 313263) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 295481) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 248932) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236918) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 147192) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 173337) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 217372) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125707) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 120818) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 252899) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 255229) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 308391) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 291386) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 248762) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236748) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 144907) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 185811) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 242327) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125653) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 133309) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122899) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 9068ca3a10..4b6d3daa16 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -58,7 +58,7 @@ library Internal { // The source pool address, abi encoded. 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 pool, abi encoded in the case of EVM chains + // The address of the destination token, abi encoded in the case of EVM chains // 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 @@ -106,7 +106,6 @@ library Internal { bytes32 messageId; // a hash of the message data } - // TODO: create new const for EVM2AnyMessage /// @dev EVM2EVMMessage struct has 13 fields, including 3 variable arrays. /// Each variable array takes 1 more slot to store its length. /// When abi encoded, excluding array contents, @@ -114,11 +113,24 @@ library Internal { /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 17. uint256 public constant MESSAGE_FIXED_BYTES = 32 * 17; - // TODO: create new const for EVM2AnyMessage /// @dev Each token transfer adds 1 EVMTokenAmount and 1 bytes. /// When abiEncoded, each EVMTokenAmount takes 2 slots, each bytes takes 2 slots, excl bytes contents uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 4; + /// @dev Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (data, receiver and tokenAmounts). + /// Each variable array takes 1 more slot to store its length. + /// When abi encoded, excluding array contents, + /// Any2EVMMessage takes up a fixed number of 13 slots, 32 bytes each. + /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 14. + /// The fixed bytes does not cover struct data (this is represented by ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + 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. + /// When abi encoded, each token transfer takes up 7 slots, excl bytes contents. + uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 7; + function _toAny2EVMMessage( EVM2EVMMessage memory original, Client.EVMTokenAmount[] memory destTokenAmounts @@ -167,6 +179,7 @@ library Internal { } bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1"); + bytes32 internal constant EVM_2_ANY_MESSAGE_HASH = keccak256("EVM2AnyMessageHashV1"); /// @dev Used to hash messages for multi-lane family-agnostic OffRamps. /// OnRamp hash(EVM2AnyMessage) != Any2EVMRampMessage.messageId @@ -197,8 +210,31 @@ library Internal { ) ), keccak256(original.data), + keccak256(abi.encode(original.tokenAmounts)) + ) + ); + } + + function _hash(EVM2AnyRampMessage 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, + metadataHash, + keccak256( + abi.encode( + original.sender, + original.receiver, + original.header.sequenceNumber, + original.header.nonce, + original.feeToken, + original.feeTokenAmount + ) + ), + keccak256(original.data), keccak256(abi.encode(original.tokenAmounts)), - keccak256(abi.encode(original.sourceTokenData)) + keccak256(original.extraArgs) ) ); } @@ -246,9 +282,23 @@ 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 + // 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 + // 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 + // 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 header for OnRamp & OffRamp messages. /// The messageId is not expected to match hash(message), since it may originate from another ramp family - // TODO: revisit if destChainSelector is required (likely sufficient to have it implicitly in the commit roots) 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 @@ -266,8 +316,23 @@ 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 - // TODO: revisit collapsing tokenAmounts + sourceTokenData into one struct array - Client.EVMTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer - bytes[] sourceTokenData; // array of token data, one per token + RampTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer } + + /// @notice Family-agnostic message emitted from the OnRamp + /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage) due to encoding & parameter differences + /// messageId = hash(EVM2AnyRampMessage) using the source EVM chain's encoding format + struct EVM2AnyRampMessage { + RampMessageHeader header; // Message header + address sender; // sender address on the source chain + bytes data; // arbitrary data payload supplied by the message sender + bytes receiver; // receiver address on the destination chain + 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 + } + + // bytes4(keccak256("CCIP ChainFamilySelector EVM")) + bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; } diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 08c8086884..9d1664cd66 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -497,12 +497,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0); if (message.tokenAmounts.length > 0) { destTokenAmounts = _releaseOrMintTokens( - message.tokenAmounts, - message.sender, - message.receiver, - message.header.sourceChainSelector, - message.sourceTokenData, - offchainTokenData + message.tokenAmounts, message.sender, message.receiver, message.header.sourceChainSelector, offchainTokenData ); } @@ -787,25 +782,22 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { /// @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 sourceAmount The amount of tokens to be released/minted. + /// @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 sourceTokenData A struct containing the local token address, the source pool address and optional data - /// returned from the source pool. /// @param offchainTokenData Data fetched offchain by the DON. /// @return destTokenAmount local token address with amount function _releaseOrMintSingleToken( - uint256 sourceAmount, + Internal.RampTokenAmount memory sourceTokenAmount, bytes memory originalSender, address receiver, uint64 sourceChainSelector, - Internal.SourceTokenData memory sourceTokenData, 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(sourceTokenData.destTokenAddress); + 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. @@ -827,11 +819,11 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { Pool.ReleaseOrMintInV1({ originalSender: originalSender, receiver: receiver, - amount: sourceAmount, + amount: sourceTokenAmount.amount, localToken: localToken, remoteChainSelector: sourceChainSelector, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, + sourcePoolAddress: sourceTokenAmount.sourcePoolAddress, + sourcePoolData: sourceTokenAmount.extraData, offchainTokenData: offchainTokenData }) ), @@ -866,34 +858,26 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base { } /// @notice Uses pools to release or mint a number of different tokens to a receiver address. - /// @param sourceTokenAmounts List of tokens and amount values to be released/minted. + /// @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 encodedSourceTokenData Encoded source token data, decoding to Internal.SourceTokenData /// @param offchainTokenData Array of token data fetched offchain by the DON. /// @return destTokenAmounts local token addresses with amounts /// @dev This function wrappes 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( - Client.EVMTokenAmount[] memory sourceTokenAmounts, + Internal.RampTokenAmount[] memory sourceTokenAmounts, bytes memory originalSender, address receiver, uint64 sourceChainSelector, - bytes[] memory encodedSourceTokenData, bytes[] memory offchainTokenData ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { - // Creating a copy is more gas efficient than initializing a new array. - destTokenAmounts = sourceTokenAmounts; + destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { destTokenAmounts[i] = _releaseOrMintSingleToken( - sourceTokenAmounts[i].amount, - originalSender, - receiver, - sourceChainSelector, - abi.decode(encodedSourceTokenData[i], (Internal.SourceTokenData)), - offchainTokenData[i] + sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] ); } diff --git a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol index 130309a9a6..bcb7a74c5f 100644 --- a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol @@ -56,7 +56,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre ); event TokenTransferFeeConfigDeleted(uint64 indexed destChainSelector, address indexed token); /// RMN depends on this event, if changing, please notify the RMN maintainers. - event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2EVMMessage message); + event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); event DestChainDynamicConfigUpdated(uint64 indexed destChainSelector, DestChainDynamicConfig dynamicConfig); @@ -140,7 +140,8 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre uint64 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. + bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. + bytes4 chainFamilySelector; // ──────────────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. } /// @dev Struct to hold the configs for a destination chain @@ -249,7 +250,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre address originalSender ) external returns (bytes32) { DestChainConfig storage destChainConfig = s_destChainConfig[destChainSelector]; - Internal.EVM2EVMMessage memory newMessage = + Internal.EVM2AnyRampMessage memory newMessage = _generateNewMessage(destChainConfig, destChainSelector, message, feeTokenAmount, originalSender); // Lock the tokens as last step. TokenPools may not always be trusted. @@ -287,26 +288,25 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre ) { revert SourceTokenDataTooLarge(tokenAndAmount.token); } - // We validate the token address to ensure it is a valid EVM address - Internal._validateEVMAddress(poolReturnData.destTokenAddress); - - newMessage.sourceTokenData[i] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(sourcePool), - destTokenAddress: poolReturnData.destTokenAddress, - extraData: poolReturnData.destPoolData - }) - ); + + _validateDestFamilyAddress(destChainConfig.dynamicConfig.chainFamilySelector, poolReturnData.destTokenAddress); + + newMessage.tokenAmounts[i] = Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(sourcePool), + destTokenAddress: poolReturnData.destTokenAddress, + extraData: poolReturnData.destPoolData, + amount: tokenAndAmount.amount + }); } // Hash only after the sourceTokenData has been set - newMessage.messageId = Internal._hash(newMessage, destChainConfig.metadataHash); + newMessage.header.messageId = Internal._hash(newMessage, destChainConfig.metadataHash); // 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); - return newMessage.messageId; + return newMessage.header.messageId; } /// @notice Helper function to relieve stack pressure from `forwardFromRouter` @@ -321,7 +321,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre Client.EVM2AnyMessage calldata message, uint256 feeTokenAmount, address originalSender - ) internal returns (Internal.EVM2EVMMessage memory) { + ) internal returns (Internal.EVM2AnyRampMessage memory) { if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. if (originalSender == address(0)) revert RouterMustSetOriginalSender(); @@ -329,13 +329,10 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre if (msg.sender != s_dynamicConfig.router) revert MustBeCalledByRouter(); if (!destChainConfig.dynamicConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); - Client.EVMExtraArgsV2 memory extraArgs = - _extraArgsFromBytes(message.extraArgs, destChainConfig.dynamicConfig.defaultTxGasLimit); // Validate the message with various checks uint256 numberOfTokens = message.tokenAmounts.length; - _validateMessage( - destChainSelector, message.data.length, extraArgs.gasLimit, numberOfTokens, extraArgs.allowOutOfOrderExecution - ); + // TODO: optimization - consider removing this call, since the Router calls into getFee -> _validateMessage + _validateMessage(destChainSelector, message.data.length, numberOfTokens, message.receiver); // Only check token value if there are tokens if (numberOfTokens > 0) { @@ -361,48 +358,95 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre if (msgFeeJuels > i_maxFeeJuelsPerMsg) revert MessageFeeTooHigh(msgFeeJuels, i_maxFeeJuelsPerMsg); - // We need the next available sequence number so we increment before we use the value - return Internal.EVM2EVMMessage({ - sourceChainSelector: i_chainSelector, - sender: originalSender, - // EVM destination addresses should be abi encoded and therefore always 32 bytes long - // Not duplicately validated in `getFee`. Invalid address is uncommon, gas cost outweighs UX gain. - receiver: Internal._validateEVMAddress(message.receiver), - sequenceNumber: ++destChainConfig.sequenceNumber, - gasLimit: extraArgs.gasLimit, - strict: false, + // NOTE: when supporting non-EVM chains, revisit this and parse non-EVM args + // Assumes strict ordering, unless the chain is of the EVM family and the extra args indicate out of order execution + uint64 nonce = 0; + if (!_parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig.dynamicConfig).allowOutOfOrderExecution) { // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we // may block ordered message nonces, which is not what we want. - nonce: extraArgs.allowOutOfOrderExecution - ? 0 - : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender), + nonce = INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender); + } + + Internal.EVM2AnyRampMessage memory rampMessage = Internal.EVM2AnyRampMessage({ + header: Internal.RampMessageHeader({ + // Should be generated after the message is complete + messageId: "", + sourceChainSelector: i_chainSelector, + destChainSelector: destChainSelector, + // We need the next available sequence number so we increment before we use the value + sequenceNumber: ++destChainConfig.sequenceNumber, + nonce: nonce + }), + sender: originalSender, + data: message.data, + extraArgs: _convertParsedExtraArgs(message.extraArgs, destChainConfig.dynamicConfig), + receiver: message.receiver, feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, - data: message.data, - tokenAmounts: message.tokenAmounts, - sourceTokenData: new bytes[](numberOfTokens), // will be populated below - messageId: "" + tokenAmounts: new Internal.RampTokenAmount[](numberOfTokens) // should be populated after generation }); + + return rampMessage; + } + + /// @dev Parses extraArgs with dest chain config family tag validation, and re-encodes the args to the latest arguments version. + /// Used to generate an EVM2AnyRampMessage with the accurate representation of the parsed extraArgs. + /// @param extraArgs The extra args bytes + /// @param destChainDynamicConfig Dest chain config to validate against + /// @return encodedExtraArgs the parsed & encoded extra args + function _convertParsedExtraArgs( + bytes calldata extraArgs, + DestChainDynamicConfig memory destChainDynamicConfig + ) internal pure returns (bytes memory encodedExtraArgs) { + bytes4 chainFamilySelector = destChainDynamicConfig.chainFamilySelector; + if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { + return abi.encode(_parseEVMExtraArgsFromBytes(extraArgs, destChainDynamicConfig)); + } + // Invalid chain family selectors cannot be configured - ignore invalid cases + return encodedExtraArgs; + } + + /// @dev Convert the extra args bytes into a struct with validations against the dest chain config + /// @param extraArgs The extra args bytes + /// @param destChainDynamicConfig Dest chain config to validate against + /// @return EVMExtraArgs the extra args struct (latest version) + function _parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + DestChainDynamicConfig memory destChainDynamicConfig + ) internal pure returns (Client.EVMExtraArgsV2 memory) { + Client.EVMExtraArgsV2 memory evmExtraArgs = + _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, destChainDynamicConfig.defaultTxGasLimit); + + if (evmExtraArgs.gasLimit > uint256(destChainDynamicConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); + if (destChainDynamicConfig.enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { + revert ExtraArgOutOfOrderExecutionMustBeTrue(); + } + + return evmExtraArgs; } /// @dev Convert the extra args bytes into a struct /// @param extraArgs The extra args bytes - /// @return EVMExtraArgs the extra args struct - function _extraArgsFromBytes( + /// @param defaultTxGasLimit default tx gas limit to use in the absence of extra args + /// @return EVMExtraArgs the extra args struct (latest version) + function _parseUnvalidatedEVMExtraArgsFromBytes( bytes calldata extraArgs, uint64 defaultTxGasLimit - ) internal pure returns (Client.EVMExtraArgsV2 memory) { + ) private pure returns (Client.EVMExtraArgsV2 memory) { if (extraArgs.length == 0) { + // If extra args are empty, generate default values return Client.EVMExtraArgsV2({gasLimit: defaultTxGasLimit, allowOutOfOrderExecution: false}); } bytes4 extraArgsTag = bytes4(extraArgs); + bytes memory argsData = extraArgs[4:]; + if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { - return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV2)); + return abi.decode(argsData, (Client.EVMExtraArgsV2)); } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { // EVMExtraArgsV1 originally included a second boolean (strict) field which has been deprecated. // Clients may still include it but it will be ignored. - return Client.EVMExtraArgsV2({gasLimit: abi.decode(extraArgs[4:], (uint256)), allowOutOfOrderExecution: false}); + return Client.EVMExtraArgsV2({gasLimit: abi.decode(argsData, (uint256)), allowOutOfOrderExecution: false}); } revert InvalidExtraArgsTag(); @@ -413,24 +457,30 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre /// only common user-driven mistakes are validated here to minimize duplicate validation cost. /// @param destChainSelector The destination chain selector. /// @param dataLength The length of the data field of the message. - /// @param gasLimit The gasLimit set in message for destination execution. /// @param numberOfTokens The number of tokens to be sent. function _validateMessage( uint64 destChainSelector, uint256 dataLength, - uint256 gasLimit, uint256 numberOfTokens, - bool allowOutOfOrderExecution + bytes calldata receiver ) internal view { // Check that payload is formed correctly DestChainDynamicConfig storage destChainDynamicConfig = s_destChainConfig[destChainSelector].dynamicConfig; if (dataLength > uint256(destChainDynamicConfig.maxDataBytes)) { revert MessageTooLarge(uint256(destChainDynamicConfig.maxDataBytes), dataLength); } - if (gasLimit > uint256(destChainDynamicConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); if (numberOfTokens > uint256(destChainDynamicConfig.maxNumberOfTokensPerMsg)) revert UnsupportedNumberOfTokens(); - if (destChainDynamicConfig.enforceOutOfOrder && !allowOutOfOrderExecution) { - revert ExtraArgOutOfOrderExecutionMustBeTrue(); + + _validateDestFamilyAddress(destChainDynamicConfig.chainFamilySelector, receiver); + } + + /// @notice Validates that the destAddress matches the expected format of the family. + /// @param chainFamilySelector Tag to identify the target family + /// @param destAddress Dest address to validate + /// @dev precondition - assumes the family tag is correct and validated + function _validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) internal pure { + if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { + Internal._validateEVMAddress(destAddress); } } @@ -515,16 +565,8 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre if (!destChainDynamicConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); - Client.EVMExtraArgsV2 memory extraArgs = - _extraArgsFromBytes(message.extraArgs, destChainDynamicConfig.defaultTxGasLimit); // Validate the message with various checks - _validateMessage( - destChainSelector, - message.data.length, - extraArgs.gasLimit, - message.tokenAmounts.length, - extraArgs.allowOutOfOrderExecution - ); + _validateMessage(destChainSelector, message.data.length, message.tokenAmounts.length, message.receiver); uint64 premiumMultiplierWeiPerEth = s_premiumMultiplierWeiPerEth[message.feeToken]; @@ -569,11 +611,16 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre // We add the message gas limit, the overhead gas, the gas of passing message data to receiver, and token transfer gas together. // We then multiply this gas total with the gas multiplier and gas price, converting it into USD with 36 decimals. // uint112(packedGasPrice) = executionGasPrice - uint256 executionCost = uint112(packedGasPrice) - * ( - extraArgs.gasLimit + destChainDynamicConfig.destGasOverhead - + (message.data.length * destChainDynamicConfig.destGasPerPayloadByte) + tokenTransferGas - ) * destChainDynamicConfig.gasMultiplierWeiPerEth; + + // TODO: revisit how generic this logic can be for non-EVM chains + + uint256 executionGasCost = destChainDynamicConfig.destGasOverhead + + (message.data.length * destChainDynamicConfig.destGasPerPayloadByte) + tokenTransferGas; + + // NOTE: when supporting non-EVM chains, revisit this and parse non-EVM args + executionGasCost += _parseEVMExtraArgsFromBytes(message.extraArgs, destChainDynamicConfig).gasLimit; + + uint256 executionCost = uint112(packedGasPrice) * executionGasCost * destChainDynamicConfig.gasMultiplierWeiPerEth; // 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. @@ -598,8 +645,8 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre ) internal view returns (uint256 dataAvailabilityCostUSD36Decimal) { // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields. // Fixed message fields do account for the offset and length slot of the dynamic fields. - uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; DestChainDynamicConfig storage destChainDynamicConfig = s_destChainConfig[destChainSelector].dynamicConfig; // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost. @@ -705,7 +752,11 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; - if (destChainSelector == 0 || destChainConfigArg.dynamicConfig.defaultTxGasLimit == 0) { + // NOTE: when supporting non-EVM chains, update chainFamilySelector validations + if ( + destChainSelector == 0 || destChainConfigArg.dynamicConfig.defaultTxGasLimit == 0 + || destChainConfigArg.dynamicConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM + ) { revert InvalidDestChainConfig(destChainSelector); } @@ -723,7 +774,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre if (destChainConfig.metadataHash == 0) { newDestChainConfig.metadataHash = - keccak256(abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))); + keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))); destChainConfig.metadataHash = newDestChainConfig.metadataHash; if (prevOnRamp != address(0)) destChainConfig.prevOnRamp = prevOnRamp; diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index b780f4cfad..a9b248eb72 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -402,9 +402,7 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); uint64 startNonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messages[0].sender)); - s_prevOffRamp.execute( - _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) - ); + s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); // Nonce unchanged for chain 3 assertEq( @@ -436,9 +434,7 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); for (uint64 i = 1; i < 4; ++i) { - s_prevOffRamp.execute( - _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) - ); + s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); // messages contains a single message - update for the next execution messages[0].nonce++; @@ -457,9 +453,7 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_2, abi.encode(messages[0].sender)); for (uint64 i = 1; i < 4; ++i) { - s_nestedPrevOffRamps[0].execute( - _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new uint256[](0) - ); + s_nestedPrevOffRamps[0].execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); // messages contains a single message - update for the next execution messages[0].nonce++; @@ -478,9 +472,7 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)); - s_prevOffRamp.execute( - _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) - ); + s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); assertEq( startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender)) @@ -533,9 +525,7 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { Internal.EVM2EVMMessage[] memory messages = _generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1); - s_prevOffRamp.execute( - _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0) - ); + s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0)); Internal.Any2EVMRampMessage[] memory messagesMultiRamp = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -587,9 +577,7 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { messagesSingleLane[0].messageId = Internal._hash(messagesSingleLane[0], s_prevOffRamp.metadataHash()); // previous offramp executes msg and increases nonce - s_prevOffRamp.execute( - _generateSingleLaneRampReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesSingleLane), new uint256[](0) - ); + s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messagesSingleLane), new uint256[](0)); assertEq( startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messagesSingleLane[0].sender)) @@ -612,10 +600,11 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup { assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); } - function _generateSingleLaneRampReportFromMessages( - uint64 sourceChainSelector, - 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/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 1d9a99f182..ad42c20d14 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -221,7 +221,7 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { IERC20(s_sourceTokens[1]).approve(address(router), i_tokenAmount1); message.receiver = abi.encode(address(s_receiver)); - Internal.EVM2EVMMessage memory msgEvent = _messageToEvent( + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( message, sourceChainSelector, DEST_CHAIN_SELECTOR, @@ -240,20 +240,21 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); + uint256 gasLimit = abi.decode(msgEvent.extraArgs, (Client.EVMExtraArgsV2)).gasLimit; + return Internal.Any2EVMRampMessage({ header: Internal.RampMessageHeader({ - messageId: msgEvent.messageId, + messageId: msgEvent.header.messageId, sourceChainSelector: sourceChainSelector, destChainSelector: DEST_CHAIN_SELECTOR, - sequenceNumber: msgEvent.sequenceNumber, - nonce: msgEvent.nonce + sequenceNumber: msgEvent.header.sequenceNumber, + nonce: msgEvent.header.nonce }), sender: abi.encode(msgEvent.sender), data: msgEvent.data, - receiver: msgEvent.receiver, - gasLimit: msgEvent.gasLimit, - tokenAmounts: msgEvent.tokenAmounts, - sourceTokenData: msgEvent.sourceTokenData + receiver: abi.decode(msgEvent.receiver, (address)), + gasLimit: gasLimit, + tokenAmounts: msgEvent.tokenAmounts }); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol index 0e2202869e..4ee4144bc9 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol @@ -27,29 +27,24 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { } function releaseOrMintSingleToken( - uint256 sourceTokenAmount, + Internal.RampTokenAmount memory sourceTokenAmount, bytes calldata originalSender, address receiver, uint64 sourceChainSelector, - Internal.SourceTokenData calldata sourceTokenData, bytes calldata offchainTokenData ) external returns (Client.EVMTokenAmount memory) { - return _releaseOrMintSingleToken( - sourceTokenAmount, originalSender, receiver, sourceChainSelector, sourceTokenData, offchainTokenData - ); + return + _releaseOrMintSingleToken(sourceTokenAmount, originalSender, receiver, sourceChainSelector, offchainTokenData); } function releaseOrMintTokens( - Client.EVMTokenAmount[] memory sourceTokenAmounts, + Internal.RampTokenAmount[] memory sourceTokenAmounts, bytes memory originalSender, address receiver, uint64 sourceChainSelector, - bytes[] calldata sourceTokenData, bytes[] calldata offchainTokenData ) external returns (Client.EVMTokenAmount[] memory) { - return _releaseOrMintTokens( - sourceTokenAmounts, originalSender, receiver, sourceChainSelector, sourceTokenData, offchainTokenData - ); + return _releaseOrMintTokens(sourceTokenAmounts, originalSender, receiver, sourceChainSelector, offchainTokenData); } function trialExecute( diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol index c850de6cd5..6261e6539b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol @@ -42,10 +42,21 @@ contract EVM2EVMMultiOnRampHelper is EVM2EVMMultiOnRamp, IgnoreContractSize { return _getTokenTransferCost(destChainSelector, feeToken, feeTokenPrice, tokenAmounts); } - function extraArgsFromBytes( + function parseEVMExtraArgsFromBytes( bytes calldata extraArgs, uint64 destChainSelector ) external view returns (Client.EVMExtraArgsV2 memory) { - return _extraArgsFromBytes(extraArgs, s_destChainConfig[destChainSelector].dynamicConfig.defaultTxGasLimit); + return _parseEVMExtraArgsFromBytes(extraArgs, s_destChainConfig[destChainSelector].dynamicConfig); + } + + function validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) external pure { + _validateDestFamilyAddress(chainFamilySelector, destAddress); + } + + function convertParsedExtraArgs( + bytes calldata extraArgs, + DestChainDynamicConfig memory destChainDynamicConfig + ) external pure returns (bytes memory encodedExtraArgs) { + return _convertParsedExtraArgs(extraArgs, destChainDynamicConfig); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol index 755b326c0d..f0ca898a6c 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -11,16 +11,12 @@ contract MessageHasher { return Internal._hash(message, onRamp); } - function encodeTokenAmountsHashPreimage(Client.EVMTokenAmount[] memory tokenAmounts) + function encodeTokenAmountsHashPreimage(Internal.RampTokenAmount[] memory rampTokenAmounts) public pure returns (bytes memory) { - return abi.encode(tokenAmounts); - } - - function encodeSourceTokenDataHashPreimage(bytes[] memory sourceTokenData) public pure returns (bytes memory) { - return abi.encode(sourceTokenData); + return abi.encode(rampTokenAmounts); } function encodeMetadataHashPreimage( @@ -48,11 +44,8 @@ contract MessageHasher { bytes32 implicitMetadataHash, bytes32 fixedSizeFieldsHash, bytes32 dataHash, - bytes32 tokenAmountsHash, - bytes32 sourceTokenDataHash + bytes32 tokenAmountsHash ) public pure returns (bytes memory) { - return abi.encode( - leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash - ); + return abi.encode(leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash); } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index c994cf5698..4ab5acf374 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -702,13 +702,7 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(fakePoolAddress), - destTokenAddress: abi.encode(s_destTokenBySourceToken[messages[0].tokenAmounts[0].token]), - extraData: "" - }) - ); + 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); @@ -982,7 +976,6 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { Internal.Any2EVMRampMessage memory message = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); - Internal.SourceTokenData memory sourceTokenData = abi.decode(message.sourceTokenData[0], (Internal.SourceTokenData)); vm.expectCall( s_destPoolByToken[s_destTokens[0]], @@ -992,11 +985,11 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { originalSender: message.sender, receiver: message.receiver, amount: message.tokenAmounts[0].amount, - localToken: s_destTokenBySourceToken[message.tokenAmounts[0].token], + localToken: abi.decode(message.tokenAmounts[0].destTokenAddress, (address)), remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: "" + sourcePoolAddress: message.tokenAmounts[0].sourcePoolAddress, + sourcePoolData: message.tokenAmounts[0].extraData, + offchainTokenData: offchainTokenData[0] }) ) ); @@ -1693,16 +1686,13 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { // 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 Client.EVMTokenAmount[](1); - messages[0].tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: tokenAmount}); - messages[0].sourceTokenData = new bytes[](1); - messages[0].sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[s_sourceFeeToken]), - extraData: "" - }) - ); + messages[0].tokenAmounts = new Internal.RampTokenAmount[](1); + messages[0].tokenAmounts[0] = Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), + destTokenAddress: abi.encode(s_destTokenBySourceToken[s_sourceFeeToken]), + extraData: "", + amount: tokenAmount + }); messages[0].receiver = address(receiver); @@ -2257,13 +2247,13 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { // address 0 has no contract assertEq(address(0).code.length, 0); - message.sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(address(0)), - extraData: "" - }) - ); + + message.tokenAmounts[0] = Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(address(0)), + destTokenAddress: abi.encode(address(0)), + extraData: "", + amount: message.tokenAmounts[0].amount + }); message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); @@ -2275,13 +2265,12 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { address notAContract = makeAddr("not_a_contract"); - message.sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(notAContract), - extraData: "" - }) - ); + message.tokenAmounts[0] = Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(address(0)), + destTokenAddress: abi.encode(notAContract), + extraData: "", + amount: message.tokenAmounts[0].amount + }); message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); @@ -2307,10 +2296,11 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet IERC20 dstToken1 = IERC20(s_destTokenBySourceToken[token]); uint256 startingBalance = dstToken1.balanceOf(OWNER); - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), - extraData: "" + extraData: "", + amount: amount }); vm.expectCall( @@ -2323,16 +2313,14 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet amount: amount, localToken: s_destTokenBySourceToken[token], remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, + sourcePoolAddress: tokenAmount.sourcePoolAddress, + sourcePoolData: tokenAmount.extraData, offchainTokenData: offchainTokenData }) ) ); - s_offRamp.releaseOrMintSingleToken( - amount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData - ); + s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); } @@ -2345,10 +2333,11 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet bytes memory originalSender = abi.encode(OWNER); bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(destToken), - extraData: "" + extraData: "", + amount: amount }); // Address(0) should always revert @@ -2362,9 +2351,7 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, returnedPool)); - s_offRamp.releaseOrMintSingleToken( - amount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData - ); + s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); // A contract that doesn't support the interface should also revert returnedPool = address(s_offRamp); @@ -2377,9 +2364,7 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, returnedPool)); - s_offRamp.releaseOrMintSingleToken( - amount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData - ); + s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); } function test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() public { @@ -2390,10 +2375,11 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet bytes memory originalSender = abi.encode(OWNER); bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(destToken), - extraData: "" + extraData: "", + amount: amount }); bytes memory revertData = "call reverted :o"; @@ -2402,7 +2388,7 @@ contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSet vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, revertData)); s_offRamp.releaseOrMintSingleToken( - amount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData + tokenAmount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); } } @@ -2423,8 +2409,7 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); offchainTokenData[0] = abi.encode(0x12345678); - bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); + Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2436,15 +2421,15 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { amount: srcTokenAmounts[0].amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, offchainTokenData: offchainTokenData[0] }) ) ); s_offRamp.releaseOrMintTokens( - srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, encodedSourceTokenData, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); @@ -2458,8 +2443,8 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { srcTokenAmounts[0].amount = amount; bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); + + Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); // Since the pool call is mocked, we manually release funds to the offRamp deal(destToken, address(s_offRamp), amount * destinationDenominationMultiplier); @@ -2474,8 +2459,8 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { amount: amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, offchainTokenData: offchainTokenData[0] }) ), @@ -2483,7 +2468,7 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { ); Client.EVMTokenAmount[] memory destTokenAmounts = s_offRamp.releaseOrMintTokens( - srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, encodedSourceTokenData, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); assertEq(destTokenAmounts[0].amount, amount * destinationDenominationMultiplier); @@ -2501,11 +2486,10 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, unknownError)); s_offRamp.releaseOrMintTokens( - srcTokenAmounts, + _getDefaultSourceTokenData(srcTokenAmounts), abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, - _getDefaultSourceTokenData(srcTokenAmounts), new bytes[](srcTokenAmounts.length) ); } @@ -2516,8 +2500,7 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { srcTokenAmounts[0].amount = amount; bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); + Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.mockCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2529,8 +2512,8 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { amount: amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, offchainTokenData: offchainTokenData[0] }) ), @@ -2543,7 +2526,7 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { ); s_offRamp.releaseOrMintTokens( - srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, encodedSourceTokenData, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); } @@ -2551,21 +2534,15 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - bytes[] memory sourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); bytes memory wrongAddress = abi.encode(address(1000), address(10000), address(10000)); - sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[0].token]), - destTokenAddress: wrongAddress, - extraData: "" - }) - ); + sourceTokenAmounts[0].destTokenAddress = wrongAddress; vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, wrongAddress)); s_offRamp.releaseOrMintTokens( - srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); } @@ -2573,19 +2550,16 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { // The offRamp is a contract, but not a pool address fakePoolAddress = address(s_offRamp); - bytes[] memory sourceTokenData = new bytes[](1); - sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(fakePoolAddress), - destTokenAddress: abi.encode(s_offRamp), - extraData: "" - }) - ); + Internal.RampTokenAmount[] memory sourceTokenAmounts = new Internal.RampTokenAmount[](1); + sourceTokenAmounts[0] = Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(fakePoolAddress), + destTokenAddress: abi.encode(s_offRamp), + extraData: "", + amount: 1 + }); vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, address(0))); - s_offRamp.releaseOrMintTokens( - new Client.EVMTokenAmount[](1), abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, new bytes[](1) - ); + s_offRamp.releaseOrMintTokens(sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1)); } function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { @@ -2596,8 +2570,7 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); offchainTokenData[0] = abi.encode(0x12345678); - bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); + Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2609,15 +2582,15 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { amount: srcTokenAmounts[0].amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], remoteChainSelector: SOURCE_CHAIN_SELECTOR_3, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, offchainTokenData: offchainTokenData[0] }) ) ); vm.expectRevert(); s_offRamp.releaseOrMintTokens( - srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, encodedSourceTokenData, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, offchainTokenData ); } @@ -2629,17 +2602,16 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { // triggers some Create2Deployer and causes it to fail vm.assume(destPool != 447301751254033913445893214690834296930546521452); bytes memory unusedVar = abi.encode(makeAddr("unused")); - bytes[] memory sourceTokenData = new bytes[](1); - sourceTokenData[0] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: unusedVar, - destTokenAddress: abi.encode(destPool), - extraData: unusedVar - }) - ); + Internal.RampTokenAmount[] memory sourceTokenAmounts = new Internal.RampTokenAmount[](1); + sourceTokenAmounts[0] = Internal.RampTokenAmount({ + sourcePoolAddress: unusedVar, + destTokenAddress: abi.encode(destPool), + extraData: unusedVar, + amount: 1 + }); try s_offRamp.releaseOrMintTokens( - new Client.EVMTokenAmount[](1), abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, new bytes[](1) + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1) ) {} 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/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol index 7355d6a072..fcaa6139e8 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol @@ -250,13 +250,12 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); for (uint256 i = 0; i < numberOfTokens; ++i) { - Internal.SourceTokenData memory sourceTokenData = - abi.decode(original.sourceTokenData[i], (Internal.SourceTokenData)); + Internal.RampTokenAmount memory tokenAmount = original.tokenAmounts[i]; - address destPoolAddress = abi.decode(sourceTokenData.destTokenAddress, (address)); + address destPoolAddress = abi.decode(tokenAmount.destTokenAddress, (address)); TokenPool pool = TokenPool(destPoolAddress); destTokenAmounts[i].token = address(pool.getToken()); - destTokenAmounts[i].amount = original.tokenAmounts[i].amount; + destTokenAmounts[i].amount = tokenAmount.amount; } return Client.Any2EVMMessage({ @@ -297,6 +296,19 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba bool allowOutOfOrderExecution ) internal view returns (Internal.Any2EVMRampMessage memory) { bytes memory data = abi.encode(0); + + Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](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({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), + destTokenAddress: abi.encode(s_destTokenBySourceToken[tokenAmounts[i].token]), + extraData: "", + amount: tokenAmounts[i].amount + }); + } + Internal.Any2EVMRampMessage memory message = Internal.Any2EVMRampMessage({ header: Internal.RampMessageHeader({ messageId: "", @@ -308,22 +320,10 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba sender: abi.encode(OWNER), data: data, receiver: address(s_receiver), - tokenAmounts: tokenAmounts, - sourceTokenData: new bytes[](tokenAmounts.length), + tokenAmounts: rampTokenAmounts, gasLimit: GAS_LIMIT }); - // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - message.sourceTokenData[i] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[tokenAmounts[i].token]), - extraData: "" - }) - ); - } - message.header.messageId = Internal._hash(message, onRamp); return message; @@ -417,17 +417,16 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba function _getDefaultSourceTokenData(Client.EVMTokenAmount[] memory srcTokenAmounts) internal view - returns (bytes[] memory) + returns (Internal.RampTokenAmount[] memory) { - bytes[] memory sourceTokenData = new bytes[](srcTokenAmounts.length); + Internal.RampTokenAmount[] memory sourceTokenData = new Internal.RampTokenAmount[](srcTokenAmounts.length); for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { - sourceTokenData[i] = abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[srcTokenAmounts[i].token]), - extraData: "" - }) - ); + sourceTokenData[i] = Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), + destTokenAddress: abi.encode(s_destTokenBySourceToken[srcTokenAmounts[i].token]), + extraData: "", + amount: srcTokenAmounts[i].amount + }); } return sourceTokenData; } diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol index 2b16c87e2e..253012570b 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol @@ -65,7 +65,7 @@ contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { sequenceNumber: 0, metadataHash: keccak256( abi.encode( - Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArg.destChainSelector, address(s_onRamp) + Internal.EVM_2_ANY_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArg.destChainSelector, address(s_onRamp) ) ) }); @@ -195,6 +195,8 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet type(uint32).max ) ); + destChainConfigArgs.dynamicConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + bool isNewChain = true; if (destChainConfigArgs.destChainSelector == DEST_CHAIN_SELECTOR) { @@ -210,7 +212,7 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet sequenceNumber: 0, metadataHash: keccak256( abi.encode( - Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArgs.destChainSelector, address(s_onRamp) + Internal.EVM_2_ANY_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArgs.destChainSelector, address(s_onRamp) ) ) }); @@ -246,7 +248,7 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet sequenceNumber: 0, metadataHash: keccak256( abi.encode( - Internal.EVM_2_EVM_MESSAGE_HASH, + Internal.EVM_2_ANY_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArgs[0].destChainSelector, address(s_onRamp) @@ -260,7 +262,7 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet sequenceNumber: 0, metadataHash: keccak256( abi.encode( - Internal.EVM_2_EVM_MESSAGE_HASH, + Internal.EVM_2_ANY_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArgs[1].destChainSelector, address(s_onRamp) @@ -294,6 +296,8 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet assertEq(vm.getRecordedLogs().length, 0); } + // Reverts + function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -305,7 +309,7 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero() public { + function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -343,6 +347,18 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); } + + function test_InvalidChainFamilySelector_Revert() public { + EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); + EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.dynamicConfig.chainFamilySelector = bytes4(uint32(1)); + + vm.expectRevert( + abi.encodeWithSelector(EVM2EVMMultiOnRamp.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); + } } contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { @@ -576,7 +592,7 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { // Make sure the tokens are in the contract deal(s_sourceFeeToken, address(s_onRamp), feeTokenAmount); - Internal.EVM2EVMMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); + Internal.EVM2AnyRampMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); vm.expectEmit(); emit EVM2EVMMultiOnRamp.FeePaid(s_sourceFeeToken, feeTokenAmount); @@ -585,7 +601,8 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { // Assert the message Id is correct assertEq( - expectedEvent.messageId, s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeTokenAmount, originalSender) + expectedEvent.header.messageId, + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeTokenAmount, originalSender) ); } @@ -735,7 +752,7 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 1, OWNER); } - function test_InvalidAddress_Revert() public { + function test_InvalidEVMAddress_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.receiver = abi.encode(type(uint208).max); @@ -854,6 +871,41 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } + function test_InvalidEVMAddressDestToken_Revert() public { + address sourceETH = s_sourceTokens[1]; + vm.stopPrank(); + vm.startPrank(OWNER); + + MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( + BurnMintERC677(sourceETH), new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); + deal(address(sourceETH), address(newPool), type(uint256).max); + + // Add TokenPool to OnRamp + s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); + + bytes memory nonEvmAddress = abi.encode(type(uint208).max); + + // Allow chain in TokenPool + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_destTokenPool), + remoteTokenAddress: nonEvmAddress, + allowed: true, + outboundRateLimiterConfig: getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: getInboundRateLimiterConfig() + }); + newPool.applyChainUpdates(chainUpdates); + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); + + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + function test_forwardFromRouter_UnsupportedToken_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.tokenAmounts = new Client.EVMTokenAmount[](1); @@ -968,7 +1020,7 @@ contract EVM2EVMMultiOnRamp_getDataAvailabilityCost is EVM2EVMMultiOnRamp_getFee s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; uint256 dataAvailabilityGas = destChainDynamicConfig.destDataAvailabilityOverheadGas - + destChainDynamicConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; + + destChainDynamicConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; uint256 expectedDataAvailabilityCostUSD = USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainDynamicConfig.destDataAvailabilityMultiplierBps * 1e14; @@ -989,7 +1041,7 @@ contract EVM2EVMMultiOnRamp_getDataAvailabilityCost is EVM2EVMMultiOnRamp_getFee uint256 dataAvailabilityCostUSD2 = s_onRamp.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); dataAvailabilityGas = destChainDynamicConfig.destDataAvailabilityOverheadGas - + destChainDynamicConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; + + destChainDynamicConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; expectedDataAvailabilityCostUSD = USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainDynamicConfig.destDataAvailabilityMultiplierBps * 1e14; @@ -1005,7 +1057,7 @@ contract EVM2EVMMultiOnRamp_getDataAvailabilityCost is EVM2EVMMultiOnRamp_getFee s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; uint256 dataAvailabilityLengthBytes = - Internal.MESSAGE_FIXED_BYTES + 100 + (5 * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; + Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + 100 + (5 * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; uint256 dataAvailabilityGas = destChainDynamicConfig.destDataAvailabilityOverheadGas + destChainDynamicConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; uint256 expectedDataAvailabilityCostUSD = USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas @@ -1055,6 +1107,7 @@ contract EVM2EVMMultiOnRamp_getDataAvailabilityCost is EVM2EVMMultiOnRamp_getFee destChainConfigArgs[0].dynamicConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; destChainConfigArgs[0].dynamicConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; destChainConfigArgs[0].dynamicConfig.defaultTxGasLimit = GAS_LIMIT; + destChainConfigArgs[0].dynamicConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); @@ -1066,8 +1119,8 @@ contract EVM2EVMMultiOnRamp_getDataAvailabilityCost is EVM2EVMMultiOnRamp_getFee tokenTransferBytesOverhead ); - uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; uint256 dataAvailabilityGas = destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; @@ -1716,7 +1769,7 @@ contract EVM2EVMMultiOnRamp_withdrawFeeTokens is EVM2EVMMultiOnRampSetup { } } -contract EVM2EVMOnRamp_applyPremiumMultiplierWeiPerEthUpdates is EVM2EVMMultiOnRampSetup { +contract EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates is EVM2EVMMultiOnRampSetup { function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg ) public { @@ -1994,3 +2047,94 @@ contract EVM2EVMMultiOnRamp_getTokenPool is EVM2EVMMultiOnRampSetup { assertEq(address(0), nonExistentPool); } } + +contract EVM2EVMMultiOnRamp_validateDestFamilyAddress is EVM2EVMMultiOnRampSetup { + function test_ValidEVMAddress_Success() public view { + bytes memory encodedAddress = abi.encode(address(10000)); + s_onRamp.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); + } + + function test_ValidNonEVMAddress_Success() public view { + s_onRamp.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); + } + + // Reverts + + function test_InvalidEVMAddress_Revert() public { + bytes memory invalidAddress = abi.encode(type(uint208).max); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); + s_onRamp.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + } +} + +contract EVM2EVMMultiOnRamp_convertParsedExtraArgs is EVM2EVMMultiOnRampSetup { + EVM2EVMMultiOnRamp.DestChainDynamicConfig private s_destChainDynamicConfig; + + function setUp() public virtual override { + super.setUp(); + s_destChainDynamicConfig = _generateDestChainConfigArgs()[0].dynamicConfig; + } + + function test_EVMExtraArgsV1_Success() public view { + Client.EVMExtraArgsV1 memory inputArgs = Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + Client.EVMExtraArgsV2 memory expectedOutputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); + + vm.assertEq( + s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig), abi.encode(expectedOutputArgs) + ); + } + + function test_EVMExtraArgsV2_Success() public view { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + + vm.assertEq(s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig), abi.encode(inputArgs)); + } + + function test_EVMExtraArgsDefault_Success() public view { + Client.EVMExtraArgsV2 memory expectedOutputArgs = + Client.EVMExtraArgsV2({gasLimit: s_destChainDynamicConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); + + vm.assertEq(s_onRamp.convertParsedExtraArgs("", s_destChainDynamicConfig), abi.encode(expectedOutputArgs)); + } + + function test_EmptyExtraArgs_Success() public { + s_destChainDynamicConfig.chainFamilySelector = bytes4(uint32(1)); + vm.assertEq(s_onRamp.convertParsedExtraArgs("", s_destChainDynamicConfig), ""); + } + + // Reverts + + function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + // Invalidate selector + inputExtraArgs[0] = bytes1(uint8(0)); + + vm.expectRevert(EVM2EVMMultiOnRamp.InvalidExtraArgsTag.selector); + s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig); + } + + function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + s_destChainDynamicConfig.enforceOutOfOrder = true; + + vm.expectRevert(EVM2EVMMultiOnRamp.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig); + } + + function test_EVMExtraArgsGasLimitTooHigh_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: s_destChainDynamicConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + + vm.expectRevert(EVM2EVMMultiOnRamp.MessageGasLimitTooHigh.selector); + s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig); + } +} diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol index d9e2921421..97136d048f 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol @@ -21,9 +21,6 @@ import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { - // Duplicate event of the CCIPSendRequested in the IOnRamp - event CCIPSendRequested(Internal.EVM2EVMMessage message); - address internal constant CUSTOM_TOKEN = address(12345); uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM @@ -170,7 +167,7 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { uint64 nonce, uint256 feeTokenAmount, address originalSender - ) public view returns (Internal.EVM2EVMMessage memory) { + ) public view returns (Internal.EVM2AnyRampMessage memory) { return _messageToEvent( message, SOURCE_CHAIN_SELECTOR, @@ -194,46 +191,46 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { address originalSender, bytes32 metadataHash, TokenAdminRegistry tokenAdminRegistry - ) internal view returns (Internal.EVM2EVMMessage memory) { - Client.EVMExtraArgsV2 memory extraArgs = s_onRamp.extraArgsFromBytes(message.extraArgs, destChainSelector); - - Internal.EVM2EVMMessage memory messageEvent = Internal.EVM2EVMMessage({ - sequenceNumber: seqNum, - feeTokenAmount: feeTokenAmount, + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + Client.EVMExtraArgsV2 memory extraArgs = s_onRamp.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); + + Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ + header: Internal.RampMessageHeader({ + messageId: "", + sourceChainSelector: sourceChainSelector, + destChainSelector: destChainSelector, + sequenceNumber: seqNum, + nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce + }), sender: originalSender, - nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce, - gasLimit: extraArgs.gasLimit, - strict: false, - sourceChainSelector: sourceChainSelector, - receiver: abi.decode(message.receiver, (address)), data: message.data, - tokenAmounts: message.tokenAmounts, - sourceTokenData: new bytes[](message.tokenAmounts.length), + receiver: message.receiver, + extraArgs: abi.encode(extraArgs), feeToken: message.feeToken, - messageId: "" + feeTokenAmount: feeTokenAmount, + tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) }); for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - messageEvent.sourceTokenData[i] = _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry); + messageEvent.tokenAmounts[i] = _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry); } - messageEvent.messageId = Internal._hash(messageEvent, metadataHash); + messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); return messageEvent; } function _getSourceTokenData( Client.EVMTokenAmount memory tokenAmount, TokenAdminRegistry tokenAdminRegistry - ) internal view returns (bytes memory) { + ) internal view returns (Internal.RampTokenAmount memory) { address destToken = s_destTokenBySourceToken[tokenAmount.token]; - return abi.encode( - Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool), - destTokenAddress: abi.encode(destToken), - extraData: "" - }) - ); + return Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool), + destTokenAddress: abi.encode(destToken), + extraData: "", + amount: tokenAmount.amount + }); } function _generateDynamicMultiOnRampConfig( @@ -277,7 +274,8 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { defaultTxGasLimit: GAS_LIMIT, gasMultiplierWeiPerEth: 5e17, networkFeeUSDCents: 1_00, - enforceOutOfOrder: false + enforceOutOfOrder: false, + chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM }), prevOnRamp: address(0) }); @@ -327,7 +325,7 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { return ( onRamp, - keccak256(abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, sourceChainSelector, DEST_CHAIN_SELECTOR, address(onRamp))) + keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, sourceChainSelector, DEST_CHAIN_SELECTOR, address(onRamp))) ); } diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go index b2fcdc4670..edd06bf867 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go @@ -93,13 +93,12 @@ type EVM2EVMMultiOffRampUnblessedRoot struct { } type InternalAny2EVMRampMessage struct { - Header InternalRampMessageHeader - Sender []byte - Data []byte - Receiver common.Address - GasLimit *big.Int - TokenAmounts []ClientEVMTokenAmount - SourceTokenData [][]byte + Header InternalRampMessageHeader + Sender []byte + Data []byte + Receiver common.Address + GasLimit *big.Int + TokenAmounts []InternalRampTokenAmount } type InternalExecutionReportSingleChain struct { @@ -128,6 +127,13 @@ type InternalRampMessageHeader struct { Nonce uint64 } +type InternalRampTokenAmount struct { + SourcePoolAddress []byte + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int +} + type InternalTokenPriceUpdate struct { SourceToken common.Address UsdPerToken *big.Int @@ -156,8 +162,8 @@ type MultiOCR3BaseOCRConfigArgs struct { } var EVM2EVMMultiOffRampMetaData = &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\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"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\":\"error\",\"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\":\"structEVM2EVMMultiOffRamp.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\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"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\":\"error\",\"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\":[{\"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\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\"}],\"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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"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\":\"structEVM2EVMMultiOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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: "0x6101206040523480156200001257600080fd5b506040516200694f3803806200694f8339810160408190526200003591620005bd565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001ee565b5050466080525060208201516001600160a01b03161580620000ec575060408201516001600160a01b0316155b8062000103575060608201516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b81516001600160401b0390811660a052602080840180516001600160a01b0390811660c05260408087018051831660e0526060808901805185166101005283518a519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e68162000299565b505062000a03565b336001600160a01b03821603620002485760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015620004eb576000828281518110620002bd57620002bd620007cc565b60200260200101519050600081600001519050806001600160401b0316600003620002fb5760405163c656089560e01b815260040160405180910390fd5b6001600160401b03811660009081526007602052604081206001810180549192916200032790620007e2565b80601f01602080910402602001604051908101604052809291908181526020018280546200035590620007e2565b8015620003a65780601f106200037a57610100808354040283529160200191620003a6565b820191906000526020600020905b8154815290600101906020018083116200038857829003601f168201915b50505050509050600084604001519050815160000362000449578051600003620003e3576040516342bcdf7f60e11b815260040160405180910390fd5b60018301620003f3828262000873565b508254610100600160481b0319166101001783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a162000484565b8080519060200120828051906020012014620004845760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b6020850151835460ff19169015151783556040516001600160401b038516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba90620004d29086906200093f565b60405180910390a250505050508060010190506200029c565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200052a576200052a620004ef565b60405290565b604051606081016001600160401b03811182821017156200052a576200052a620004ef565b604051601f8201601f191681016001600160401b0381118282101715620005805762000580620004ef565b604052919050565b80516001600160401b0381168114620005a057600080fd5b919050565b80516001600160a01b0381168114620005a057600080fd5b60008082840360a0811215620005d257600080fd5b6080811215620005e157600080fd5b50620005ec62000505565b620005f78462000588565b8152602062000608818601620005a5565b818301526200061a60408601620005a5565b60408301526200062d60608601620005a5565b606083015260808501519193506001600160401b03808311156200065057600080fd5b828601925086601f8401126200066557600080fd5b8251818111156200067a576200067a620004ef565b8060051b6200068b84820162000555565b918252848101840191848101908a841115620006a657600080fd5b85870192505b83831015620007bb57825185811115620006c557600080fd5b8701601f196060828e0382011215620006dd57600080fd5b620006e762000530565b620006f489840162000588565b8152604083015180151581146200070a57600080fd5b818a01526060830151888111156200072157600080fd5b8084019350508d603f8401126200073757600080fd5b88830151888111156200074e576200074e620004ef565b620007608a84601f8401160162000555565b92508083528e60408286010111156200077857600080fd5b60005b818110156200079957848101604001518482018c01528a016200077b565b5060009083018a015260408101919091528352509185019190850190620006ac565b809750505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620007f757607f821691505b6020821081036200081857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200086e576000816000526020600020601f850160051c81016020861015620008495750805b601f850160051c820191505b818110156200086a5782815560010162000855565b5050505b505050565b81516001600160401b038111156200088f576200088f620004ef565b620008a781620008a08454620007e2565b846200081e565b602080601f831160018114620008df5760008415620008c65750858301515b600019600386901b1c1916600185901b1785556200086a565b600085815260208120601f198616915b828110156200091057888601518255948401946001909101908401620008ef565b50858210156200092f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020808252825460ff811615158383015260081c6001600160401b031660408301526060808301526001808401805460009392919084906200098181620007e2565b80608089015260a06001831660008114620009a55760018114620009c257620009f4565b60ff19841660a08b015260a083151560051b8b01019450620009f4565b85600052602060002060005b84811015620009eb5781548c8201850152908801908901620009ce565b8b0160a0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615edd62000a726000396000818161023e0152612be101526000818161020f0152612ecb0152600081816101e0015281816115ca01526116810152600081816101b00152612755015260008181611fb901526120050152615edd6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b146105b1578063f716f99f146105c4578063ff888fb1146105d757600080fd5b8063ccd37ba314610539578063d2a15d351461057e578063e9d68a8e1461059157600080fd5b8063a12a9870116100bd578063a12a9870146104f3578063bec0b14314610506578063c673e5841461051957600080fd5b806385572ffb146104ca5780638da5cb5b146104d857600080fd5b8063403b2d631161012f5780635ffb5ced116101145780635ffb5ced146103855780637437ff9f1461039857806379ba5097146104c257600080fd5b8063403b2d63146103525780635e36480c1461036557600080fd5b80632d04ab76116101605780632d04ab761461030e578063311cd513146103235780633f4b04aa1461033657600080fd5b806306285c691461017c578063181f5a77146102c5575b600080fd5b61026e60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102bc9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103016040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b6040516102bc9190613f11565b61032161031c366004613fbc565b6105fa565b005b61032161033136600461406f565b6109c0565b600a5460405167ffffffffffffffff90911681526020016102bc565b6103216103603660046141f8565b610a29565b610378610373366004614297565b610bfb565b6040516102bc91906142f4565b610321610393366004614600565b610c51565b6104596040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526004546001600160a01b03808216835263ffffffff7401000000000000000000000000000000000000000083048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b90910490921660608201526005548216608082015260065490911660a082015290565b6040516102bc9190600060c0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401528060a08501511660a08401525092915050565b610321610fa9565b610321610177366004614664565b6000546040516001600160a01b0390911681526020016102bc565b6103216105013660046146b8565b611067565b610321610514366004614a46565b61107b565b61052c610527366004614b82565b611220565b6040516102bc9190614be2565b610570610547366004614c57565b67ffffffffffffffff919091166000908152600960209081526040808320938352929052205490565b6040519081526020016102bc565b61032161058c366004614c81565b61137e565b6105a461059f366004614cf6565b611438565b6040516102bc9190614d11565b6103216105bf366004614d4c565b611521565b6103216105d2366004614dd1565b611532565b6105ea6105e5366004614f0f565b611574565b60405190151581526020016102bc565b600061060887890189615098565b8051515190915015158061062157508051602001515115155b1561072157600a5460208a01359067ffffffffffffffff808316911610156106e057600a805467ffffffffffffffff191667ffffffffffffffff831617905560065482516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691633937306f916106a9916004016152d6565b600060405180830381600087803b1580156106c357600080fd5b505af11580156106d7573d6000803e3d6000fd5b5050505061071f565b81602001515160000361071f576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b8160200151518110156109095760008260200151828151811061074957610749615203565b6020026020010151905060008160000151905061076581611635565b600061077082611737565b602084015151815491925067ffffffffffffffff908116610100909204161415806107b2575060208084015190810151905167ffffffffffffffff9182169116115b156107fb57825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526107f29291906004016152e9565b60405180910390fd5b604083015180610837576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff166000908152600960209081526040808320848452909152902054156108aa5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016107f2565b60208085015101516108bd906001615334565b825468ffffffffffffffff00191661010067ffffffffffffffff928316021790925592511660009081526009602090815260408083209483529390529190912042905550600101610724565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610939919061535c565b60405180910390a16109b560008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611797915050565b505050505050505050565b610a006109cf828401846153f9565b60408051600080825260208201909252906109fa565b60608152602001906001900390816109e55790505b50611b0e565b604080516000808252602082019092529050610a23600185858585866000611797565b50505050565b610a31611bbe565b60a08101516001600160a01b03161580610a53575080516001600160a01b0316155b15610a8a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a177401000000000000000000000000000000000000000063ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff19908116928e1692909217905560a0808e01805160068054909416908f161790925586519a8b5297518716988a0198909852925185169388019390935251909216958501959095525185169383019390935251909216908201527f0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c9060c00160405180910390a150565b6000610c096001600461542e565b6002610c16608085615457565b67ffffffffffffffff16610c2a919061547e565b610c348585611c1a565b901c166003811115610c4857610c486142ca565b90505b92915050565b333014610c8a576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610cc7565b6040805180820190915260008082526020820152815260200190600190039081610ca05790505b5060a08401515190915015610cff57610cfc8360a00151846020015185606001518660000151602001518760c0015187611c61565b90505b6040805160a0810182528451518152845160209081015167ffffffffffffffff1681830152808601518351600094840192610d3b929101613f11565b60408051601f19818403018152918152908252868101516020830152018390526005549091506001600160a01b03168015610e48576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610db5908590600401615543565b600060405180830381600087803b158015610dcf57600080fd5b505af1925050508015610de0575060015b610e48573d808015610e0e576040519150601f19603f3d011682016040523d82523d6000602084013e610e13565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107f29190613f11565b604085015151158015610e5d57506080850151155b80610e74575060608501516001600160a01b03163b155b80610eb457506060850151610eb2906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611d0e565b155b15610ec0575050505050565b60048054608087015160608801516040517f3cf9798300000000000000000000000000000000000000000000000000000000815260009485946001600160a01b031693633cf9798393610f1b938a9361138893929101615556565b6000604051808303816000875af1158015610f3a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f6291908101906155d7565b509150915081610fa057806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107f29190613f11565b50505050505050565b6001546001600160a01b031633146110035760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016107f2565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61106f611bbe565b61107881611d2a565b50565b611083611fb6565b8151815181146110bf576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156112105760008482815181106110de576110de615203565b6020026020010151905060008160200151519050600085848151811061110657611106615203565b602002602001015190508051821461114a576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561120157600082828151811061116957611169615203565b60200260200101519050806000141580156111a457508460200151828151811061119557611195615203565b60200260200101516080015181105b156111f85784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064016107f2565b5060010161114d565b505050508060010190506110c2565b5061121b8383611b0e565b505050565b6112636040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561130c57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112ee575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561136e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611350575b5050505050815250509050919050565b611386611bbe565b60005b8181101561121b5760008383838181106113a5576113a5615203565b9050604002018036038101906113bb9190615631565b90506113ca8160200151611574565b61142f57805167ffffffffffffffff1660009081526009602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b50600101611389565b60408051606080820183526000808352602080840182905283850183905267ffffffffffffffff8681168352600782529185902085519384018652805460ff8116151585526101009004909216908301526001810180549394929391928401916114a19061566a565b80601f01602080910402602001604051908101604052809291908181526020018280546114cd9061566a565b801561136e5780601f106114ef5761010080835404028352916020019161136e565b820191906000526020600020905b8154815290600101906020018083116114fd57505050919092525091949350505050565b611529611bbe565b61107881612037565b61153a611bbe565b60005b81518110156115705761156882828151811061155b5761155b615203565b60200260200101516120ed565b60010161153d565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611611573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b91906156a4565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156116d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f491906156a4565b15611078576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016107f2565b67ffffffffffffffff81166000908152600760205260408120805460ff16610c4b576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016107f2565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117f68760a46156c1565b905082606001511561183e57845161180f90602061547e565b865161181c90602061547e565b6118279060a06156c1565b61183191906156c1565b61183b90826156c1565b90505b368114611880576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016107f2565b50815181146118c85781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107f2565b6118d0611fb6565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561191e5761191e6142ca565b600281111561192f5761192f6142ca565b905250905060028160200151600281111561194c5761194c6142ca565b1480156119a05750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061198857611988615203565b6000918252602090912001546001600160a01b031633145b6119d6576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611ab85760208201516119f19060016156d4565b60ff16855114611a2d576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611a68576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611a7a9291906156ed565b604051908190038120611a91918b906020016156fd565b604051602081830303815290604052805190602001209050611ab68a82888888612431565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611b48576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611bb757611baf858281518110611b7d57611b7d615203565b602002602001015184611ba957858381518110611b9c57611b9c615203565b6020026020010151612648565b83612648565b600101611b5f565b5050505050565b6000546001600160a01b03163314611c185760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107f2565b565b67ffffffffffffffff8216600090815260086020526040812081611c3f608085615711565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b8560005b8751811015611d0357611cde888281518110611c8357611c83615203565b602002602001015160200151888888888681518110611ca457611ca4615203565b6020026020010151806020019051810190611cbf9190615738565b888781518110611cd157611cd1615203565b6020026020010151612e6a565b828281518110611cf057611cf0615203565b6020908102919091010152600101611c65565b509695505050505050565b6000611d19836131f8565b8015610c485750610c488383613244565b60005b8151811015611570576000828281518110611d4a57611d4a615203565b602002602001015190506000816000015190508067ffffffffffffffff16600003611da1576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600760205260408120600181018054919291611dcc9061566a565b80601f0160208091040260200160405190810160405280929190818152602001828054611df89061566a565b8015611e455780601f10611e1a57610100808354040283529160200191611e45565b820191906000526020600020905b815481529060010190602001808311611e2857829003601f168201915b505050505090506000846040015190508151600003611efe578051600003611e99576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301611ea78282615835565b50825468ffffffffffffffff00191661010017835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611f51565b8080519060200120828051906020012014611f51576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016107f2565b6020850151835460ff191690151517835560405167ffffffffffffffff8516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba90611f9e9086906158f5565b60405180910390a25050505050806001019050611d2d565b467f000000000000000000000000000000000000000000000000000000000000000014611c18576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107f2565b336001600160a01b0382160361208f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107f2565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003612118576000604051631b3fab5160e11b81526004016107f291906159b1565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361218557606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff9092169190911790556121da565b6060840151600182015460ff62010000909104161515901515146121da576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016107f2565b60a08401518051601f60ff82161115612209576001604051631b3fab5160e11b81526004016107f291906159b1565b61226f858560030180548060200260200160405190810160405280929190818152602001828054801561226557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612247575b50505050506132e6565b85606001511561239e576122dd8585600201805480602002602001604051908101604052809291908181526020018280548015612265576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122475750505050506132e6565b608086015180516122f79060028701906020840190613e1f565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612357576002604051631b3fab5160e11b81526004016107f291906159b1565b60408801516123679060036159cb565b60ff168160ff161161238f576003604051631b3fab5160e11b81526004016107f291906159b1565b61239b8783600161334f565b50505b6123aa8583600261334f565b81516123bf9060038601906020850190613e1f565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793612418938a939260028b019291906159e7565b60405180910390a1612429856134cf565b505050505050565b612439613e8d565b835160005b8181101561263e57600060018886846020811061245d5761245d615203565b61246a91901a601b6156d4565b89858151811061247c5761247c615203565b602002602001015189868151811061249657612496615203565b6020026020010151604051600081526020016040526040516124d4949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156124f6573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612557576125576142ca565b6002811115612568576125686142ca565b9052509050600181602001516002811115612585576125856142ca565b146125bc576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f81106125d3576125d3615203565b60200201511561260f576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061262a5761262a615203565b91151560209092020152505060010161243e565b5050505050505050565b815161265381611635565b600061265e82611737565b60208501515190915060008190036126a1576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001515181146126df576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff8111156126fa576126fa6140c3565b604051908082528060200260200182016040528015612723578160200160208202803683370190505b50905060005b828110156128985760008760200151828151811061274957612749615203565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff16146127dc57805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f2565b612872818660010180546127ef9061566a565b80601f016020809104026020016040519081016040528092919081815260200182805461281b9061566a565b80156128685780601f1061283d57610100808354040283529160200191612868565b820191906000526020600020905b81548152906001019060200180831161284b57829003601f168201915b50505050506134eb565b83838151811061288457612884615203565b602090810291909101015250600101612729565b5060006128af858389606001518a6080015161363d565b9050806000036128f7576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016107f2565b8551151560005b848110156109b55760008960200151828151811061291e5761291e615203565b60200260200101519050600061293c89836000015160600151610bfb565b90506002816003811115612952576129526142ca565b036129a9578151606001516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612e62565b60008160038111156129bd576129bd6142ca565b14806129da575060038160038111156129d8576129d86142ca565b145b612a2b578151606001516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016107f2565b8315612b0c5760045460009074010000000000000000000000000000000000000000900463ffffffff16612a5f874261542e565b1190508080612a7f57506003826003811115612a7d57612a7d6142ca565b145b612ac1576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526024016107f2565b8a8481518110612ad357612ad3615203565b6020026020010151600014612b06578a8481518110612af457612af4615203565b60200260200101518360800181815250505b50612b72565b6000816003811115612b2057612b206142ca565b14612b72578151606001516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016107f2565b81516080015167ffffffffffffffff1615801590612ba157506000816003811115612b9f57612b9f6142ca565b145b15612c665781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c18928e929190600401615a6d565b6020604051808303816000875af1158015612c37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5b91906156a4565b612c66575050612e62565b60008b604001518481518110612c7e57612c7e615203565b6020026020010151905080518360a001515114612ce2578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808d16600483015290911660248201526044016107f2565b612cf68a8460000151606001516001613693565b600080612d03858461373b565b91509150612d1a8c86600001516060015184613693565b868015612d3857506003826003811115612d3657612d366142ca565b145b8015612d5657506000846003811115612d5357612d536142ca565b14155b15612d93578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526107f291908390600401615a9a565b6003826003811115612da757612da76142ca565b14158015612dc757506002826003811115612dc457612dc46142ca565b14155b15612e08578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526107f2918e918590600401615ab3565b8451805160609091015160405167ffffffffffffffff918216918f16907f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df290612e549087908790615ad9565b60405180910390a450505050505b6001016128fe565b60408051808201909152600080825260208201526000612e8d8460200151613983565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f369190615af9565b90506001600160a01b0381161580612f7e5750612f7c6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611d0e565b155b15612fc0576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016107f2565b60008061308b633907753760e01b6040518061010001604052808d81526020018b67ffffffffffffffff1681526020018c6001600160a01b031681526020018e8152602001876001600160a01b031681526020018a6000015181526020018a6040015181526020018981525060405160240161303c9190615b16565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600454859063ffffffff600160e01b9091041661138860846139c5565b5091509150816130b0578060405163e1cd550960e01b81526004016107f29190613f11565b80516020146130f85780516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016107f2565b60008180602001905181019061310e9190615bed565b604080516001600160a01b038d16602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526004549192506131a69187907801000000000000000000000000000000000000000000000000900463ffffffff1661138860846139c5565b509093509150826131cc578160405163e1cd550960e01b81526004016107f29190613f11565b604080518082019091526001600160a01b03909516855260208501525091925050509695505050505050565b6000613224827f01ffc9a700000000000000000000000000000000000000000000000000000000613244565b8015610c4b575061323d826001600160e01b0319613244565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132cf575060208210155b80156132db5750600081115b979650505050505050565b60005b815181101561121b5760ff83166000908152600360205260408120835190919084908490811061331b5761331b615203565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016132e9565b60005b82518160ff161015610a23576000838260ff168151811061337557613375615203565b6020026020010151905060006002811115613392576133926142ca565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156133d1576133d16142ca565b146133f2576004604051631b3fab5160e11b81526004016107f291906159b1565b6001600160a01b038116613432576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff168152602001846002811115613458576134586142ca565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156134b5576134b56142ca565b021790555090505050806134c890615c06565b9050613352565b60ff811661107857600a805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613531937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c25565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761357a9794969395929491939101615c58565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016135b19190615cab565b604051602081830303815290604052805190602001208760c001516040516020016135dc9190615d60565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061364b858585613aeb565b905061365681611574565b61366457600091505061368b565b67ffffffffffffffff86166000908152600960209081526040808320938352929052205490505b949350505050565b600060026136a2608085615457565b67ffffffffffffffff166136b6919061547e565b905060006136c48585611c1a565b9050816136d36001600461542e565b901b1916818360038111156136ea576136ea6142ca565b67ffffffffffffffff871660009081526008602052604081209190921b92909217918291613719608088615711565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517f5ffb5ced0000000000000000000000000000000000000000000000000000000081526000906060903090635ffb5ced9061377f9087908790600401615d73565b600060405180830381600087803b15801561379957600080fd5b505af19250505080156137aa575060015b613967573d8080156137d8576040519150601f19603f3d011682016040523d82523d6000602084013e6137dd565b606091505b5060006137e982615e98565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000006001600160e01b031982161480613833575063e1cd550960e01b6001600160e01b03198216145b8061384e575063046b337b60e51b6001600160e01b03198216145b8061388257507f78ef8024000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138b657507f0c3b563c000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138ea57507fae9b4ce9000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b8061391e57507f09c25325000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b1561392f575060039250905061397c565b8551516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526107f291908490600401615a9a565b50506040805160208101909152600081526002905b9250929050565b600081516020146139a9578160405163046b337b60e51b81526004016107f29190613f11565b610c4b828060200190518101906139c09190615bed565b613d8a565b6000606060008361ffff1667ffffffffffffffff8111156139e8576139e86140c3565b6040519080825280601f01601f191660200182016040528015613a12576020820181803683370190505b509150863b613a45577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613a78577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ab1577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613ad45750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b2c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b4057506101018111155b613b5d576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613b87576040516309bde33960e01b815260040160405180910390fd5b80600003613bb45786600081518110613ba257613ba2615203565b60200260200101519350505050613d83565b60008167ffffffffffffffff811115613bcf57613bcf6140c3565b604051908082528060200260200182016040528015613bf8578160200160208202803683370190505b50905060008080805b85811015613d225760006001821b8b811603613c5c5788851015613c45578c5160018601958e918110613c3657613c36615203565b60200260200101519050613c7e565b8551600185019487918110613c3657613c36615203565b8b5160018401938d918110613c7357613c73615203565b602002602001015190505b600089861015613cae578d5160018701968f918110613c9f57613c9f615203565b60200260200101519050613cd0565b8651600186019588918110613cc557613cc5615203565b602002602001015190505b82851115613cf1576040516309bde33960e01b815260040160405180910390fd5b613cfb8282613dde565b878481518110613d0d57613d0d615203565b60209081029190910101525050600101613c01565b506001850382148015613d3457508683145b8015613d3f57508581145b613d5c576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613d7157613d71615203565b60200260200101519750505050505050505b9392505050565b60006001600160a01b03821180613da2575061040082105b15613dda5760408051602081018490520160408051601f198184030181529082905263046b337b60e51b82526107f291600401613f11565b5090565b6000818310613df657613df18284613dfc565b610c48565b610c4883835b60408051600160208201529081018390526060810182905260009060800161361f565b828054828255906000526020600020908101928215613e81579160200282015b82811115613e81578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e3f565b50613dda929150613eac565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613dda5760008155600101613ead565b60005b83811015613edc578181015183820152602001613ec4565b50506000910152565b60008151808452613efd816020860160208601613ec1565b601f01601f19169290920160200192915050565b602081526000610c486020830184613ee5565b8060608101831015610c4b57600080fd5b60008083601f840112613f4757600080fd5b50813567ffffffffffffffff811115613f5f57600080fd5b60208301915083602082850101111561397c57600080fd5b60008083601f840112613f8957600080fd5b50813567ffffffffffffffff811115613fa157600080fd5b6020830191508360208260051b850101111561397c57600080fd5b60008060008060008060008060e0898b031215613fd857600080fd5b613fe28a8a613f24565b9750606089013567ffffffffffffffff80821115613fff57600080fd5b61400b8c838d01613f35565b909950975060808b013591508082111561402457600080fd5b6140308c838d01613f77565b909750955060a08b013591508082111561404957600080fd5b506140568b828c01613f77565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561408457600080fd5b61408e8585613f24565b9250606084013567ffffffffffffffff8111156140aa57600080fd5b6140b686828701613f35565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156140fc576140fc6140c3565b60405290565b60405160a0810167ffffffffffffffff811182821017156140fc576140fc6140c3565b6040805190810167ffffffffffffffff811182821017156140fc576140fc6140c3565b60405160e0810167ffffffffffffffff811182821017156140fc576140fc6140c3565b6040516060810167ffffffffffffffff811182821017156140fc576140fc6140c3565b604051601f8201601f1916810167ffffffffffffffff811182821017156141b7576141b76140c3565b604052919050565b6001600160a01b038116811461107857600080fd5b80356141df816141bf565b919050565b803563ffffffff811681146141df57600080fd5b600060c0828403121561420a57600080fd5b6142126140d9565b823561421d816141bf565b815261422b602084016141e4565b602082015261423c604084016141e4565b604082015261424d606084016141e4565b60608201526080830135614260816141bf565b608082015260a0830135614273816141bf565b60a08201529392505050565b803567ffffffffffffffff811681146141df57600080fd5b600080604083850312156142aa57600080fd5b6142b38361427f565b91506142c16020840161427f565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106142f0576142f06142ca565b9052565b60208101610c4b82846142e0565b600060a0828403121561431457600080fd5b61431c614102565b90508135815261432e6020830161427f565b602082015261433f6040830161427f565b60408201526143506060830161427f565b60608201526143616080830161427f565b608082015292915050565b600067ffffffffffffffff821115614386576143866140c3565b50601f01601f191660200190565b600082601f8301126143a557600080fd5b81356143b86143b38261436c565b61418e565b8181528460208386010111156143cd57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115614404576144046140c3565b5060051b60200190565b600082601f83011261441f57600080fd5b8135602061442f6143b3836143ea565b82815260069290921b8401810191818101908684111561444e57600080fd5b8286015b84811015611d03576040818903121561446b5760008081fd5b614473614125565b813561447e816141bf565b81528185013585820152835291830191604001614452565b600082601f8301126144a757600080fd5b813560206144b76143b3836143ea565b82815260059290921b840181019181810190868411156144d657600080fd5b8286015b84811015611d0357803567ffffffffffffffff8111156144fa5760008081fd5b6145088986838b0101614394565b8452509183019183016144da565b6000610160828403121561452957600080fd5b614531614148565b905061453d8383614302565b815260a082013567ffffffffffffffff8082111561455a57600080fd5b61456685838601614394565b602084015260c084013591508082111561457f57600080fd5b61458b85838601614394565b604084015261459c60e085016141d4565b606084015261010084013560808401526101208401359150808211156145c157600080fd5b6145cd8583860161440e565b60a08401526101408401359150808211156145e757600080fd5b506145f484828501614496565b60c08301525092915050565b6000806040838503121561461357600080fd5b823567ffffffffffffffff8082111561462b57600080fd5b61463786838701614516565b9350602085013591508082111561464d57600080fd5b5061465a85828601614496565b9150509250929050565b60006020828403121561467657600080fd5b813567ffffffffffffffff81111561468d57600080fd5b820160a08185031215613d8357600080fd5b801515811461107857600080fd5b80356141df8161469f565b600060208083850312156146cb57600080fd5b823567ffffffffffffffff808211156146e357600080fd5b818501915085601f8301126146f757600080fd5b81356147056143b3826143ea565b81815260059190911b8301840190848101908883111561472457600080fd5b8585015b838110156147b4578035858111156147405760008081fd5b86016060818c03601f19018113156147585760008081fd5b61476061416b565b61476b8a840161427f565b815260408084013561477c8161469f565b828c01529183013591888311156147935760008081fd5b6147a18e8c85870101614394565b9082015285525050918601918601614728565b5098975050505050505050565b600082601f8301126147d257600080fd5b813560206147e26143b3836143ea565b82815260059290921b8401810191818101908684111561480157600080fd5b8286015b84811015611d0357803567ffffffffffffffff8111156148255760008081fd5b6148338986838b0101614516565b845250918301918301614805565b600082601f83011261485257600080fd5b813560206148626143b3836143ea565b82815260059290921b8401810191818101908684111561488157600080fd5b8286015b84811015611d0357803567ffffffffffffffff8111156148a55760008081fd5b6148b38986838b0101614496565b845250918301918301614885565b600082601f8301126148d257600080fd5b813560206148e26143b3836143ea565b8083825260208201915060208460051b87010193508684111561490457600080fd5b602086015b84811015611d035780358352918301918301614909565b600082601f83011261493157600080fd5b813560206149416143b3836143ea565b82815260059290921b8401810191818101908684111561496057600080fd5b8286015b84811015611d0357803567ffffffffffffffff808211156149855760008081fd5b818901915060a080601f19848d030112156149a05760008081fd5b6149a8614102565b6149b388850161427f565b8152604080850135848111156149c95760008081fd5b6149d78e8b838901016147c1565b8a84015250606080860135858111156149f05760008081fd5b6149fe8f8c838a0101614841565b8385015250608091508186013585811115614a195760008081fd5b614a278f8c838a01016148c1565b9184019190915250919093013590830152508352918301918301614964565b6000806040808486031215614a5a57600080fd5b833567ffffffffffffffff80821115614a7257600080fd5b614a7e87838801614920565b9450602091508186013581811115614a9557600080fd5b8601601f81018813614aa657600080fd5b8035614ab46143b3826143ea565b81815260059190911b8201840190848101908a831115614ad357600080fd5b8584015b83811015614b5f57803586811115614aef5760008081fd5b8501603f81018d13614b015760008081fd5b87810135614b116143b3826143ea565b81815260059190911b82018a0190898101908f831115614b315760008081fd5b928b01925b82841015614b4f5783358252928a0192908a0190614b36565b8652505050918601918601614ad7565b50809750505050505050509250929050565b803560ff811681146141df57600080fd5b600060208284031215614b9457600080fd5b610c4882614b71565b60008151808452602080850194506020840160005b83811015614bd75781516001600160a01b031687529582019590820190600101614bb2565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c3160e0840182614b9d565b90506040840151601f198483030160c0850152614c4e8282614b9d565b95945050505050565b60008060408385031215614c6a57600080fd5b614c738361427f565b946020939093013593505050565b60008060208385031215614c9457600080fd5b823567ffffffffffffffff80821115614cac57600080fd5b818501915085601f830112614cc057600080fd5b813581811115614ccf57600080fd5b8660208260061b8501011115614ce457600080fd5b60209290920196919550909350505050565b600060208284031215614d0857600080fd5b610c488261427f565b6020815281511515602082015267ffffffffffffffff60208301511660408201526000604083015160608084015261368b6080840182613ee5565b600060208284031215614d5e57600080fd5b8135613d83816141bf565b600082601f830112614d7a57600080fd5b81356020614d8a6143b3836143ea565b8083825260208201915060208460051b870101935086841115614dac57600080fd5b602086015b84811015611d03578035614dc4816141bf565b8352918301918301614db1565b60006020808385031215614de457600080fd5b823567ffffffffffffffff80821115614dfc57600080fd5b818501915085601f830112614e1057600080fd5b8135614e1e6143b3826143ea565b81815260059190911b83018401908481019088831115614e3d57600080fd5b8585015b838110156147b457803585811115614e5857600080fd5b860160c0818c03601f19011215614e6f5760008081fd5b614e776140d9565b8882013581526040614e8a818401614b71565b8a8301526060614e9b818501614b71565b8284015260809150614eae8285016146ad565b9083015260a08381013589811115614ec65760008081fd5b614ed48f8d83880101614d69565b838501525060c0840135915088821115614eee5760008081fd5b614efc8e8c84870101614d69565b9083015250845250918601918601614e41565b600060208284031215614f2157600080fd5b5035919050565b80356001600160e01b03811681146141df57600080fd5b600082601f830112614f5057600080fd5b81356020614f606143b3836143ea565b82815260069290921b84018101918181019086841115614f7f57600080fd5b8286015b84811015611d035760408189031215614f9c5760008081fd5b614fa4614125565b614fad8261427f565b8152614fba858301614f28565b81860152835291830191604001614f83565b600082601f830112614fdd57600080fd5b81356020614fed6143b3836143ea565b82815260079290921b8401810191818101908684111561500c57600080fd5b8286015b84811015611d0357808803608081121561502a5760008081fd5b61503261416b565b61503b8361427f565b8152604080601f19840112156150515760008081fd5b615059614125565b925061506687850161427f565b835261507381850161427f565b8388015281870192909252606083013591810191909152835291830191608001615010565b600060208083850312156150ab57600080fd5b823567ffffffffffffffff808211156150c357600080fd5b818501915060408083880312156150d957600080fd5b6150e1614125565b8335838111156150f057600080fd5b84016040818a03121561510257600080fd5b61510a614125565b81358581111561511957600080fd5b8201601f81018b1361512a57600080fd5b80356151386143b3826143ea565b81815260069190911b8201890190898101908d83111561515757600080fd5b928a01925b828410156151a75787848f0312156151745760008081fd5b61517c614125565b8435615187816141bf565b8152615194858d01614f28565b818d0152825292870192908a019061515c565b8452505050818701359350848411156151bf57600080fd5b6151cb8a858401614f3f565b81880152825250838501359150828211156151e557600080fd5b6151f188838601614fcc565b85820152809550505050505092915050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561527057835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615239565b50508583015187820388850152805180835290840192506000918401905b808310156152ca578351805167ffffffffffffffff1683528501516001600160e01b03168583015292840192600192909201919085019061528e565b50979650505050505050565b602081526000610c486020830184615219565b67ffffffffffffffff8316815260608101613d836020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153555761535561531e565b5092915050565b60006020808352606084516040808487015261537b6060870183615219565b87850151878203601f19016040890152805180835290860193506000918601905b808310156147b457845167ffffffffffffffff8151168352878101516153db89850182805167ffffffffffffffff908116835260209182015116910152565b5084015182870152938601936001929092019160809091019061539c565b60006020828403121561540b57600080fd5b813567ffffffffffffffff81111561542257600080fd5b61368b84828501614920565b81810381811115610c4b57610c4b61531e565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061547257615472615441565b92169190910692915050565b8082028115828204841417610c4b57610c4b61531e565b60008151808452602080850194506020840160005b83811015614bd757815180516001600160a01b0316885260209081015190880152604087019650908201906001016154aa565b8051825267ffffffffffffffff60208201511660208301526000604082015160a0604085015261551060a0850182613ee5565b9050606083015184820360608601526155298282613ee5565b91505060808301518482036080860152614c4e8282615495565b602081526000610c4860208301846154dd565b60808152600061556960808301876154dd565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b600082601f8301126155a357600080fd5b81516155b16143b38261436c565b8181528460208386010111156155c657600080fd5b61368b826020830160208701613ec1565b6000806000606084860312156155ec57600080fd5b83516155f78161469f565b602085015190935067ffffffffffffffff81111561561457600080fd5b61562086828701615592565b925050604084015190509250925092565b60006040828403121561564357600080fd5b61564b614125565b6156548361427f565b8152602083013560208201528091505092915050565b600181811c9082168061567e57607f821691505b60208210810361569e57634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156156b657600080fd5b8151613d838161469f565b80820180821115610c4b57610c4b61531e565b60ff8181168382160190811115610c4b57610c4b61531e565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff8084168061572c5761572c615441565b92169190910492915050565b60006020828403121561574a57600080fd5b815167ffffffffffffffff8082111561576257600080fd5b908301906060828603121561577657600080fd5b61577e61416b565b82518281111561578d57600080fd5b61579987828601615592565b8252506020830151828111156157ae57600080fd5b6157ba87828601615592565b6020830152506040830151828111156157d257600080fd5b6157de87828601615592565b60408301525095945050505050565b601f82111561121b576000816000526020600020601f850160051c810160208610156158165750805b601f850160051c820191505b8181101561242957828155600101615822565b815167ffffffffffffffff81111561584f5761584f6140c3565b6158638161585d845461566a565b846157ed565b602080601f83116001811461589857600084156158805750858301515b600019600386901b1c1916600185901b178555612429565b600085815260208120601f198616915b828110156158c7578886015182559484019460019091019084016158a8565b50858210156158e55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020808352835460ff81161515602085015267ffffffffffffffff8160081c166040850152506001808501606080860152600081546159358161566a565b80608089015260a060018316600081146159565760018114615972576159a2565b60ff19841660a08b015260a083151560051b8b010194506159a2565b85600052602060002060005b848110156159995781548c820185015290880190890161597e565b8b0160a0019550505b50929998505050505050505050565b60208101600583106159c5576159c56142ca565b91905290565b60ff81811683821602908116908181146153555761535561531e565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015615a415784546001600160a01b031683526001948501949284019201615a1c565b50508481036060860152615a558188614b9d565b935050505060ff831660808301529695505050505050565b600067ffffffffffffffff808616835280851660208401525060606040830152614c4e6060830184613ee5565b82815260406020820152600061368b6040830184613ee5565b67ffffffffffffffff8481168252831660208201526060810161368b60408301846142e0565b615ae381846142e0565b60406020820152600061368b6040830184613ee5565b600060208284031215615b0b57600080fd5b8151613d83816141bf565b6020815260008251610100806020850152615b35610120850183613ee5565b91506020850151615b52604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615b8c60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615ba98483613ee5565b935060c08701519150808685030160e0870152615bc68483613ee5565b935060e0870151915080868503018387015250615be38382613ee5565b9695505050505050565b600060208284031215615bff57600080fd5b5051919050565b600060ff821660ff8103615c1c57615c1c61531e565b60010192915050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152615be36080830184613ee5565b86815260c060208201526000615c7160c0830188613ee5565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b6020808252825182820181905260009190848201906040850190845b81811015615cfa57835180516001600160a01b031684526020908101519084015260408301938501939250600101615cc7565b50909695505050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015615d5357601f19868403018952615d41838351613ee5565b98840198925090830190600101615d25565b5090979650505050505050565b602081526000610c486020830184615d06565b60408152615dc460408201845180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208401516101608060e0850152615de26101a0850183613ee5565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615e1f8483613ee5565b935060608801519150615e3e6101208701836001600160a01b03169052565b608088015161014087015260a08801519150808685030183870152615e638483615495565b935060c0880151925080868503016101808701525050615e838282615d06565b9150508281036020840152614c4e8185615d06565b6000815160208301516001600160e01b031980821693506004831015615ec85780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", + 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\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"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\":\"error\",\"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\":\"structEVM2EVMMultiOffRamp.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\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"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\":\"error\",\"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\":[{\"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\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\"}],\"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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.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\":\"structEVM2EVMMultiOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"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\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.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: "0x6101206040523480156200001257600080fd5b506040516200690e3803806200690e8339810160408190526200003591620005bd565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001ee565b5050466080525060208201516001600160a01b03161580620000ec575060408201516001600160a01b0316155b8062000103575060608201516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b81516001600160401b0390811660a052602080840180516001600160a01b0390811660c05260408087018051831660e0526060808901805185166101005283518a519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e68162000299565b505062000a03565b336001600160a01b03821603620002485760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015620004eb576000828281518110620002bd57620002bd620007cc565b60200260200101519050600081600001519050806001600160401b0316600003620002fb5760405163c656089560e01b815260040160405180910390fd5b6001600160401b03811660009081526007602052604081206001810180549192916200032790620007e2565b80601f01602080910402602001604051908101604052809291908181526020018280546200035590620007e2565b8015620003a65780601f106200037a57610100808354040283529160200191620003a6565b820191906000526020600020905b8154815290600101906020018083116200038857829003601f168201915b50505050509050600084604001519050815160000362000449578051600003620003e3576040516342bcdf7f60e11b815260040160405180910390fd5b60018301620003f3828262000873565b508254610100600160481b0319166101001783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a162000484565b8080519060200120828051906020012014620004845760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b6020850151835460ff19169015151783556040516001600160401b038516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba90620004d29086906200093f565b60405180910390a250505050508060010190506200029c565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200052a576200052a620004ef565b60405290565b604051606081016001600160401b03811182821017156200052a576200052a620004ef565b604051601f8201601f191681016001600160401b0381118282101715620005805762000580620004ef565b604052919050565b80516001600160401b0381168114620005a057600080fd5b919050565b80516001600160a01b0381168114620005a057600080fd5b60008082840360a0811215620005d257600080fd5b6080811215620005e157600080fd5b50620005ec62000505565b620005f78462000588565b8152602062000608818601620005a5565b818301526200061a60408601620005a5565b60408301526200062d60608601620005a5565b606083015260808501519193506001600160401b03808311156200065057600080fd5b828601925086601f8401126200066557600080fd5b8251818111156200067a576200067a620004ef565b8060051b6200068b84820162000555565b918252848101840191848101908a841115620006a657600080fd5b85870192505b83831015620007bb57825185811115620006c557600080fd5b8701601f196060828e0382011215620006dd57600080fd5b620006e762000530565b620006f489840162000588565b8152604083015180151581146200070a57600080fd5b818a01526060830151888111156200072157600080fd5b8084019350508d603f8401126200073757600080fd5b88830151888111156200074e576200074e620004ef565b620007608a84601f8401160162000555565b92508083528e60408286010111156200077857600080fd5b60005b818110156200079957848101604001518482018c01528a016200077b565b5060009083018a015260408101919091528352509185019190850190620006ac565b809750505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620007f757607f821691505b6020821081036200081857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200086e576000816000526020600020601f850160051c81016020861015620008495750805b601f850160051c820191505b818110156200086a5782815560010162000855565b5050505b505050565b81516001600160401b038111156200088f576200088f620004ef565b620008a781620008a08454620007e2565b846200081e565b602080601f831160018114620008df5760008415620008c65750858301515b600019600386901b1c1916600185901b1785556200086a565b600085815260208120601f198616915b828110156200091057888601518255948401946001909101908401620008ef565b50858210156200092f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020808252825460ff811615158383015260081c6001600160401b031660408301526060808301526001808401805460009392919084906200098181620007e2565b80608089015260a06001831660008114620009a55760018114620009c257620009f4565b60ff19841660a08b015260a083151560051b8b01019450620009f4565b85600052602060002060005b84811015620009eb5781548c8201850152908801908901620009ce565b8b0160a0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615e9c62000a726000396000818161023e0152612c0d01526000818161020f0152612ef70152600081816101e0015281816115c5015261167c0152600081816101b00152612781015260008181611c5f0152611cab0152615e9c6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063d2a15d351161008c578063f2fde38b11610066578063f2fde38b146105b1578063f716f99f146105c4578063ff888fb1146105d757600080fd5b8063d2a15d351461056b578063e9d68a8e1461057e578063ece670b61461059e57600080fd5b8063a12a9870116100bd578063a12a9870146104f3578063c673e58414610506578063ccd37ba31461052657600080fd5b806385572ffb146104ca5780638da5cb5b146104d857600080fd5b8063403b2d631161012f5780637437ff9f116101145780637437ff9f1461038557806379ba5097146104af5780637d4eef60146104b757600080fd5b8063403b2d63146103525780635e36480c1461036557600080fd5b80632d04ab76116101605780632d04ab761461030e578063311cd513146103235780633f4b04aa1461033657600080fd5b806306285c691461017c578063181f5a77146102c5575b600080fd5b61026e60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102bc9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103016040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b6040516102bc9190613f10565b61032161031c366004613fbb565b6105fa565b005b61032161033136600461406e565b6109c0565b600a5460405167ffffffffffffffff90911681526020016102bc565b6103216103603660046141f7565b610a29565b610378610373366004614296565b610bfb565b6040516102bc91906142f3565b6104466040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526004546001600160a01b03808216835263ffffffff7401000000000000000000000000000000000000000083048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b90910490921660608201526005548216608082015260065490911660a082015290565b6040516102bc9190600060c0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401528060a08501511660a08401525092915050565b610321610c51565b6103216104c53660046148f7565b610d0f565b610321610177366004614a22565b6000546040516001600160a01b0390911681526020016102bc565b610321610501366004614a76565b610eb4565b610519610514366004614b90565b610ec8565b6040516102bc9190614bf0565b61055d610534366004614c65565b67ffffffffffffffff919091166000908152600960209081526040808320938352929052205490565b6040519081526020016102bc565b610321610579366004614c8f565b611026565b61059161058c366004614d04565b6110e0565b6040516102bc9190614d1f565b6103216105ac366004614d5a565b6111c9565b6103216105bf366004614dbe565b61151c565b6103216105d2366004614e43565b61152d565b6105ea6105e5366004614f81565b61156f565b60405190151581526020016102bc565b60006106088789018961510a565b8051515190915015158061062157508051602001515115155b1561072157600a5460208a01359067ffffffffffffffff808316911610156106e057600a805467ffffffffffffffff191667ffffffffffffffff831617905560065482516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691633937306f916106a991600401615348565b600060405180830381600087803b1580156106c357600080fd5b505af11580156106d7573d6000803e3d6000fd5b5050505061071f565b81602001515160000361071f576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b8160200151518110156109095760008260200151828151811061074957610749615275565b6020026020010151905060008160000151905061076581611630565b600061077082611732565b602084015151815491925067ffffffffffffffff908116610100909204161415806107b2575060208084015190810151905167ffffffffffffffff9182169116115b156107fb57825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526107f292919060040161535b565b60405180910390fd5b604083015180610837576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff166000908152600960209081526040808320848452909152902054156108aa5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016107f2565b60208085015101516108bd9060016153a6565b825468ffffffffffffffff00191661010067ffffffffffffffff928316021790925592511660009081526009602090815260408083209483529390529190912042905550600101610724565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d8160405161093991906153ce565b60405180910390a16109b560008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611792915050565b505050505050505050565b610a006109cf8284018461546b565b60408051600080825260208201909252906109fa565b60608152602001906001900390816109e55790505b50611b09565b604080516000808252602082019092529050610a23600185858585866000611792565b50505050565b610a31611bb9565b60a08101516001600160a01b03161580610a53575080516001600160a01b0316155b15610a8a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a177401000000000000000000000000000000000000000063ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff19908116928e1692909217905560a0808e01805160068054909416908f161790925586519a8b5297518716988a0198909852925185169388019390935251909216958501959095525185169383019390935251909216908201527f0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c9060c00160405180910390a150565b6000610c09600160046154a0565b6002610c166080856154c9565b67ffffffffffffffff16610c2a91906154f0565b610c348585611c15565b901c166003811115610c4857610c486142c9565b90505b92915050565b6001546001600160a01b03163314610cab5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016107f2565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d17611c5c565b815181518114610d53576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610ea4576000848281518110610d7257610d72615275565b60200260200101519050600081602001515190506000858481518110610d9a57610d9a615275565b6020026020010151905080518214610dde576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610e95576000828281518110610dfd57610dfd615275565b6020026020010151905080600014158015610e38575084602001518281518110610e2957610e29615275565b60200260200101516080015181105b15610e8c5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064016107f2565b50600101610de1565b50505050806001019050610d56565b50610eaf8383611b09565b505050565b610ebc611bb9565b610ec581611cdd565b50565b610f0b6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610fb457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f96575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561101657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ff8575b5050505050815250509050919050565b61102e611bb9565b60005b81811015610eaf57600083838381811061104d5761104d615275565b9050604002018036038101906110639190615507565b9050611072816020015161156f565b6110d757805167ffffffffffffffff1660009081526009602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b50600101611031565b60408051606080820183526000808352602080840182905283850183905267ffffffffffffffff8681168352600782529185902085519384018652805460ff81161515855261010090049092169083015260018101805493949293919284019161114990615540565b80601f016020809104026020016040519081016040528092919081815260200182805461117590615540565b80156110165780601f1061119757610100808354040283529160200191611016565b820191906000526020600020905b8154815290600101906020018083116111a557505050919092525091949350505050565b333014611202576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516000808252602082019092528161123f565b60408051808201909152600080825260208201528152602001906001900390816112185790505b5060a084015151909150156112725761126f8360a001518460200151856060015186600001516020015186611f69565b90505b6040805160a0810182528451518152845160209081015167ffffffffffffffff16818301528086015183516000948401926112ae929101613f10565b60408051601f19818403018152918152908252868101516020830152018390526005549091506001600160a01b031680156113bb576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a19061132890859060040161561c565b600060405180830381600087803b15801561134257600080fd5b505af1925050508015611353575060015b6113bb573d808015611381576040519150601f19603f3d011682016040523d82523d6000602084013e611386565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107f29190613f10565b6040850151511580156113d057506080850151155b806113e7575060608501516001600160a01b03163b155b8061142757506060850151611425906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000612047565b155b15611433575050505050565b60048054608087015160608801516040517f3cf9798300000000000000000000000000000000000000000000000000000000815260009485946001600160a01b031693633cf979839361148e938a936113889392910161562f565b6000604051808303816000875af11580156114ad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114d5919081019061566b565b50915091508161151357806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107f29190613f10565b50505050505050565b611524611bb9565b610ec581612063565b611535611bb9565b60005b815181101561156b5761156382828151811061155657611556615275565b6020026020010151612119565b600101611538565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa15801561160c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b9190615701565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190615701565b15610ec5576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016107f2565b67ffffffffffffffff81166000908152600760205260408120805460ff16610c4b576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016107f2565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117f18760a461571e565b905082606001511561183957845161180a9060206154f0565b86516118179060206154f0565b6118229060a061571e565b61182c919061571e565b611836908261571e565b90505b36811461187b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016107f2565b50815181146118c35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107f2565b6118cb611c5c565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611919576119196142c9565b600281111561192a5761192a6142c9565b9052509050600281602001516002811115611947576119476142c9565b14801561199b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061198357611983615275565b6000918252602090912001546001600160a01b031633145b6119d1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611ab35760208201516119ec906001615731565b60ff16855114611a28576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611a63576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611a7592919061574a565b604051908190038120611a8c918b9060200161575a565b604051602081830303815290604052805190602001209050611ab18a8288888861245d565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611b43576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611bb257611baa858281518110611b7857611b78615275565b602002602001015184611ba457858381518110611b9757611b97615275565b6020026020010151612674565b83612674565b600101611b5a565b5050505050565b6000546001600160a01b03163314611c135760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107f2565b565b67ffffffffffffffff8216600090815260086020526040812081611c3a60808561576e565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b467f000000000000000000000000000000000000000000000000000000000000000014611c13576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107f2565b60005b815181101561156b576000828281518110611cfd57611cfd615275565b602002602001015190506000816000015190508067ffffffffffffffff16600003611d54576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600760205260408120600181018054919291611d7f90615540565b80601f0160208091040260200160405190810160405280929190818152602001828054611dab90615540565b8015611df85780601f10611dcd57610100808354040283529160200191611df8565b820191906000526020600020905b815481529060010190602001808311611ddb57829003601f168201915b505050505090506000846040015190508151600003611eb1578051600003611e4c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301611e5a82826157dd565b50825468ffffffffffffffff00191661010017835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611f04565b8080519060200120828051906020012014611f04576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016107f2565b6020850151835460ff191690151517835560405167ffffffffffffffff8516907f4f49973170c548fddd4a48341b75e131818913f38f44d47af57e8735eee588ba90611f5190869061589d565b60405180910390a25050505050806001019050611ce0565b6060855167ffffffffffffffff811115611f8557611f856140c2565b604051908082528060200260200182016040528015611fca57816020015b6040805180820190915260008082526020820152815260200190600190039081611fa35790505b50905060005b865181101561203d57612018878281518110611fee57611fee615275565b602002602001015187878787868151811061200b5761200b615275565b6020026020010151612e96565b82828151811061202a5761202a615275565b6020908102919091010152600101611fd0565b5095945050505050565b600061205283613227565b8015610c485750610c488383613273565b336001600160a01b038216036120bb5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107f2565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003612144576000604051631b3fab5160e11b81526004016107f29190615959565b60208082015160ff808216600090815260029093526040832060018101549293909283921690036121b157606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612206565b6060840151600182015460ff6201000090910416151590151514612206576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016107f2565b60a08401518051601f60ff82161115612235576001604051631b3fab5160e11b81526004016107f29190615959565b61229b858560030180548060200260200160405190810160405280929190818152602001828054801561229157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612273575b5050505050613315565b8560600151156123ca576123098585600201805480602002602001604051908101604052809291908181526020018280548015612291576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311612273575050505050613315565b608086015180516123239060028701906020840190613e1e565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612383576002604051631b3fab5160e11b81526004016107f29190615959565b6040880151612393906003615973565b60ff168160ff16116123bb576003604051631b3fab5160e11b81526004016107f29190615959565b6123c78783600161337e565b50505b6123d68583600261337e565b81516123eb9060038601906020850190613e1e565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793612444938a939260028b0192919061598f565b60405180910390a1612455856134fe565b505050505050565b612465613e8c565b835160005b8181101561266a57600060018886846020811061248957612489615275565b61249691901a601b615731565b8985815181106124a8576124a8615275565b60200260200101518986815181106124c2576124c2615275565b602002602001015160405160008152602001604052604051612500949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612522573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612583576125836142c9565b6002811115612594576125946142c9565b90525090506001816020015160028111156125b1576125b16142c9565b146125e8576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f81106125ff576125ff615275565b60200201511561263b576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061265657612656615275565b91151560209092020152505060010161246a565b5050505050505050565b815161267f81611630565b600061268a82611732565b60208501515190915060008190036126cd576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461270b576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff811115612726576127266140c2565b60405190808252806020026020018201604052801561274f578160200160208202803683370190505b50905060005b828110156128c45760008760200151828151811061277557612775615275565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461280857805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f2565b61289e8186600101805461281b90615540565b80601f016020809104026020016040519081016040528092919081815260200182805461284790615540565b80156128945780601f1061286957610100808354040283529160200191612894565b820191906000526020600020905b81548152906001019060200180831161287757829003601f168201915b505050505061351a565b8383815181106128b0576128b0615275565b602090810291909101015250600101612755565b5060006128db858389606001518a6080015161363c565b905080600003612923576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016107f2565b8551151560005b848110156109b55760008960200151828151811061294a5761294a615275565b60200260200101519050600061296889836000015160600151610bfb565b9050600281600381111561297e5761297e6142c9565b036129d5578151606001516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612e8e565b60008160038111156129e9576129e96142c9565b1480612a0657506003816003811115612a0457612a046142c9565b145b612a57578151606001516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016107f2565b8315612b385760045460009074010000000000000000000000000000000000000000900463ffffffff16612a8b87426154a0565b1190508080612aab57506003826003811115612aa957612aa96142c9565b145b612aed576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526024016107f2565b8a8481518110612aff57612aff615275565b6020026020010151600014612b32578a8481518110612b2057612b20615275565b60200260200101518360800181815250505b50612b9e565b6000816003811115612b4c57612b4c6142c9565b14612b9e578151606001516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016107f2565b81516080015167ffffffffffffffff1615801590612bcd57506000816003811115612bcb57612bcb6142c9565b145b15612c925781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c44928e929190600401615a15565b6020604051808303816000875af1158015612c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c879190615701565b612c92575050612e8e565b60008b604001518481518110612caa57612caa615275565b6020026020010151905080518360a001515114612d0e578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808d16600483015290911660248201526044016107f2565b612d228a8460000151606001516001613692565b600080612d2f858461373a565b91509150612d468c86600001516060015184613692565b868015612d6457506003826003811115612d6257612d626142c9565b145b8015612d8257506000846003811115612d7f57612d7f6142c9565b14155b15612dbf578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526107f291908390600401615a42565b6003826003811115612dd357612dd36142c9565b14158015612df357506002826003811115612df057612df06142c9565b14155b15612e34578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526107f2918e918590600401615a5b565b8451805160609091015160405167ffffffffffffffff918216918f16907f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df290612e809087908790615a81565b60405180910390a450505050505b60010161292a565b60408051808201909152600080825260208201526000612eb98760200151613982565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f629190615aa1565b90506001600160a01b0381161580612faa5750612fa86001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000612047565b155b15612fec576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016107f2565b6000806130bb633907753760e01b6040518061010001604052808c81526020018a67ffffffffffffffff1681526020018b6001600160a01b031681526020018d606001518152602001876001600160a01b031681526020018d6000015181526020018d6040015181526020018981525060405160240161306c9190615abe565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600454859063ffffffff600160e01b9091041661138860846139c4565b5091509150816130e0578060405163e1cd550960e01b81526004016107f29190613f10565b80516020146131285780516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016107f2565b60008180602001905181019061313e9190615b95565b604080516001600160a01b038c16602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526004549192506131d69187907801000000000000000000000000000000000000000000000000900463ffffffff1661138860846139c4565b509093509150826131fc578160405163e1cd550960e01b81526004016107f29190613f10565b604080518082019091526001600160a01b039095168552602085015250919250505095945050505050565b6000613253827f01ffc9a700000000000000000000000000000000000000000000000000000000613273565b8015610c4b575061326c826001600160e01b0319613273565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132fe575060208210155b801561330a5750600081115b979650505050505050565b60005b8151811015610eaf5760ff83166000908152600360205260408120835190919084908490811061334a5761334a615275565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613318565b60005b82518160ff161015610a23576000838260ff16815181106133a4576133a4615275565b60200260200101519050600060028111156133c1576133c16142c9565b60ff80871660009081526003602090815260408083206001600160a01b03871684529091529020546101009004166002811115613400576134006142c9565b14613421576004604051631b3fab5160e11b81526004016107f29190615959565b6001600160a01b038116613461576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff168152602001846002811115613487576134876142c9565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156134e4576134e46142c9565b021790555090505050806134f790615bae565b9050613381565b60ff8116610ec557600a805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613560937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615bcd565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135a99794969395929491939101615c00565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016135e09190615cf7565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061364a858585613aea565b90506136558161156f565b61366357600091505061368a565b67ffffffffffffffff86166000908152600960209081526040808320938352929052205490505b949350505050565b600060026136a16080856154c9565b67ffffffffffffffff166136b591906154f0565b905060006136c38585611c15565b9050816136d2600160046154a0565b901b1916818360038111156136e9576136e96142c9565b67ffffffffffffffff871660009081526008602052604081209190921b9290921791829161371860808861576e565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fece670b6000000000000000000000000000000000000000000000000000000008152600090606090309063ece670b69061377e9087908790600401615d57565b600060405180830381600087803b15801561379857600080fd5b505af19250505080156137a9575060015b613966573d8080156137d7576040519150601f19603f3d011682016040523d82523d6000602084013e6137dc565b606091505b5060006137e882615e57565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000006001600160e01b031982161480613832575063e1cd550960e01b6001600160e01b03198216145b8061384d575063046b337b60e51b6001600160e01b03198216145b8061388157507f78ef8024000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138b557507f0c3b563c000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b806138e957507fae9b4ce9000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b8061391d57507f09c25325000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b1561392e575060039250905061397b565b8551516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526107f291908490600401615a42565b50506040805160208101909152600081526002905b9250929050565b600081516020146139a8578160405163046b337b60e51b81526004016107f29190613f10565b610c4b828060200190518101906139bf9190615b95565b613d89565b6000606060008361ffff1667ffffffffffffffff8111156139e7576139e76140c2565b6040519080825280601f01601f191660200182016040528015613a11576020820181803683370190505b509150863b613a44577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613a77577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ab0577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613ad35750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b2b576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b3f57506101018111155b613b5c576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613b86576040516309bde33960e01b815260040160405180910390fd5b80600003613bb35786600081518110613ba157613ba1615275565b60200260200101519350505050613d82565b60008167ffffffffffffffff811115613bce57613bce6140c2565b604051908082528060200260200182016040528015613bf7578160200160208202803683370190505b50905060008080805b85811015613d215760006001821b8b811603613c5b5788851015613c44578c5160018601958e918110613c3557613c35615275565b60200260200101519050613c7d565b8551600185019487918110613c3557613c35615275565b8b5160018401938d918110613c7257613c72615275565b602002602001015190505b600089861015613cad578d5160018701968f918110613c9e57613c9e615275565b60200260200101519050613ccf565b8651600186019588918110613cc457613cc4615275565b602002602001015190505b82851115613cf0576040516309bde33960e01b815260040160405180910390fd5b613cfa8282613ddd565b878481518110613d0c57613d0c615275565b60209081029190910101525050600101613c00565b506001850382148015613d3357508683145b8015613d3e57508581145b613d5b576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613d7057613d70615275565b60200260200101519750505050505050505b9392505050565b60006001600160a01b03821180613da1575061040082105b15613dd95760408051602081018490520160408051601f198184030181529082905263046b337b60e51b82526107f291600401613f10565b5090565b6000818310613df557613df08284613dfb565b610c48565b610c4883835b60408051600160208201529081018390526060810182905260009060800161361e565b828054828255906000526020600020908101928215613e80579160200282015b82811115613e80578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e3e565b50613dd9929150613eab565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613dd95760008155600101613eac565b60005b83811015613edb578181015183820152602001613ec3565b50506000910152565b60008151808452613efc816020860160208601613ec0565b601f01601f19169290920160200192915050565b602081526000610c486020830184613ee4565b8060608101831015610c4b57600080fd5b60008083601f840112613f4657600080fd5b50813567ffffffffffffffff811115613f5e57600080fd5b60208301915083602082850101111561397b57600080fd5b60008083601f840112613f8857600080fd5b50813567ffffffffffffffff811115613fa057600080fd5b6020830191508360208260051b850101111561397b57600080fd5b60008060008060008060008060e0898b031215613fd757600080fd5b613fe18a8a613f23565b9750606089013567ffffffffffffffff80821115613ffe57600080fd5b61400a8c838d01613f34565b909950975060808b013591508082111561402357600080fd5b61402f8c838d01613f76565b909750955060a08b013591508082111561404857600080fd5b506140558b828c01613f76565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561408357600080fd5b61408d8585613f23565b9250606084013567ffffffffffffffff8111156140a957600080fd5b6140b586828701613f34565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156140fb576140fb6140c2565b60405290565b60405160a0810167ffffffffffffffff811182821017156140fb576140fb6140c2565b6040516080810167ffffffffffffffff811182821017156140fb576140fb6140c2565b6040516060810167ffffffffffffffff811182821017156140fb576140fb6140c2565b6040805190810167ffffffffffffffff811182821017156140fb576140fb6140c2565b604051601f8201601f1916810167ffffffffffffffff811182821017156141b6576141b66140c2565b604052919050565b6001600160a01b0381168114610ec557600080fd5b80356141de816141be565b919050565b803563ffffffff811681146141de57600080fd5b600060c0828403121561420957600080fd5b6142116140d8565b823561421c816141be565b815261422a602084016141e3565b602082015261423b604084016141e3565b604082015261424c606084016141e3565b6060820152608083013561425f816141be565b608082015260a0830135614272816141be565b60a08201529392505050565b803567ffffffffffffffff811681146141de57600080fd5b600080604083850312156142a957600080fd5b6142b28361427e565b91506142c06020840161427e565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106142ef576142ef6142c9565b9052565b60208101610c4b82846142df565b600067ffffffffffffffff82111561431b5761431b6140c2565b5060051b60200190565b600060a0828403121561433757600080fd5b61433f614101565b9050813581526143516020830161427e565b60208201526143626040830161427e565b60408201526143736060830161427e565b60608201526143846080830161427e565b608082015292915050565b600067ffffffffffffffff8211156143a9576143a96140c2565b50601f01601f191660200190565b600082601f8301126143c857600080fd5b81356143db6143d68261438f565b61418d565b8181528460208386010111156143f057600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261441e57600080fd5b8135602061442e6143d683614301565b82815260059290921b8401810191818101908684111561444d57600080fd5b8286015b8481101561452357803567ffffffffffffffff808211156144725760008081fd5b8189019150608080601f19848d0301121561448d5760008081fd5b614495614124565b87840135838111156144a75760008081fd5b6144b58d8a838801016143b7565b825250604080850135848111156144cc5760008081fd5b6144da8e8b838901016143b7565b8a84015250606080860135858111156144f35760008081fd5b6145018f8c838a01016143b7565b9284019290925294909201359381019390935250508352918301918301614451565b509695505050505050565b6000610140828403121561454157600080fd5b6145496140d8565b90506145558383614325565b815260a082013567ffffffffffffffff8082111561457257600080fd5b61457e858386016143b7565b602084015260c084013591508082111561459757600080fd5b6145a3858386016143b7565b60408401526145b460e085016141d3565b606084015261010084013560808401526101208401359150808211156145d957600080fd5b506145e68482850161440d565b60a08301525092915050565b600082601f83011261460357600080fd5b813560206146136143d683614301565b82815260059290921b8401810191818101908684111561463257600080fd5b8286015b8481101561452357803567ffffffffffffffff8111156146565760008081fd5b6146648986838b010161452e565b845250918301918301614636565b600082601f83011261468357600080fd5b813560206146936143d683614301565b82815260059290921b840181019181810190868411156146b257600080fd5b8286015b8481101561452357803567ffffffffffffffff8111156146d65760008081fd5b6146e48986838b01016143b7565b8452509183019183016146b6565b600082601f83011261470357600080fd5b813560206147136143d683614301565b82815260059290921b8401810191818101908684111561473257600080fd5b8286015b8481101561452357803567ffffffffffffffff8111156147565760008081fd5b6147648986838b0101614672565b845250918301918301614736565b600082601f83011261478357600080fd5b813560206147936143d683614301565b8083825260208201915060208460051b8701019350868411156147b557600080fd5b602086015b8481101561452357803583529183019183016147ba565b600082601f8301126147e257600080fd5b813560206147f26143d683614301565b82815260059290921b8401810191818101908684111561481157600080fd5b8286015b8481101561452357803567ffffffffffffffff808211156148365760008081fd5b818901915060a080601f19848d030112156148515760008081fd5b614859614101565b61486488850161427e565b81526040808501358481111561487a5760008081fd5b6148888e8b838901016145f2565b8a84015250606080860135858111156148a15760008081fd5b6148af8f8c838a01016146f2565b83850152506080915081860135858111156148ca5760008081fd5b6148d88f8c838a0101614772565b9184019190915250919093013590830152508352918301918301614815565b600080604080848603121561490b57600080fd5b833567ffffffffffffffff8082111561492357600080fd5b61492f878388016147d1565b945060209150818601358181111561494657600080fd5b8601601f8101881361495757600080fd5b80356149656143d682614301565b81815260059190911b8201840190848101908a83111561498457600080fd5b8584015b83811015614a10578035868111156149a05760008081fd5b8501603f81018d136149b25760008081fd5b878101356149c26143d682614301565b81815260059190911b82018a0190898101908f8311156149e25760008081fd5b928b01925b82841015614a005783358252928a0192908a01906149e7565b8652505050918601918601614988565b50809750505050505050509250929050565b600060208284031215614a3457600080fd5b813567ffffffffffffffff811115614a4b57600080fd5b820160a08185031215613d8257600080fd5b8015158114610ec557600080fd5b80356141de81614a5d565b60006020808385031215614a8957600080fd5b823567ffffffffffffffff80821115614aa157600080fd5b818501915085601f830112614ab557600080fd5b8135614ac36143d682614301565b81815260059190911b83018401908481019088831115614ae257600080fd5b8585015b83811015614b7257803585811115614afe5760008081fd5b86016060818c03601f1901811315614b165760008081fd5b614b1e614147565b614b298a840161427e565b8152604080840135614b3a81614a5d565b828c0152918301359188831115614b515760008081fd5b614b5f8e8c858701016143b7565b9082015285525050918601918601614ae6565b5098975050505050505050565b803560ff811681146141de57600080fd5b600060208284031215614ba257600080fd5b610c4882614b7f565b60008151808452602080850194506020840160005b83811015614be55781516001600160a01b031687529582019590820190600101614bc0565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c3f60e0840182614bab565b90506040840151601f198483030160c0850152614c5c8282614bab565b95945050505050565b60008060408385031215614c7857600080fd5b614c818361427e565b946020939093013593505050565b60008060208385031215614ca257600080fd5b823567ffffffffffffffff80821115614cba57600080fd5b818501915085601f830112614cce57600080fd5b813581811115614cdd57600080fd5b8660208260061b8501011115614cf257600080fd5b60209290920196919550909350505050565b600060208284031215614d1657600080fd5b610c488261427e565b6020815281511515602082015267ffffffffffffffff60208301511660408201526000604083015160608084015261368a6080840182613ee4565b60008060408385031215614d6d57600080fd5b823567ffffffffffffffff80821115614d8557600080fd5b614d918683870161452e565b93506020850135915080821115614da757600080fd5b50614db485828601614672565b9150509250929050565b600060208284031215614dd057600080fd5b8135613d82816141be565b600082601f830112614dec57600080fd5b81356020614dfc6143d683614301565b8083825260208201915060208460051b870101935086841115614e1e57600080fd5b602086015b84811015614523578035614e36816141be565b8352918301918301614e23565b60006020808385031215614e5657600080fd5b823567ffffffffffffffff80821115614e6e57600080fd5b818501915085601f830112614e8257600080fd5b8135614e906143d682614301565b81815260059190911b83018401908481019088831115614eaf57600080fd5b8585015b83811015614b7257803585811115614eca57600080fd5b860160c0818c03601f19011215614ee15760008081fd5b614ee96140d8565b8882013581526040614efc818401614b7f565b8a8301526060614f0d818501614b7f565b8284015260809150614f20828501614a6b565b9083015260a08381013589811115614f385760008081fd5b614f468f8d83880101614ddb565b838501525060c0840135915088821115614f605760008081fd5b614f6e8e8c84870101614ddb565b9083015250845250918601918601614eb3565b600060208284031215614f9357600080fd5b5035919050565b80356001600160e01b03811681146141de57600080fd5b600082601f830112614fc257600080fd5b81356020614fd26143d683614301565b82815260069290921b84018101918181019086841115614ff157600080fd5b8286015b84811015614523576040818903121561500e5760008081fd5b61501661416a565b61501f8261427e565b815261502c858301614f9a565b81860152835291830191604001614ff5565b600082601f83011261504f57600080fd5b8135602061505f6143d683614301565b82815260079290921b8401810191818101908684111561507e57600080fd5b8286015b8481101561452357808803608081121561509c5760008081fd5b6150a4614147565b6150ad8361427e565b8152604080601f19840112156150c35760008081fd5b6150cb61416a565b92506150d887850161427e565b83526150e581850161427e565b8388015281870192909252606083013591810191909152835291830191608001615082565b6000602080838503121561511d57600080fd5b823567ffffffffffffffff8082111561513557600080fd5b8185019150604080838803121561514b57600080fd5b61515361416a565b83358381111561516257600080fd5b84016040818a03121561517457600080fd5b61517c61416a565b81358581111561518b57600080fd5b8201601f81018b1361519c57600080fd5b80356151aa6143d682614301565b81815260069190911b8201890190898101908d8311156151c957600080fd5b928a01925b828410156152195787848f0312156151e65760008081fd5b6151ee61416a565b84356151f9816141be565b8152615206858d01614f9a565b818d0152825292870192908a01906151ce565b84525050508187013593508484111561523157600080fd5b61523d8a858401614fb1565b818801528252508385013591508282111561525757600080fd5b6152638883860161503e565b85820152809550505050505092915050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b818110156152e257835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016152ab565b50508583015187820388850152805180835290840192506000918401905b8083101561533c578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615300565b50979650505050505050565b602081526000610c48602083018461528b565b67ffffffffffffffff8316815260608101613d826020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153c7576153c7615390565b5092915050565b6000602080835260608451604080848701526153ed606087018361528b565b87850151878203601f19016040890152805180835290860193506000918601905b80831015614b7257845167ffffffffffffffff81511683528781015161544d89850182805167ffffffffffffffff908116835260209182015116910152565b5084015182870152938601936001929092019160809091019061540e565b60006020828403121561547d57600080fd5b813567ffffffffffffffff81111561549457600080fd5b61368a848285016147d1565b81810381811115610c4b57610c4b615390565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806154e4576154e46154b3565b92169190910692915050565b8082028115828204841417610c4b57610c4b615390565b60006040828403121561551957600080fd5b61552161416a565b61552a8361427e565b8152602083013560208201528091505092915050565b600181811c9082168061555457607f821691505b60208210810361557457634e487b7160e01b600052602260045260246000fd5b50919050565b805182526000602067ffffffffffffffff81840151168185015260408084015160a060408701526155ae60a0870182613ee4565b9050606085015186820360608801526155c78282613ee4565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561533c57835180516001600160a01b03168352860151868301529285019260019290920191908401906155ea565b602081526000610c48602083018461557a565b608081526000615642608083018761557a565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561568057600080fd5b835161568b81614a5d565b602085015190935067ffffffffffffffff8111156156a857600080fd5b8401601f810186136156b957600080fd5b80516156c76143d68261438f565b8181528760208385010111156156dc57600080fd5b6156ed826020830160208601613ec0565b809450505050604084015190509250925092565b60006020828403121561571357600080fd5b8151613d8281614a5d565b80820180821115610c4b57610c4b615390565b60ff8181168382160190811115610c4b57610c4b615390565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615789576157896154b3565b92169190910492915050565b601f821115610eaf576000816000526020600020601f850160051c810160208610156157be5750805b601f850160051c820191505b81811015612455578281556001016157ca565b815167ffffffffffffffff8111156157f7576157f76140c2565b61580b816158058454615540565b84615795565b602080601f83116001811461584057600084156158285750858301515b600019600386901b1c1916600185901b178555612455565b600085815260208120601f198616915b8281101561586f57888601518255948401946001909101908401615850565b508582101561588d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020808352835460ff81161515602085015267ffffffffffffffff8160081c166040850152506001808501606080860152600081546158dd81615540565b80608089015260a060018316600081146158fe576001811461591a5761594a565b60ff19841660a08b015260a083151560051b8b0101945061594a565b85600052602060002060005b848110156159415781548c8201850152908801908901615926565b8b0160a0019550505b50929998505050505050505050565b602081016005831061596d5761596d6142c9565b91905290565b60ff81811683821602908116908181146153c7576153c7615390565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b818110156159e95784546001600160a01b0316835260019485019492840192016159c4565b505084810360608601526159fd8188614bab565b935050505060ff831660808301529695505050505050565b600067ffffffffffffffff808616835280851660208401525060606040830152614c5c6060830184613ee4565b82815260406020820152600061368a6040830184613ee4565b67ffffffffffffffff8481168252831660208201526060810161368a60408301846142df565b615a8b81846142df565b60406020820152600061368a6040830184613ee4565b600060208284031215615ab357600080fd5b8151613d82816141be565b6020815260008251610100806020850152615add610120850183613ee4565b91506020850151615afa604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615b3460a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615b518483613ee4565b935060c08701519150808685030160e0870152615b6e8483613ee4565b935060e0870151915080868503018387015250615b8b8382613ee4565b9695505050505050565b600060208284031215615ba757600080fd5b5051919050565b600060ff821660ff8103615bc457615bc4615390565b60010192915050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152615b8b6080830184613ee4565b86815260c060208201526000615c1960c0830188613ee4565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615cea57601f19868403018952815160808151818652615c9682870182613ee4565b9150508582015185820387870152615cae8282613ee4565b91505060408083015186830382880152615cc88382613ee4565b6060948501519790940196909652505098840198925090830190600101615c70565b5090979650505050505050565b602081526000610c486020830184615c53565b60008282518085526020808601955060208260051b8401016020860160005b84811015615cea57601f19868403018952615d45838351613ee4565b98840198925090830190600101615d29565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615dbf610180850183613ee4565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615dfc8483613ee4565b935060608801519150615e1b6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615e428282615c53565b9150508281036020840152614c5c8185615d0a565b6000815160208301516001600160e01b031980821693506004831015615e875780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", } var EVM2EVMMultiOffRampABI = EVM2EVMMultiOffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go index fadeefb48b..4fdc2e8136 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go @@ -73,6 +73,7 @@ type EVM2EVMMultiOnRampDestChainDynamicConfig struct { GasMultiplierWeiPerEth uint64 NetworkFeeUSDCents uint32 EnforceOutOfOrder bool + ChainFamilySelector [4]byte } type EVM2EVMMultiOnRampDynamicConfig struct { @@ -120,25 +121,35 @@ type EVM2EVMMultiOnRampTokenTransferFeeConfigSingleTokenArgs struct { TokenTransferFeeConfig EVM2EVMMultiOnRampTokenTransferFeeConfig } -type InternalEVM2EVMMessage struct { +type InternalEVM2AnyRampMessage struct { + Header InternalRampMessageHeader + Sender common.Address + Data []byte + Receiver []byte + ExtraArgs []byte + FeeToken common.Address + FeeTokenAmount *big.Int + TokenAmounts []InternalRampTokenAmount +} + +type InternalRampMessageHeader struct { + MessageId [32]byte SourceChainSelector uint64 - Sender common.Address - Receiver common.Address + DestChainSelector uint64 SequenceNumber uint64 - GasLimit *big.Int - Strict bool Nonce uint64 - FeeToken common.Address - FeeTokenAmount *big.Int - Data []byte - TokenAmounts []ClientEVMTokenAmount - SourceTokenData [][]byte - MessageId [32]byte +} + +type InternalRampTokenAmount struct { + SourcePoolAddress []byte + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int } var EVM2EVMMultiOnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"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\":[{\"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\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainDynamicConfigUpdated\",\"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\"},{\"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\":\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"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\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":[{\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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: "0x6101406040523480156200001257600080fd5b5060405162006b4538038062006b458339810160408190526200003591620014af565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000214565b505085516001600160a01b031615905080620000e6575060208501516001600160401b0316155b80620000fd575060608501516001600160a01b0316155b8062000114575060808501516001600160a01b0316155b806200012b575060a08501516001600160a01b0316155b156200014a576040516306b7c75960e31b815260040160405180910390fd5b84516001600160a01b0390811660a090815260208701516001600160401b031660c05260408701516001600160601b031660809081526060880151831660e0528701518216610100528601511661012052620001a684620002bf565b620001b18362000482565b620001bc8262000a00565b60408051600080825260208201909252620002099183919062000202565b6040805180820190915260008082526020820152815260200190600190039081620001da5790505b5062000acc565b5050505050620018f7565b336001600160a01b038216036200026e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b03161580620002e5575060608101516001600160a01b0316155b1562000304576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b039283166001600160a01b0319918216179091556020808401516003805491851691841691909117905560408085015160048054918616918516919091179055606080860151600580549187169190951617909355805160c0808201835260a080518716835290516001600160401b031693820193909352608080516001600160601b03168284015260e05186169482019490945261010051851693810193909352610120519093169082015290517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916200047791849082516001600160a01b0390811682526020808501516001600160401b0316818401526040808601516001600160601b03168185015260608087015184168186015260808088015185169086015260a0968701518416968501969096528451831660c085015290840151821660e084015283015181166101008301529190920151166101208201526101400190565b60405180910390a150565b60005b8151811015620009fc576000828281518110620004a657620004a6620015f5565b602002602001015190506000838381518110620004c757620004c7620015f5565b6020026020010151600001519050806001600160401b031660001480620004fe5750602082015161018001516001600160401b0316155b15620005295760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b600060066000836001600160401b03166001600160401b0316815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a90046001600160401b03166001600160401b031681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff02191690831515021790555090505082600301546000801b03620009195760c051604080517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b360208201526001600160401b0392831691810191909152908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b03821615620008d0576002830180546001600160a01b0319166001600160a01b0384161790555b836001600160401b03167f4be92415590c4554edbd7d3fbf308eeb6e5d00ababade0791f835b4a18416ed6846040516200090b91906200160b565b60405180910390a2620009eb565b60028301546001600160a01b03838116911614620009565760405163c35aa79d60e01b81526001600160401b038516600482015260240162000083565b60208560200151610160015163ffffffff161015620009a357602085015161016001516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000083565b836001600160401b03167f1173725509a61aed633c58cd12e31c104cd26ca24f6c270c8ac81c5f6f12e8e98660200151604051620009e29190620017b5565b60405180910390a25b505050505080600101905062000485565b5050565b60005b8151811015620009fc57600082828151811062000a245762000a24620015f5565b6020026020010151600001519050600083838151811062000a495762000a49620015f5565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a03565b60005b825181101562000d3957600083828151811062000af05762000af0620015f5565b6020026020010151905060008160000151905060005b82602001515181101562000d2a5760008360200151828151811062000b2f5762000b2f620015f5565b602002602001015160200151905060008460200151838151811062000b585762000b58620015f5565b60200260200101516000015190506020826080015163ffffffff16101562000bb15760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d17908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b06565b50505080600101905062000acf565b5060005b815181101562000dff57600082828151811062000d5e5762000d5e620015f5565b6020026020010151600001519050600083838151811062000d835762000d83620015f5565b6020908102919091018101518101516001600160401b03841660008181526008845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d3d565b505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000e3f5762000e3f62000e04565b60405290565b60405161020081016001600160401b038111828210171562000e3f5762000e3f62000e04565b604080519081016001600160401b038111828210171562000e3f5762000e3f62000e04565b60405160c081016001600160401b038111828210171562000e3f5762000e3f62000e04565b604051601f8201601f191681016001600160401b038111828210171562000ee05762000ee062000e04565b604052919050565b80516001600160a01b038116811462000f0057600080fd5b919050565b80516001600160401b038116811462000f0057600080fd5b60006080828403121562000f3057600080fd5b604051608081016001600160401b038111828210171562000f555762000f5562000e04565b60405290508062000f668362000ee8565b815262000f766020840162000ee8565b602082015262000f896040840162000ee8565b604082015262000f9c6060840162000ee8565b60608201525092915050565b60006001600160401b0382111562000fc45762000fc462000e04565b5060051b60200190565b8051801515811462000f0057600080fd5b805161ffff8116811462000f0057600080fd5b805163ffffffff8116811462000f0057600080fd5b600082601f8301126200101957600080fd5b81516020620010326200102c8362000fa8565b62000eb5565b82815261024092830285018201928282019190878511156200105357600080fd5b8387015b85811015620012125780890382811215620010725760008081fd5b6200107c62000e1a565b620010878362000f05565b815261020080601f19840112156200109f5760008081fd5b620010a962000e45565b9250620010b888850162000fce565b83526040620010c981860162000fdf565b898501526060620010dc81870162000ff2565b828601526080620010ef81880162000ff2565b8287015260a091506200110482880162000ff2565b9086015260c06200111787820162000fdf565b8287015260e091506200112c82880162000ff2565b908601526101006200114087820162000fdf565b8287015261012091506200115682880162000fdf565b908601526101406200116a87820162000fdf565b8287015261016091506200118082880162000ff2565b908601526101806200119487820162000ff2565b828701526101a09150620011aa82880162000f05565b908601526101c0620011be87820162000f05565b828701526101e09150620011d482880162000ff2565b90860152620011e586840162000fce565b81860152508389840152620011fe610220860162000ee8565b908301525085525092840192810162001057565b5090979650505050505050565b600082601f8301126200123157600080fd5b81516020620012446200102c8362000fa8565b82815260069290921b840181019181810190868411156200126457600080fd5b8286015b84811015620012ba5760408189031215620012835760008081fd5b6200128d62000e6b565b620012988262000ee8565b8152620012a785830162000f05565b8186015283529183019160400162001268565b509695505050505050565b600082601f830112620012d757600080fd5b81516020620012ea6200102c8362000fa8565b82815260059290921b840181019181810190868411156200130a57600080fd5b8286015b84811015620012ba5780516001600160401b03808211156200132f57600080fd5b908801906040601f19838c0381018213156200134a57600080fd5b6200135462000e6b565b6200136189860162000f05565b815282850151848111156200137557600080fd5b8086019550508c603f8601126200138b57600080fd5b888501519350620013a06200102c8562000fa8565b84815260e09094028501830193898101908e861115620013bf57600080fd5b958401955b858710156200149857868f0360e0811215620013df57600080fd5b620013e962000e6b565b620013f48962000ee8565b815260c086830112156200140757600080fd5b6200141162000e90565b9150620014208d8a0162000ff2565b82526200142f878a0162000ff2565b8d8301526200144160608a0162000fdf565b878301526200145360808a0162000ff2565b60608301526200146660a08a0162000ff2565b60808301526200147960c08a0162000fce565b60a0830152808d0191909152825260e09690960195908a0190620013c4565b828b0152508752505050928401925083016200130e565b60008060008060008587036101a0811215620014ca57600080fd5b60c0811215620014d957600080fd5b50620014e462000e90565b620014ef8762000ee8565b8152620014ff6020880162000f05565b602082015260408701516001600160601b03811681146200151f57600080fd5b6040820152620015326060880162000ee8565b6060820152620015456080880162000ee8565b60808201526200155860a0880162000ee8565b60a082015294506200156e8760c0880162000f1d565b6101408701519094506001600160401b03808211156200158d57600080fd5b6200159b89838a0162001007565b9450610160880151915080821115620015b357600080fd5b620015c189838a016200121f565b9350610180880151915080821115620015d957600080fd5b50620015e888828901620012c5565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c811660408601526200165360608601828560381c1663ffffffff169052565b6200166b60808601828560581c1663ffffffff169052565b6200168160a08601838560781c1661ffff169052565b6200169960c08601828560881c1663ffffffff169052565b620016af60e08601838560a81c1661ffff169052565b620016c66101008601838560b81c1661ffff169052565b620016dd6101208601838560c81c1661ffff169052565b620016f66101408601828560d81c1663ffffffff169052565b600186015463ffffffff8282161661016087015292506001600160401b03602084901c811661018087015291506200173f6101a08601838560601c166001600160401b03169052565b620017586101c08601828560a01c1663ffffffff169052565b506200176f6101e0850160ff8460c01c1615159052565b60028501546001600160a01b0381166102008601529150620017a26102208501828460a01c166001600160401b03169052565b5050600383015461024083015292915050565b81511515815261020081016020830151620017d6602084018261ffff169052565b506040830151620017ef604084018263ffffffff169052565b50606083015162001808606084018263ffffffff169052565b50608083015162001821608084018263ffffffff169052565b5060a08301516200183860a084018261ffff169052565b5060c08301516200185160c084018263ffffffff169052565b5060e08301516200186860e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b03908116918501919091526101a080860151909116908401526101c080850151909116908301526101e0928301511515929091019190915290565b60805160a05160c05160e0516101005161012051615195620019b0600039600081816102da01528181610f260152612adf0152600081816102ab01528181612ab7015261323e01526000818161027c01528181612a8d0152612bf30152600081816102180152818161265001528181612a2801526130f90152600081816101e901528181612a0301528181612eda0152612f8401526000818161024801528181612a5a0152818161304601526130b601526151956000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063a69c64c011610081578063df0aa9e911610066578063df0aa9e9146108c0578063f2fde38b146108d3578063fbca3b74146108e657600080fd5b8063a69c64c01461089a578063a6f3ab6c146108ad57600080fd5b80638da5cb5b116100b25780638da5cb5b146108635780639041be3d14610874578063932e53c81461088757600080fd5b806379ba5097146106f857806382b49eb01461070057600080fd5b80633a019940116101245780636def4ce7116101095780636def4ce7146103b65780637437ff9f14610672578063770e2dc4146106e557600080fd5b80633a0199401461038157806348a98aa41461038b57600080fd5b8063061877e31461015657806306285c69146101a7578063181f5a771461031757806320487ded14610360575b600080fd5b610189610164366004613945565b6001600160a01b031660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61030a6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161019e9190613962565b6103536040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161019e9190613a1e565b61037361036e366004613a6a565b610906565b60405190815260200161019e565b610389610d27565b005b61039e610399366004613aba565b610eeb565b6040516001600160a01b03909116815260200161019e565b6106656103c4366004613af3565b604080516102808101825260006080820181815260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e08301829052610200830182905261022083018290526102408301829052610260830182905282526020820181905291810182905260608101919091525067ffffffffffffffff908116600090815260066020908152604091829020825161028081018452815460ff80821615156080840190815261ffff610100808504821660a087015263ffffffff63010000008604811660c08801526701000000000000008604811660e08801526b01000000000000000000000086048116918701919091526f01000000000000000000000000000000850482166101208701527101000000000000000000000000000000000085048116610140870152750100000000000000000000000000000000000000000085048216610160870152770100000000000000000000000000000000000000000000008504821661018087015279010000000000000000000000000000000000000000000000000085049091166101a08601527b0100000000000000000000000000000000000000000000000000000090930483166101c085015260018501548084166101e0860152640100000000810489166102008601526c010000000000000000000000008104891661022086015274010000000000000000000000000000000000000000808204909416610240860152780100000000000000000000000000000000000000000000000090049091161515610260840152825260028301546001600160a01b0381169483019490945290920490931691810191909152600390910154606082015290565b60405161019e9190613c41565b6106d860408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526002546001600160a01b03908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161019e9190613c8e565b6103896106f3366004613ec1565b610f9a565b610389610fb0565b61080361070e366004613aba565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff9190911660009081526008602090815260408083206001600160a01b0394909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b60405161019e9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b6000546001600160a01b031661039e565b610189610882366004613af3565b611079565b61038961089536600461413b565b6110bd565b6103896108a8366004614348565b6110d1565b6103896108bb366004614406565b6110e2565b6103736108ce36600461448b565b6110f3565b6103896108e1366004613945565b61157b565b6108f96108f4366004613af3565b61158c565b60405161019e91906144f7565b67ffffffffffffffff82166000908152600660205260408120805460ff1661096b576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b600061099961097d6080860186614544565b6001850154640100000000900467ffffffffffffffff166115c0565b90506109ca856109ac6020870187614544565b84519091506109be6040890189614592565b9050856020015161172d565b60006007816109df6080880160608901613945565b6001600160a01b03168152602081019190915260400160009081205467ffffffffffffffff169150819003610a5c57610a1e6080860160608701613945565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b60035460009081906001600160a01b031663ffdb4b37610a8260808a0160608b01613945565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8b1660248201526044016040805180830381865afa158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b119190614608565b90925090506000808080610b2860408c018c614592565b90501115610b6357610b578b610b4460808d0160608e01613945565b87610b5260408f018f614592565b6118a3565b91945092509050610b9a565b6001880154610b979074010000000000000000000000000000000000000000900463ffffffff16662386f26fc10000614661565b92505b875460009077010000000000000000000000000000000000000000000000900461ffff1615610c0657610c038c6dffffffffffffffffffffffffffff607088901c16610be960208f018f614544565b90508e8060400190610bfb9190614592565b905086611c94565b90505b600089600101600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff168463ffffffff168b600001600f9054906101000a900461ffff1661ffff168e8060200190610c599190614544565b610c64929150614661565b8c548c51610c87916b010000000000000000000000900463ffffffff1690614678565b610c919190614678565b610c9b9190614678565b610cb5906dffffffffffffffffffffffffffff8916614661565b610cbf9190614661565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff87168282610cf667ffffffffffffffff8c1689614661565b610d009190614678565b610d0a9190614678565b610d14919061468b565b9a50505050505050505050505b92915050565b600354604080517fcdc73d5100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163cdc73d5191600480830192869291908290030181865afa158015610d89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610db191908101906146c6565b6005549091506001600160a01b031660005b8251811015610ee6576000838281518110610de057610de0614755565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e729190614784565b90508015610edc57610e8e6001600160a01b0383168583611d9a565b816001600160a01b0316846001600160a01b03167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ed391815260200190565b60405180910390a35b5050600101610dc3565b505050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f93919061479d565b9392505050565b610fa2611e1a565b610fac8282611e76565b5050565b6001546001600160a01b0316331461100a5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610962565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120600201549091610d21917401000000000000000000000000000000000000000090041660016147ba565b6110c5611e1a565b6110ce81612256565b50565b6110d9611e1a565b6110ce81612849565b6110ea611e1a565b6110ce81612926565b67ffffffffffffffff841660009081526006602052604081208161111a8288888888612b3f565b905060005b8161014001515181101561151157600061113c6040890189614592565b8381811061114c5761114c614755565b90506040020180360381019061116291906147e2565b905080602001516000036111a2576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111b28a8360000151610eeb565b90506001600160a01b038116158061126857506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015611242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611266919061481c565b155b156112ad5781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b6000816001600160a01b0316639a4575b96040518060a001604052808d80600001906112d99190614544565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff8f166020808301919091526001600160a01b03808e16604080850191909152918901516060840152885116608090920191909152517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526113849190600401614839565b6000604051808303816000875af11580156113a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113cb9190810190614906565b9050602081602001515111801561142c575067ffffffffffffffff8b16600090815260086020908152604080832086516001600160a01b0316845282529091205490820151516e01000000000000000000000000000090910463ffffffff16105b156114715782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b805161147c906133f7565b5060408051606081019091526001600160a01b03831660808201528060a0810160405160208183030381529060405281526020018260000151815260200182602001518152506040516020016114d29190614997565b60405160208183030381529060405285610160015185815181106114f8576114f8614755565b602002602001018190525050505080600101905061111f565b50611520818360030154613452565b61018082015260405167ffffffffffffffff8816907fc79f9c3e610deac14de4e704195fe17eab0983ee9916866bc04d16a00f54daa690611562908490614aa2565b60405180910390a261018001519150505b949350505050565b611583611e1a565b6110ce816135ad565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260008082526020820152600083900361160157506040805180820190915267ffffffffffffffff8216815260006020820152610f93565b600061160d8486614bd7565b90507fe7e230f0000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161167a576116658460048188614c1f565b8101906116729190614c49565b915050610f93565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016116fb5760408051808201909152806116db866004818a614c1f565b8101906116e89190614c81565b815260006020909101529150610f939050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8516600090815260066020526040902080546301000000900463ffffffff168511156117a65780546040517f86933789000000000000000000000000000000000000000000000000000000008152630100000090910463ffffffff16600482015260248101869052604401610962565b8054670100000000000000900463ffffffff168411156117f2576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8054610100900461ffff16831115611836576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018101547801000000000000000000000000000000000000000000000000900460ff168015611864575081155b1561189b576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000808083815b81811015611c875760008787838181106118c6576118c6614755565b9050604002018036038101906118dc91906147e2565b905060006001600160a01b03166118f78c8360000151610eeb565b6001600160a01b0316036119455780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610962565b67ffffffffffffffff8b16600090815260086020908152604080832084516001600160a01b03168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052611ab35767ffffffffffffffff8c1660009081526006602052604090208054611a5390790100000000000000000000000000000000000000000000000000900461ffff16662386f26fc10000614661565b611a5d9089614678565b8154909850611a91907b01000000000000000000000000000000000000000000000000000000900463ffffffff1688614c9a565b6001820154909750611aa99063ffffffff1687614c9a565b9550505050611c7f565b604081015160009061ffff1615611bcf5760008c6001600160a01b031684600001516001600160a01b031614611b725760035484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015611b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6b9190614cb7565b9050611b75565b508a5b620186a0836040015161ffff16611bb78660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661366e90919063ffffffff16565b611bc19190614661565b611bcb919061468b565b9150505b6060820151611bde9088614c9a565b9650816080015186611bf09190614c9a565b8251909650600090611c0f9063ffffffff16662386f26fc10000614661565b905080821015611c2e57611c23818a614678565b985050505050611c7f565b6000836020015163ffffffff16662386f26fc10000611c4d9190614661565b905080831115611c6d57611c61818b614678565b99505050505050611c7f565b611c77838b614678565b995050505050505b6001016118aa565b5050955095509592505050565b60008063ffffffff8316611ca9608086614661565b611cb587610220614678565b611cbf9190614678565b611cc99190614678565b67ffffffffffffffff8816600090815260066020526040812080549293509171010000000000000000000000000000000000810463ffffffff1690611d2b907501000000000000000000000000000000000000000000900461ffff1685614661565b611d359190614678565b825490915077010000000000000000000000000000000000000000000000900461ffff16611d736dffffffffffffffffffffffffffff8a1683614661565b611d7d9190614661565b611d8d90655af3107a4000614661565b9998505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610ee69084906136ab565b6000546001600160a01b03163314611e745760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610962565b565b60005b825181101561217f576000838281518110611e9657611e96614755565b6020026020010151905060008160000151905060005b82602001515181101561217157600083602001518281518110611ed157611ed1614755565b6020026020010151602001519050600084602001518381518110611ef757611ef7614755565b60200260200101516000015190506020826080015163ffffffff161015611f675760808201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015263ffffffff9091166024820152604401610962565b67ffffffffffffffff841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59061215f908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101611eac565b505050806001019050611e79565b5060005b8151811015610ee65760008282815181106121a0576121a0614755565b602002602001015160000151905060008383815181106121c2576121c2614755565b60209081029190910181015181015167ffffffffffffffff841660008181526008845260408082206001600160a01b038516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612183565b60005b8151811015610fac57600082828151811061227657612276614755565b60200260200101519050600083838151811061229457612294614755565b60200260200101516000015190508067ffffffffffffffff16600014806122cc57506020820151610180015167ffffffffffffffff16155b1561230f576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610962565b6000600660008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff02191690831515021790555090505082600301546000801b0361273957604080517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b038216156126f2576002830180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555b8367ffffffffffffffff167f4be92415590c4554edbd7d3fbf308eeb6e5d00ababade0791f835b4a18416ed68460405161272c9190614cd2565b60405180910390a2612839565b60028301546001600160a01b0383811691161461278e576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610962565b60208560200151610160015163ffffffff1610156127f257602085015161016001516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610962565b8367ffffffffffffffff167f1173725509a61aed633c58cd12e31c104cd26ca24f6c270c8ac81c5f6f12e8e986602001516040516128309190614e73565b60405180910390a25b5050505050806001019050612259565b60005b8151811015610fac57600082828151811061286957612869614755565b6020026020010151600001519050600083838151811061288b5761288b614755565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161284c565b60208101516001600160a01b0316158061294b575060608101516001600160a01b0316155b15612982576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556020808401516003805484169185169190911790556040808501516004805485169186169190911790556060808601516005805490951690861617909355805160c0810182527f0000000000000000000000000000000000000000000000000000000000000000851681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16928101929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16828201527f00000000000000000000000000000000000000000000000000000000000000008416928201929092527f0000000000000000000000000000000000000000000000000000000000000000831660808201527f000000000000000000000000000000000000000000000000000000000000000090921660a0830152517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa91612b34918490614e82565b60405180910390a150565b604080516101a08101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018390526101008201839052610120820181905261014082018190526101608201526101808101919091526040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608086901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c66919061481c565b15612ca9576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610962565b6001600160a01b038216612ce9576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546001600160a01b03163314612d2d576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460ff16612d74576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610962565b6000612da2612d866080870187614544565b60018a0154640100000000900467ffffffffffffffff166115c0565b90506000612db36040870187614592565b9150612dda905087612dc86020890189614544565b9050846000015184866020015161172d565b8015612ece576004546001600160a01b03168015612ecc576040517fe0a0e5060000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063e0a0e50690612e39908b908b90600401614fe4565b600060405180830381600087803b158015612e5357600080fd5b505af1925050508015612e64575060015b612ecc573d808015612e92576040519150601f19603f3d011682016040523d82523d6000602084013e612e97565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016109629190613a1e565b505b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612f0a6080890160608a01613945565b6001600160a01b031603612f1f575084612ff2565b6003546001600160a01b03166241e5be612f3f60808a0160608b01613945565b60405160e083901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039182166004820152602481018a90527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015612fcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fef9190614784565b90505b6130026080880160608901613945565b6001600160a01b03167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8260405161303c91815260200190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff168111156130e3576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018290526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610962565b604080516101a08101825267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526001600160a01b038716602082015290810161317461313a8a80614544565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133f792505050565b6001600160a01b031681526020018a600201601481819054906101000a900467ffffffffffffffff166131a690615102565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020018460000151815260200160001515815260200184602001516132b0576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526001600160a01b0388811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015613287573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ab9190615129565b6132b3565b60005b67ffffffffffffffff1681526020016132d260808a0160608b01613945565b6001600160a01b031681526020018781526020018880602001906132f69190614544565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161333d60408a018a614592565b808060200260200160405190810160405280939291908181526020016000905b828210156133895761337a604083028601368190038101906147e2565b8152602001906001019061335d565b505050505081526020018367ffffffffffffffff8111156133ac576133ac613cca565b6040519080825280602002602001820160405280156133df57816020015b60608152602001906001900390816133ca5790505b50815260006020909101529998505050505050505050565b6000815160201461343657816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109629190613a1e565b610d218280602001905181019061344d9190614784565b613790565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016134e89897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016135219190615146565b6040516020818303038152906040528051906020012087610160015160405160200161354d9190615159565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b336001600160a01b038216036136055760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610962565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a76400006136a1837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616614661565b610f93919061468b565b6000613700826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137fd9092919063ffffffff16565b805190915015610ee6578080602001905181019061371e919061481c565b610ee65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610962565b60006001600160a01b038211806137a8575061040082105b156137f95760408051602081018490520160408051601f19818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261096291600401613a1e565b5090565b6060611573848460008585600080866001600160a01b03168587604051613824919061516c565b60006040518083038185875af1925050503d8060008114613861576040519150601f19603f3d011682016040523d82523d6000602084013e613866565b606091505b509150915061387787838387613882565b979650505050505050565b606083156138f15782516000036138ea576001600160a01b0385163b6138ea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610962565b5081611573565b61157383838151156139065781518083602001fd5b8060405162461bcd60e51b81526004016109629190613a1e565b6001600160a01b03811681146110ce57600080fd5b803561394081613920565b919050565b60006020828403121561395757600080fd5b8135610f9381613920565b60c08101610d2182846001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60005b838110156139e95781810151838201526020016139d1565b50506000910152565b60008151808452613a0a8160208601602086016139ce565b601f01601f19169290920160200192915050565b602081526000610f9360208301846139f2565b67ffffffffffffffff811681146110ce57600080fd5b803561394081613a31565b600060a08284031215613a6457600080fd5b50919050565b60008060408385031215613a7d57600080fd5b8235613a8881613a31565b9150602083013567ffffffffffffffff811115613aa457600080fd5b613ab085828601613a52565b9150509250929050565b60008060408385031215613acd57600080fd5b8235613ad881613a31565b91506020830135613ae881613920565b809150509250929050565b600060208284031215613b0557600080fd5b8135610f9381613a31565b8051151582526020810151613b2b602084018261ffff169052565b506040810151613b43604084018263ffffffff169052565b506060810151613b5b606084018263ffffffff169052565b506080810151613b73608084018263ffffffff169052565b5060a0810151613b8960a084018261ffff169052565b5060c0810151613ba160c084018263ffffffff169052565b5060e0810151613bb760e084018261ffff169052565b506101008181015161ffff9081169184019190915261012080830151909116908301526101408082015163ffffffff90811691840191909152610160808301518216908401526101808083015167ffffffffffffffff908116918501919091526101a080840151909116908401526101c080830151909116908301526101e0908101511515910152565b600061026082019050613c55828451613b10565b60208301516001600160a01b0316610200830152604083015167ffffffffffffffff166102208301526060909201516102409091015290565b60808101610d21828480516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b60405290565b60405160c0810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b6040516060810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b604051610200810167ffffffffffffffff81118282101715613d1c57613d1c613cca565b604051601f8201601f1916810167ffffffffffffffff81118282101715613db557613db5613cca565b604052919050565b600067ffffffffffffffff821115613dd757613dd7613cca565b5060051b60200190565b803563ffffffff8116811461394057600080fd5b803561ffff8116811461394057600080fd5b80151581146110ce57600080fd5b803561394081613e07565b600082601f830112613e3157600080fd5b81356020613e46613e4183613dbd565b613d8c565b82815260069290921b84018101918181019086841115613e6557600080fd5b8286015b84811015613eb65760408189031215613e825760008081fd5b613e8a613cf9565b8135613e9581613a31565b815281850135613ea481613920565b81860152835291830191604001613e69565b509695505050505050565b60008060408385031215613ed457600080fd5b67ffffffffffffffff83351115613eea57600080fd5b83601f843585010112613efc57600080fd5b613f0c613e418435850135613dbd565b8335840180358083526020808401939260059290921b90910101861015613f3257600080fd5b602085358601015b85358601803560051b016020018110156141055767ffffffffffffffff81351115613f6457600080fd5b6040601f19823588358901018903011215613f7e57600080fd5b613f86613cf9565b613f996020833589358a01010135613a31565b863587018235016020810135825267ffffffffffffffff6040909101351115613fc157600080fd5b86358701823501604081013501603f81018913613fdd57600080fd5b613fed613e416020830135613dbd565b602082810135808352908201919060e00283016040018b101561400f57600080fd5b604083015b604060e06020860135028501018110156140ec5760e0818d03121561403857600080fd5b614040613cf9565b61404a8235613920565b8135815260c0601f19838f0301121561406257600080fd5b61406a613d22565b61407660208401613de1565b815261408460408401613de1565b602082015261409560608401613df5565b60408201526140a660808401613de1565b60608201526140b760a08401613de1565b60808201526140c960c0840135613e07565b60c083013560a0820152602082810191909152908452929092019160e001614014565b5060208481019190915292865250509283019201613f3a565b5092505067ffffffffffffffff6020840135111561412257600080fd5b6141328460208501358501613e20565b90509250929050565b6000602080838503121561414e57600080fd5b823567ffffffffffffffff81111561416557600080fd5b8301601f8101851361417657600080fd5b8035614184613e4182613dbd565b81815261024091820283018401918482019190888411156141a457600080fd5b938501935b8385101561433c57848903818112156141c25760008081fd5b6141ca613d45565b86356141d581613a31565b8152610200601f1983018113156141ec5760008081fd5b6141f4613d68565b9250614201898901613e15565b83526040614210818a01613df5565b8a8501526060614221818b01613de1565b828601526080614232818c01613de1565b8287015260a09150614245828c01613de1565b9086015260c06142568b8201613df5565b8287015260e09150614269828c01613de1565b9086015261010061427b8b8201613df5565b82870152610120915061428f828c01613df5565b908601526101406142a18b8201613df5565b8287015261016091506142b5828c01613de1565b908601526101806142c78b8201613de1565b828701526101a091506142db828c01613a47565b908601526101c06142ed8b8201613a47565b828701526101e09150614301828c01613de1565b908601526143108a8401613e15565b8186015250838a8401526143276102208a01613935565b908301525084525093840193918501916141a9565b50979650505050505050565b6000602080838503121561435b57600080fd5b823567ffffffffffffffff81111561437257600080fd5b8301601f8101851361438357600080fd5b8035614391613e4182613dbd565b81815260069190911b820183019083810190878311156143b057600080fd5b928401925b8284101561387757604084890312156143ce5760008081fd5b6143d6613cf9565b84356143e181613920565b8152848601356143f081613a31565b81870152825260409390930192908401906143b5565b60006080828403121561441857600080fd5b6040516080810181811067ffffffffffffffff8211171561443b5761443b613cca565b604052823561444981613920565b8152602083013561445981613920565b6020820152604083013561446c81613920565b6040820152606083013561447f81613920565b60608201529392505050565b600080600080608085870312156144a157600080fd5b84356144ac81613a31565b9350602085013567ffffffffffffffff8111156144c857600080fd5b6144d487828801613a52565b9350506040850135915060608501356144ec81613920565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b818110156145385783516001600160a01b031683529284019291840191600101614513565b50909695505050505050565b6000808335601e1984360301811261455b57600080fd5b83018035915067ffffffffffffffff82111561457657600080fd5b60200191503681900382131561458b57600080fd5b9250929050565b6000808335601e198436030181126145a957600080fd5b83018035915067ffffffffffffffff8211156145c457600080fd5b6020019150600681901b360382131561458b57600080fd5b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461394057600080fd5b6000806040838503121561461b57600080fd5b614624836145dc565b9150614132602084016145dc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610d2157610d21614632565b80820180821115610d2157610d21614632565b6000826146c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208083850312156146d957600080fd5b825167ffffffffffffffff8111156146f057600080fd5b8301601f8101851361470157600080fd5b805161470f613e4182613dbd565b81815260059190911b8201830190838101908783111561472e57600080fd5b928401925b8284101561387757835161474681613920565b82529284019290840190614733565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561479657600080fd5b5051919050565b6000602082840312156147af57600080fd5b8151610f9381613920565b67ffffffffffffffff8181168382160190808211156147db576147db614632565b5092915050565b6000604082840312156147f457600080fd5b6147fc613cf9565b823561480781613920565b81526020928301359281019290925250919050565b60006020828403121561482e57600080fd5b8151610f9381613e07565b602081526000825160a0602084015261485560c08401826139f2565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f8301126148b357600080fd5b815167ffffffffffffffff8111156148cd576148cd613cca565b6148e06020601f19601f84011601613d8c565b8181528460208386010111156148f557600080fd5b6115738260208301602087016139ce565b60006020828403121561491857600080fd5b815167ffffffffffffffff8082111561493057600080fd5b908301906040828603121561494457600080fd5b61494c613cf9565b82518281111561495b57600080fd5b614967878286016148a2565b82525060208301518281111561497c57600080fd5b614988878286016148a2565b60208301525095945050505050565b6020815260008251606060208401526149b360808401826139f2565b90506020840151601f19808584030160408601526149d183836139f2565b92506040860151915080858403016060860152506149ef82826139f2565b95945050505050565b60008151808452602080850194506020840160005b83811015614a3d57815180516001600160a01b031688528301518388015260409096019590820190600101614a0d565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015614a9557601f19868403018952614a838383516139f2565b98840198925090830190600101614a67565b5090979650505050505050565b60208152614abd60208201835167ffffffffffffffff169052565b60006020830151614ad960408401826001600160a01b03169052565b5060408301516001600160a01b038116606084015250606083015167ffffffffffffffff8116608084015250608083015160a083015260a0830151614b2260c084018215159052565b5060c083015167ffffffffffffffff811660e08401525060e0830151610100614b55818501836001600160a01b03169052565b840151610120848101919091528401516101a061014080860182905291925090614b836101c08601846139f2565b9250808601519050601f19610160818786030181880152614ba485846149f8565b945080880151925050610180818786030181880152614bc38584614a48565b970151959092019490945250929392505050565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614c175780818660040360031b1b83161692505b505092915050565b60008085851115614c2f57600080fd5b83861115614c3c57600080fd5b5050820193919092039150565b600060408284031215614c5b57600080fd5b614c63613cf9565b823581526020830135614c7581613e07565b60208201529392505050565b600060208284031215614c9357600080fd5b5035919050565b63ffffffff8181168382160190808211156147db576147db614632565b600060208284031215614cc957600080fd5b610f93826145dc565b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c81166040860152614d1960608601828560381c1663ffffffff169052565b614d3060808601828560581c1663ffffffff169052565b614d4560a08601838560781c1661ffff169052565b614d5c60c08601828560881c1663ffffffff169052565b614d7160e08601838560a81c1661ffff169052565b614d876101008601838560b81c1661ffff169052565b614d9d6101208601838560c81c1661ffff169052565b614db56101408601828560d81c1663ffffffff169052565b600186015463ffffffff82821616610160870152925067ffffffffffffffff602084901c81166101808701529150614dff6101a08601838560601c1667ffffffffffffffff169052565b614e176101c08601828560a01c1663ffffffff169052565b50614e2d6101e0850160ff8460c01c1615159052565b60028501546001600160a01b0381166102008601529150614e606102208501828460a01c1667ffffffffffffffff169052565b5050600383015461024083015292915050565b6102008101610d218284613b10565b6101408101614eef82856001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b82516001600160a01b0390811660c08401526020840151811660e084015260408401518116610100840152606084015116610120830152610f93565b6000808335601e19843603018112614f4257600080fd5b830160208101925035905067ffffffffffffffff811115614f6257600080fd5b80360382131561458b57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8183526000602080850194508260005b85811015614a3d578135614fbf81613920565b6001600160a01b03168752818301358388015260409687019690910190600101614fac565b600067ffffffffffffffff8085168352604060208401526150058485614f2b565b60a0604086015261501a60e086018284614f71565b91505061502a6020860186614f2b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152615060848385614f71565b935060408801359250601e1988360301831261507b57600080fd5b6020928801928301923591508482111561509457600080fd5b8160061b36038313156150a657600080fd5b808785030160808801526150bb848385614f9c565b94506150c960608901613935565b6001600160a01b03811660a089015293506150e76080890189614f2b565b94509250808786030160c08801525050613877838383614f71565b600067ffffffffffffffff80831681810361511f5761511f614632565b6001019392505050565b60006020828403121561513b57600080fd5b8151610f9381613a31565b602081526000610f9360208301846149f8565b602081526000610f936020830184614a48565b6000825161517e8184602087016139ce565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"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\":[{\"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\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"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\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainDynamicConfigUpdated\",\"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\"},{\"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\":\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"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\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":[{\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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: "0x6101406040523480156200001257600080fd5b506040516200740738038062007407833981016040819052620000359162001528565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000214565b505085516001600160a01b031615905080620000e6575060208501516001600160401b0316155b80620000fd575060608501516001600160a01b0316155b8062000114575060808501516001600160a01b0316155b806200012b575060a08501516001600160a01b0316155b156200014a576040516306b7c75960e31b815260040160405180910390fd5b84516001600160a01b0390811660a090815260208701516001600160401b031660c05260408701516001600160601b031660809081526060880151831660e0528701518216610100528601511661012052620001a684620002bf565b620001b18362000482565b620001bc8262000a4b565b60408051600080825260208201909252620002099183919062000202565b6040805180820190915260008082526020820152815260200190600190039081620001da5790505b5062000b17565b50505050506200199a565b336001600160a01b038216036200026e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b03161580620002e5575060608101516001600160a01b0316155b1562000304576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b039283166001600160a01b0319918216179091556020808401516003805491851691841691909117905560408085015160048054918616918516919091179055606080860151600580549187169190951617909355805160c0808201835260a080518716835290516001600160401b031693820193909352608080516001600160601b03168284015260e05186169482019490945261010051851693810193909352610120519093169082015290517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916200047791849082516001600160a01b0390811682526020808501516001600160401b0316818401526040808601516001600160601b03168185015260608087015184168186015260808088015185169086015260a0968701518416968501969096528451831660c085015290840151821660e084015283015181166101008301529190920151166101208201526101400190565b60405180910390a150565b60005b815181101562000a47576000828281518110620004a657620004a66200166e565b602002602001015190506000838381518110620004c757620004c76200166e565b6020026020010151600001519050806001600160401b031660001480620004fe5750602082015161018001516001600160401b0316155b80620005245750602082015161020001516001600160e01b031916630a04b54b60e21b14155b156200054f5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b600060066000836001600160401b03166001600160401b0316815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a90046001600160401b03166001600160401b031681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505082600301546000801b03620009645760c051604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f732160208201526001600160401b0392831691810191909152908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b038216156200091b576002830180546001600160a01b0319166001600160a01b0384161790555b836001600160401b03167f66951b52bb33e5d462611460f7aa53069005b173e002d9224c15fb986e4ead8f8460405162000956919062001684565b60405180910390a262000a36565b60028301546001600160a01b03838116911614620009a15760405163c35aa79d60e01b81526001600160401b038516600482015260240162000083565b60208560200151610160015163ffffffff161015620009ee57602085015161016001516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000083565b836001600160401b03167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb866020015160405162000a2d919062001843565b60405180910390a25b505050505080600101905062000485565b5050565b60005b815181101562000a4757600082828151811062000a6f5762000a6f6200166e565b6020026020010151600001519050600083838151811062000a945762000a946200166e565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a4e565b60005b825181101562000d8457600083828151811062000b3b5762000b3b6200166e565b6020026020010151905060008160000151905060005b82602001515181101562000d755760008360200151828151811062000b7a5762000b7a6200166e565b602002602001015160200151905060008460200151838151811062000ba35762000ba36200166e565b60200260200101516000015190506020826080015163ffffffff16101562000bfc5760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d62908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b51565b50505080600101905062000b1a565b5060005b815181101562000e4a57600082828151811062000da95762000da96200166e565b6020026020010151600001519050600083838151811062000dce5762000dce6200166e565b6020908102919091018101518101516001600160401b03841660008181526008845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d88565b505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b60405290565b60405161022081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b604080519081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b60405160c081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b604051601f8201601f191681016001600160401b038111828210171562000f2b5762000f2b62000e4f565b604052919050565b80516001600160a01b038116811462000f4b57600080fd5b919050565b80516001600160401b038116811462000f4b57600080fd5b60006080828403121562000f7b57600080fd5b604051608081016001600160401b038111828210171562000fa05762000fa062000e4f565b60405290508062000fb18362000f33565b815262000fc16020840162000f33565b602082015262000fd46040840162000f33565b604082015262000fe76060840162000f33565b60608201525092915050565b60006001600160401b038211156200100f576200100f62000e4f565b5060051b60200190565b8051801515811462000f4b57600080fd5b805161ffff8116811462000f4b57600080fd5b805163ffffffff8116811462000f4b57600080fd5b80516001600160e01b03198116811462000f4b57600080fd5b600082601f8301126200107d57600080fd5b8151602062001096620010908362000ff3565b62000f00565b8281526102609283028501820192828201919087851115620010b757600080fd5b8387015b858110156200128b5780890382811215620010d65760008081fd5b620010e062000e65565b620010eb8362000f50565b815261022080601f1984011215620011035760008081fd5b6200110d62000e90565b92506200111c88850162001019565b835260406200112d8186016200102a565b898501526060620011408187016200103d565b828601526080620011538188016200103d565b8287015260a09150620011688288016200103d565b9086015260c06200117b8782016200102a565b8287015260e09150620011908288016200103d565b90860152610100620011a48782016200102a565b828701526101209150620011ba8288016200102a565b90860152610140620011ce8782016200102a565b828701526101609150620011e48288016200103d565b90860152610180620011f88782016200103d565b828701526101a091506200120e82880162000f50565b908601526101c06200122287820162000f50565b828701526101e09150620012388288016200103d565b908601526102006200124c87820162001019565b828701526200125d84880162001052565b818701525050838984015262001277610240860162000f33565b9083015250855250928401928101620010bb565b5090979650505050505050565b600082601f830112620012aa57600080fd5b81516020620012bd620010908362000ff3565b82815260069290921b84018101918181019086841115620012dd57600080fd5b8286015b84811015620013335760408189031215620012fc5760008081fd5b6200130662000eb6565b620013118262000f33565b81526200132085830162000f50565b81860152835291830191604001620012e1565b509695505050505050565b600082601f8301126200135057600080fd5b8151602062001363620010908362000ff3565b82815260059290921b840181019181810190868411156200138357600080fd5b8286015b84811015620013335780516001600160401b0380821115620013a857600080fd5b908801906040601f19838c038101821315620013c357600080fd5b620013cd62000eb6565b620013da89860162000f50565b81528285015184811115620013ee57600080fd5b8086019550508c603f8601126200140457600080fd5b88850151935062001419620010908562000ff3565b84815260e09094028501830193898101908e8611156200143857600080fd5b958401955b858710156200151157868f0360e08112156200145857600080fd5b6200146262000eb6565b6200146d8962000f33565b815260c086830112156200148057600080fd5b6200148a62000edb565b9150620014998d8a016200103d565b8252620014a8878a016200103d565b8d830152620014ba60608a016200102a565b87830152620014cc60808a016200103d565b6060830152620014df60a08a016200103d565b6080830152620014f260c08a0162001019565b60a0830152808d0191909152825260e09690960195908a01906200143d565b828b01525087525050509284019250830162001387565b60008060008060008587036101a08112156200154357600080fd5b60c08112156200155257600080fd5b506200155d62000edb565b620015688762000f33565b8152620015786020880162000f50565b602082015260408701516001600160601b03811681146200159857600080fd5b6040820152620015ab6060880162000f33565b6060820152620015be6080880162000f33565b6080820152620015d160a0880162000f33565b60a08201529450620015e78760c0880162000f68565b6101408701519094506001600160401b03808211156200160657600080fd5b6200161489838a016200106b565b94506101608801519150808211156200162c57600080fd5b6200163a89838a0162001298565b93506101808801519150808211156200165257600080fd5b5062001661888289016200133e565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b815460ff81161515825261028082019061ffff600882901c8116602085015263ffffffff601883901c81166040860152620016cc60608601828560381c1663ffffffff169052565b620016e460808601828560581c1663ffffffff169052565b620016fa60a08601838560781c1661ffff169052565b6200171260c08601828560881c1663ffffffff169052565b6200172860e08601838560a81c1661ffff169052565b6200173f6101008601838560b81c1661ffff169052565b620017566101208601838560c81c1661ffff169052565b6200176f6101408601828560d81c1663ffffffff169052565b600186015463ffffffff8282161661016087015292506001600160401b03602084901c81166101808701529150620017b86101a08601838560601c166001600160401b03169052565b620017d16101c08601828560a01c1663ffffffff169052565b50620017e86101e0850160ff8460c01c1615159052565b6001600160e01b0319601883901b1661020085015260028501546001600160a01b0381166102208601529150620018306102408501828460a01c166001600160401b03169052565b5050600383015461026083015292915050565b8151151581526102208101602083015162001864602084018261ffff169052565b5060408301516200187d604084018263ffffffff169052565b50606083015162001896606084018263ffffffff169052565b506080830151620018af608084018263ffffffff169052565b5060a0830151620018c660a084018261ffff169052565b5060c0830151620018df60c084018263ffffffff169052565b5060e0830151620018f660e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b03908116918501919091526101a080860151909116908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b60805160a05160c05160e05161010051610120516159b462001a53600039600081816102da015281816111820152612c640152600081816102ab01528181612c3c015261350001526000818161027c01528181612c120152612d77015260008181610218015281816123f501528181612bad01526135910152600081816101e901528181612b880152818161302901526130bb01526000818161024801528181612bdf0152818161317d01526131ed01526159b46000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063770e2dc4116100cd578063a69c64c011610081578063df0aa9e911610066578063df0aa9e9146108e5578063f2fde38b146108f8578063fbca3b741461090b57600080fd5b8063a69c64c0146108bf578063a6f3ab6c146108d257600080fd5b806382b49eb0116100b257806382b49eb0146107385780638da5cb5b1461089b5780639041be3d146108ac57600080fd5b8063770e2dc41461071d57806379ba50971461073057600080fd5b80633a019940116101245780636def4ce7116101095780636def4ce7146103b6578063714f5ec5146106975780637437ff9f146106aa57600080fd5b80633a0199401461038157806348a98aa41461038b57600080fd5b8063061877e31461015657806306285c69146101a7578063181f5a771461031757806320487ded14610360575b600080fd5b61018961016436600461418f565b6001600160a01b031660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61030a6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161019e91906141ac565b6103536040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161019e9190614268565b61037361036e3660046142b4565b61092b565b60405190815260200161019e565b610389610f83565b005b61039e610399366004614304565b611147565b6040516001600160a01b03909116815260200161019e565b61068a6103c436600461433d565b604080516102a08101825260006080820181815260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e083018290526102008301829052610220830182905261024083018290526102608301829052610280830182905282526020820181905291810182905260608101919091525067ffffffffffffffff90811660009081526006602090815260409182902082516102a081018452815460ff80821615156080840190815261010080840461ffff90811660a08701526301000000850463ffffffff90811660c08801526701000000000000008604811660e0808901919091526b01000000000000000000000087048216938801939093526f0100000000000000000000000000000086048216610120880152710100000000000000000000000000000000008604811661014088015275010000000000000000000000000000000000000000008604821661016088015277010000000000000000000000000000000000000000000000860482166101808801527901000000000000000000000000000000000000000000000000008087049092166101a08801527b0100000000000000000000000000000000000000000000000000000090950485166101c087015260018701548086166101e088015264010000000081048b166102008801526c0100000000000000000000000081048b166102208801527401000000000000000000000000000000000000000080820490961661024088015278010000000000000000000000000000000000000000000000008104909416151561026087015290920490911b6001600160e01b031916610280840152825260028301546001600160a01b0381169483019490945290920490931691810191909152600390910154606082015290565b60405161019e91906144a0565b6103896106a536600461465b565b6111f6565b61071060408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526002546001600160a01b03908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161019e9190614880565b61038961072b366004614958565b61120a565b610389611220565b61083b610746366004614304565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff9190911660009081526008602090815260408083206001600160a01b0394909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b60405161019e9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b6000546001600160a01b031661039e565b6101896108ba36600461433d565b6112e9565b6103896108cd366004614bd2565b61132d565b6103896108e0366004614c90565b61133e565b6103736108f3366004614d15565b61134f565b61038961090636600461418f565b6117c7565b61091e61091936600461433d565b6117d8565b60405161019e9190614d81565b67ffffffffffffffff82166000908152600660205260408120805460ff16610990576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6109c1846109a16020860186614dce565b90506109b06040870187614e1c565b90506109bc8780614dce565b61180c565b60006007816109d6608087016060880161418f565b6001600160a01b03168152602081019190915260400160009081205467ffffffffffffffff169150819003610a5357610a15608085016060860161418f565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b60035460009081906001600160a01b031663ffdb4b37610a796080890160608a0161418f565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8a1660248201526044016040805180830381865afa158015610acc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af09190614e7d565b90925090506000808080610b0760408b018b614e1c565b90501115610b4257610b368a610b2360808c0160608d0161418f565b87610b3160408e018e614e1c565b611934565b91945092509050610b79565b6001870154610b769074010000000000000000000000000000000000000000900463ffffffff16662386f26fc10000614ed6565b92505b865460009077010000000000000000000000000000000000000000000000900461ffff1615610be257610bdf8b6dffffffffffffffffffffffffffff607088901c16610bc860208e018e614dce565b9050610bd760408f018f614e1c565b905086611d10565b90505b875460009063ffffffff8516906f01000000000000000000000000000000900461ffff16610c1360208e018e614dce565b610c1e929150614ed6565b8a54610c3f91906b010000000000000000000000900463ffffffff16614eed565b610c499190614eed565b9050610edc610c5b60808d018d614dce565b8b604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050611e16565b51610ee79082614eed565b60018a01549091506000906c01000000000000000000000000900467ffffffffffffffff16610f26836dffffffffffffffffffffffffffff8a16614ed6565b610f309190614ed6565b90506001600160e01b0388168382610f5267ffffffffffffffff8d168a614ed6565b610f5c9190614eed565b610f669190614eed565b610f709190614f00565b9a50505050505050505050505b92915050565b600354604080517fcdc73d5100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163cdc73d5191600480830192869291908290030181865afa158015610fe5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261100d9190810190614f3b565b6005549091506001600160a01b031660005b825181101561114257600083828151811061103c5761103c614fca565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ce9190614ff9565b90508015611138576110ea6001600160a01b0383168583611ed1565b816001600160a01b0316846001600160a01b03167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161112f91815260200190565b60405180910390a35b505060010161101f565b505050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190615012565b9392505050565b6111fe611f3c565b61120781611f98565b50565b611212611f3c565b61121c82826125ee565b5050565b6001546001600160a01b0316331461127a5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610987565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120600201549091610f7d9174010000000000000000000000000000000000000000900416600161502f565b611335611f3c565b611207816129ce565b611346611f3c565b61120781612aab565b67ffffffffffffffff84166000908152600660205260408120816113768288888888612cc4565b905060005b8160e00151518110156117635760006113976040890189614e1c565b838181106113a7576113a7614fca565b9050604002018036038101906113bd9190615057565b905080602001516000036113fd576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061140d8a8360000151611147565b90506001600160a01b03811615806114c357506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801561149d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c19190615091565b155b156115085781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b6000816001600160a01b0316639a4575b96040518060a001604052808d80600001906115349190614dce565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff8f166020808301919091526001600160a01b03808e16604080850191909152918901516060840152885116608090920191909152516001600160e01b031960e084901b1681526115c791906004016150ae565b6000604051808303816000875af11580156115e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261160e919081019061517b565b9050602081602001515111801561166f575067ffffffffffffffff8b16600090815260086020908152604080832086516001600160a01b0316845282529091205490820151516e01000000000000000000000000000090910463ffffffff16105b156116b45782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b600186015481516116e591790100000000000000000000000000000000000000000000000000900460e01b90613a20565b60408051608081019091526001600160a01b03831660a08201528060c081016040516020818303038152906040528152602001826000015181526020018260200151815260200184602001518152508560e00151858151811061174a5761174a614fca565b602002602001018190525050505080600101905061137b565b50611772818360030154613a5a565b81515260405167ffffffffffffffff8816907f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29906117b19084906152b0565b60405180910390a251519150505b949350505050565b6117cf611f3c565b61120781613b3c565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8516600090815260066020526040902080546301000000900463ffffffff168511156118855780546040517f86933789000000000000000000000000000000000000000000000000000000008152630100000090910463ffffffff16600482015260248101869052604401610987565b8054610100900461ffff168411156118c9576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154604080516020601f860181900481028201810190925284815261192c92790100000000000000000000000000000000000000000000000000900460e01b918690869081908401838280828437600092019190915250613a2092505050565b505050505050565b6000808083815b81811015611d0357600087878381811061195757611957614fca565b90506040020180360381019061196d9190615057565b905060006001600160a01b03166119888c8360000151611147565b6001600160a01b0316036119d65780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b67ffffffffffffffff8b16600090815260086020908152604080832084516001600160a01b03168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052611b445767ffffffffffffffff8c1660009081526006602052604090208054611ae490790100000000000000000000000000000000000000000000000000900461ffff16662386f26fc10000614ed6565b611aee9089614eed565b8154909850611b22907b01000000000000000000000000000000000000000000000000000000900463ffffffff16886153c6565b6001820154909750611b3a9063ffffffff16876153c6565b9550505050611cfb565b604081015160009061ffff1615611c4b5760008c6001600160a01b031684600001516001600160a01b031614611c035760035484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015611bd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bfc91906153e3565b9050611c06565b508a5b620186a0836040015161ffff16611c338660200151846001600160e01b0316613bfd90919063ffffffff16565b611c3d9190614ed6565b611c479190614f00565b9150505b6060820151611c5a90886153c6565b9650816080015186611c6c91906153c6565b8251909650600090611c8b9063ffffffff16662386f26fc10000614ed6565b905080821015611caa57611c9f818a614eed565b985050505050611cfb565b6000836020015163ffffffff16662386f26fc10000611cc99190614ed6565b905080831115611ce957611cdd818b614eed565b99505050505050611cfb565b611cf3838b614eed565b995050505050505b60010161193b565b5050955095509592505050565b60008063ffffffff8316611d2560e086614ed6565b611d31876101c0614eed565b611d3b9190614eed565b611d459190614eed565b67ffffffffffffffff8816600090815260066020526040812080549293509171010000000000000000000000000000000000810463ffffffff1690611da7907501000000000000000000000000000000000000000000900461ffff1685614ed6565b611db19190614eed565b825490915077010000000000000000000000000000000000000000000000900461ffff16611def6dffffffffffffffffffffffffffff8a1683614ed6565b611df99190614ed6565b611e0990655af3107a4000614ed6565b9998505050505050505050565b60408051808201909152600080825260208201526000611e3c8585856101800151613c25565b9050826060015163ffffffff1681600001511115611e86576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015611e9a57508060200151155b156117bf576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611142908490613d9e565b6000546001600160a01b03163314611f965760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610987565b565b60005b815181101561121c576000828281518110611fb857611fb8614fca565b602002602001015190506000838381518110611fd657611fd6614fca565b60200260200101516000015190508067ffffffffffffffff166000148061200e57506020820151610180015167ffffffffffffffff16155b8061204c5750602082015161020001516001600160e01b0319167f2812d52c0000000000000000000000000000000000000000000000000000000014155b1561208f576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610987565b6000600660008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505082600301546000801b036124de57604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b03821615612497576002830180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555b8367ffffffffffffffff167f66951b52bb33e5d462611460f7aa53069005b173e002d9224c15fb986e4ead8f846040516124d191906153fe565b60405180910390a26125de565b60028301546001600160a01b03838116911614612533576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610987565b60208560200151610160015163ffffffff16101561259757602085015161016001516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610987565b8367ffffffffffffffff167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb86602001516040516125d591906155b4565b60405180910390a25b5050505050806001019050611f9b565b60005b82518110156128f757600083828151811061260e5761260e614fca565b6020026020010151905060008160000151905060005b8260200151518110156128e95760008360200151828151811061264957612649614fca565b602002602001015160200151905060008460200151838151811061266f5761266f614fca565b60200260200101516000015190506020826080015163ffffffff1610156126df5760808201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015263ffffffff9091166024820152604401610987565b67ffffffffffffffff841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906128d7908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612624565b5050508060010190506125f1565b5060005b815181101561114257600082828151811061291857612918614fca565b6020026020010151600001519050600083838151811061293a5761293a614fca565b60209081029190910181015181015167ffffffffffffffff841660008181526008845260408082206001600160a01b038516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a350506001016128fb565b60005b815181101561121c5760008282815181106129ee576129ee614fca565b60200260200101516000015190506000838381518110612a1057612a10614fca565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016129d1565b60208101516001600160a01b03161580612ad0575060608101516001600160a01b0316155b15612b07576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556020808401516003805484169185169190911790556040808501516004805485169186169190911790556060808601516005805490951690861617909355805160c0810182527f0000000000000000000000000000000000000000000000000000000000000000851681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16928101929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16828201527f00000000000000000000000000000000000000000000000000000000000000008416928201929092527f0000000000000000000000000000000000000000000000000000000000000000831660808201527f000000000000000000000000000000000000000000000000000000000000000090921660a0830152517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa91612cb99184906155c3565b60405180910390a150565b604080516101a08101825260006101008201818152610120830182905261014083018290526101608301829052610180830182905282526020820181905260609282018390528282018390526080820183905260a0820181905260c082015260e08101919091526040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608086901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dea9190615091565b15612e2d576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610987565b6001600160a01b038216612e6d576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546001600160a01b03163314612eb1576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460ff16612ef8576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610987565b6000612f076040860186614e1c565b9150612f29905086612f1c6020880188614dce565b9050836109bc8980614dce565b801561301d576004546001600160a01b0316801561301b576040517fe0a0e5060000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063e0a0e50690612f88908a908a90600401615730565b600060405180830381600087803b158015612fa257600080fd5b505af1925050508015612fb3575060015b61301b573d808015612fe1576040519150601f19603f3d011682016040523d82523d6000602084013e612fe6565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016109879190614268565b505b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016613059608088016060890161418f565b6001600160a01b03160361306e575083613129565b6003546001600160a01b03166241e5be61308e6080890160608a0161418f565b60405160e083901b6001600160e01b03191681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015613102573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131269190614ff9565b90505b613139608087016060880161418f565b6001600160a01b03167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8260405161317391815260200190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681111561321a576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018290526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610987565b60006134b061322c6080890189614dce565b8b600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050611e16565b60200151613570576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff891660048201526001600160a01b0386811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015613549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061356d919061584e565b90505b604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528b811661014085015260028d018054939493849392610160850192916014916135f9917401000000000000000000000000000000000000000090041661586b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020018567ffffffffffffffff168152508152602001876001600160a01b0316815260200189806020019061365f9190614dce565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016136a38a80614dce565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016139716136ed60808c018c614dce565b8e600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050613e83565b815260200161398660808b0160608c0161418f565b6001600160a01b031681526020018881526020018567ffffffffffffffff8111156139b3576139b36144ed565b604051908082528060200260200182016040528015613a0f57816020015b6139fc6040518060800160405280606081526020016060815260200160608152602001600081525090565b8152602001906001900390816139d15790505b5090529a9950505050505050505050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b031983160161121c5761114281613f03565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001613a9c96959493929190615892565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001613ad391906158e6565b60408051601f1981840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b336001600160a01b03821603613b945760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610987565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a7640000613c1b836001600160e01b038616614ed6565b6111ef9190614f00565b60408051808201909152600080825260208201526000839003613c6657506040805180820190915267ffffffffffffffff82168152600060208201526111ef565b6000613c7284866158f9565b90506000613c838560048189615929565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b031982167fe7e230f00000000000000000000000000000000000000000000000000000000001613d085780806020019051810190613cff9190615953565b925050506111ef565b7f6859a837000000000000000000000000000000000000000000000000000000006001600160e01b0319831601613d6c57604051806040016040528082806020019051810190613d589190614ff9565b8152600060209091015292506111ef915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613df3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613f5e9092919063ffffffff16565b8051909150156111425780806020019051810190613e119190615091565b6111425760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610987565b6102008101516060907fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b0319821601613efb57613ec8858585611e16565b604080518251602080830191909152909201511515908201526060016040516020818303038152906040529150506111ef565b509392505050565b60008151602014613f4257816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109879190614268565b610f7d82806020019051810190613f599190614ff9565b613f6d565b60606117bf8484600085613fda565b60006001600160a01b03821180613f85575061040082105b15613fd65760408051602081018490520160408051601f19818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261098791600401614268565b5090565b6060824710156140525760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610987565b600080866001600160a01b0316858760405161406e919061598b565b60006040518083038185875af1925050503d80600081146140ab576040519150601f19603f3d011682016040523d82523d6000602084013e6140b0565b606091505b50915091506140c1878383876140cc565b979650505050505050565b6060831561413b578251600003614134576001600160a01b0385163b6141345760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610987565b50816117bf565b6117bf83838151156141505781518083602001fd5b8060405162461bcd60e51b81526004016109879190614268565b6001600160a01b038116811461120757600080fd5b803561418a8161416a565b919050565b6000602082840312156141a157600080fd5b81356111ef8161416a565b60c08101610f7d82846001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60005b8381101561423357818101518382015260200161421b565b50506000910152565b60008151808452614254816020860160208601614218565b601f01601f19169290920160200192915050565b6020815260006111ef602083018461423c565b67ffffffffffffffff8116811461120757600080fd5b803561418a8161427b565b600060a082840312156142ae57600080fd5b50919050565b600080604083850312156142c757600080fd5b82356142d28161427b565b9150602083013567ffffffffffffffff8111156142ee57600080fd5b6142fa8582860161429c565b9150509250929050565b6000806040838503121561431757600080fd5b82356143228161427b565b915060208301356143328161416a565b809150509250929050565b60006020828403121561434f57600080fd5b81356111ef8161427b565b8051151582526020810151614375602084018261ffff169052565b50604081015161438d604084018263ffffffff169052565b5060608101516143a5606084018263ffffffff169052565b5060808101516143bd608084018263ffffffff169052565b5060a08101516143d360a084018261ffff169052565b5060c08101516143eb60c084018263ffffffff169052565b5060e081015161440160e084018261ffff169052565b506101008181015161ffff9081169184019190915261012080830151909116908301526101408082015163ffffffff90811691840191909152610160808301518216908401526101808083015167ffffffffffffffff908116918501919091526101a080840151909116908401526101c080830151909116908301526101e080820151151590830152610200908101516001600160e01b031916910152565b6000610280820190506144b482845161435a565b60208301516001600160a01b0316610220830152604083015167ffffffffffffffff166102408301526060909201516102609091015290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561453f5761453f6144ed565b60405290565b604051610220810167ffffffffffffffff8111828210171561453f5761453f6144ed565b6040805190810167ffffffffffffffff8111828210171561453f5761453f6144ed565b60405160c0810167ffffffffffffffff8111828210171561453f5761453f6144ed565b604051601f8201601f1916810167ffffffffffffffff811182821017156145d8576145d86144ed565b604052919050565b600067ffffffffffffffff8211156145fa576145fa6144ed565b5060051b60200190565b801515811461120757600080fd5b803561418a81614604565b803561ffff8116811461418a57600080fd5b803563ffffffff8116811461418a57600080fd5b80356001600160e01b03198116811461418a57600080fd5b6000602080838503121561466e57600080fd5b823567ffffffffffffffff81111561468557600080fd5b8301601f8101851361469657600080fd5b80356146a96146a4826145e0565b6145af565b81815261026091820283018401918482019190888411156146c957600080fd5b938501935b8385101561487457848903818112156146e75760008081fd5b6146ef61451c565b86356146fa8161427b565b8152610220601f1983018113156147115760008081fd5b614719614545565b9250614726898901614612565b83526040614735818a0161461d565b8a8501526060614746818b0161462f565b828601526080614757818c0161462f565b8287015260a0915061476a828c0161462f565b9086015260c061477b8b820161461d565b8287015260e0915061478e828c0161462f565b908601526101006147a08b820161461d565b8287015261012091506147b4828c0161461d565b908601526101406147c68b820161461d565b8287015261016091506147da828c0161462f565b908601526101806147ec8b820161462f565b828701526101a09150614800828c01614291565b908601526101c06148128b8201614291565b828701526101e09150614826828c0161462f565b908601526102006148388b8201614612565b82870152614847848c01614643565b818701525050838a84015261485f6102408a0161417f565b908301525084525093840193918501916146ce565b50979650505050505050565b60808101610f7d828480516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b600082601f8301126148cd57600080fd5b813560206148dd6146a4836145e0565b82815260069290921b840181019181810190868411156148fc57600080fd5b8286015b8481101561494d57604081890312156149195760008081fd5b614921614569565b813561492c8161427b565b81528185013561493b8161416a565b81860152835291830191604001614900565b509695505050505050565b6000806040838503121561496b57600080fd5b67ffffffffffffffff8335111561498157600080fd5b83601f84358501011261499357600080fd5b6149a36146a484358501356145e0565b8335840180358083526020808401939260059290921b909101018610156149c957600080fd5b602085358601015b85358601803560051b01602001811015614b9c5767ffffffffffffffff813511156149fb57600080fd5b6040601f19823588358901018903011215614a1557600080fd5b614a1d614569565b614a306020833589358a0101013561427b565b863587018235016020810135825267ffffffffffffffff6040909101351115614a5857600080fd5b86358701823501604081013501603f81018913614a7457600080fd5b614a846146a460208301356145e0565b602082810135808352908201919060e00283016040018b1015614aa657600080fd5b604083015b604060e0602086013502850101811015614b835760e0818d031215614acf57600080fd5b614ad7614569565b614ae1823561416a565b8135815260c0601f19838f03011215614af957600080fd5b614b0161458c565b614b0d6020840161462f565b8152614b1b6040840161462f565b6020820152614b2c6060840161461d565b6040820152614b3d6080840161462f565b6060820152614b4e60a0840161462f565b6080820152614b6060c0840135614604565b60c083013560a0820152602082810191909152908452929092019160e001614aab565b50602084810191909152928652505092830192016149d1565b5092505067ffffffffffffffff60208401351115614bb957600080fd5b614bc984602085013585016148bc565b90509250929050565b60006020808385031215614be557600080fd5b823567ffffffffffffffff811115614bfc57600080fd5b8301601f81018513614c0d57600080fd5b8035614c1b6146a4826145e0565b81815260069190911b82018301908381019087831115614c3a57600080fd5b928401925b828410156140c15760408489031215614c585760008081fd5b614c60614569565b8435614c6b8161416a565b815284860135614c7a8161427b565b8187015282526040939093019290840190614c3f565b600060808284031215614ca257600080fd5b6040516080810181811067ffffffffffffffff82111715614cc557614cc56144ed565b6040528235614cd38161416a565b81526020830135614ce38161416a565b60208201526040830135614cf68161416a565b60408201526060830135614d098161416a565b60608201529392505050565b60008060008060808587031215614d2b57600080fd5b8435614d368161427b565b9350602085013567ffffffffffffffff811115614d5257600080fd5b614d5e8782880161429c565b935050604085013591506060850135614d768161416a565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b81811015614dc25783516001600160a01b031683529284019291840191600101614d9d565b50909695505050505050565b6000808335601e19843603018112614de557600080fd5b83018035915067ffffffffffffffff821115614e0057600080fd5b602001915036819003821315614e1557600080fd5b9250929050565b6000808335601e19843603018112614e3357600080fd5b83018035915067ffffffffffffffff821115614e4e57600080fd5b6020019150600681901b3603821315614e1557600080fd5b80516001600160e01b038116811461418a57600080fd5b60008060408385031215614e9057600080fd5b614e9983614e66565b9150614bc960208401614e66565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f7d57610f7d614ea7565b80820180821115610f7d57610f7d614ea7565b600082614f36577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020808385031215614f4e57600080fd5b825167ffffffffffffffff811115614f6557600080fd5b8301601f81018513614f7657600080fd5b8051614f846146a4826145e0565b81815260059190911b82018301908381019087831115614fa357600080fd5b928401925b828410156140c1578351614fbb8161416a565b82529284019290840190614fa8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561500b57600080fd5b5051919050565b60006020828403121561502457600080fd5b81516111ef8161416a565b67ffffffffffffffff81811683821601908082111561505057615050614ea7565b5092915050565b60006040828403121561506957600080fd5b615071614569565b823561507c8161416a565b81526020928301359281019290925250919050565b6000602082840312156150a357600080fd5b81516111ef81614604565b602081526000825160a060208401526150ca60c084018261423c565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f83011261512857600080fd5b815167ffffffffffffffff811115615142576151426144ed565b6151556020601f19601f840116016145af565b81815284602083860101111561516a57600080fd5b6117bf826020830160208701614218565b60006020828403121561518d57600080fd5b815167ffffffffffffffff808211156151a557600080fd5b90830190604082860312156151b957600080fd5b6151c1614569565b8251828111156151d057600080fd5b6151dc87828601615117565b8252506020830151828111156151f157600080fd5b6151fd87828601615117565b60208301525095945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156152a357601f1986840301895281516080815181865261524f8287018261423c565b9150508582015185820387870152615267828261423c565b91505060408083015186830382880152615281838261423c565b6060948501519790940196909652505098840198925090830190600101615229565b5090979650505050505050565b6020815261530160208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161531d60c08401826001600160a01b03169052565b5060408301516101808060e085015261533a6101a085018361423c565b91506060850151601f198086850301610100870152615359848361423c565b9350608087015191508086850301610120870152615377848361423c565b935060a087015191506153966101408701836001600160a01b03169052565b60c087015161016087015260e08701519150808685030183870152506153bc838261520c565b9695505050505050565b63ffffffff81811683821601908082111561505057615050614ea7565b6000602082840312156153f557600080fd5b6111ef82614e66565b815460ff81161515825261028082019061ffff600882901c8116602085015263ffffffff601883901c8116604086015261544560608601828560381c1663ffffffff169052565b61545c60808601828560581c1663ffffffff169052565b61547160a08601838560781c1661ffff169052565b61548860c08601828560881c1663ffffffff169052565b61549d60e08601838560a81c1661ffff169052565b6154b36101008601838560b81c1661ffff169052565b6154c96101208601838560c81c1661ffff169052565b6154e16101408601828560d81c1663ffffffff169052565b600186015463ffffffff82821616610160870152925067ffffffffffffffff602084901c8116610180870152915061552b6101a08601838560601c1667ffffffffffffffff169052565b6155436101c08601828560a01c1663ffffffff169052565b506155596101e0850160ff8460c01c1615159052565b601882901b6001600160e01b03191661020085015260028501546001600160a01b03811661022086015291506155a16102408501828460a01c1667ffffffffffffffff169052565b5050600383015461026083015292915050565b6102208101610f7d828461435a565b610140810161563082856001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b82516001600160a01b0390811660c08401526020840151811660e0840152604084015181166101008401526060840151166101208301526111ef565b6000808335601e1984360301811261568357600080fd5b830160208101925035905067ffffffffffffffff8111156156a357600080fd5b803603821315614e1557600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8183526000602080850194508260005b858110156157255781356157008161416a565b6001600160a01b031687528183013583880152604096870196909101906001016156ed565b509495945050505050565b600067ffffffffffffffff808516835260406020840152615751848561566c565b60a0604086015261576660e0860182846156b2565b915050615776602086018661566c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808785030160608801526157ac8483856156b2565b935060408801359250601e198836030183126157c757600080fd5b602092880192830192359150848211156157e057600080fd5b8160061b36038313156157f257600080fd5b808785030160808801526158078483856156dd565b94506158156060890161417f565b6001600160a01b03811660a08901529350615833608089018961566c565b94509250808786030160c088015250506140c18383836156b2565b60006020828403121561586057600080fd5b81516111ef8161427b565b600067ffffffffffffffff80831681810361588857615888614ea7565b6001019392505050565b60006001600160a01b03808916835260c060208401526158b560c084018961423c565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b6020815260006111ef602083018461520c565b6001600160e01b031981358181169160048510156159215780818660040360031b1b83161692505b505092915050565b6000808585111561593957600080fd5b8386111561594657600080fd5b5050820193919092039150565b60006040828403121561596557600080fd5b61596d614569565b82518152602083015161597f81614604565b60208201529392505050565b6000825161599d818460208701614218565b919091019291505056fea164736f6c6343000818000a", } var EVM2EVMMultiOnRampABI = EVM2EVMMultiOnRampMetaData.ABI @@ -794,7 +805,7 @@ func (it *EVM2EVMMultiOnRampCCIPSendRequestedIterator) Close() error { type EVM2EVMMultiOnRampCCIPSendRequested struct { DestChainSelector uint64 - Message InternalEVM2EVMMessage + Message InternalEVM2AnyRampMessage Raw types.Log } @@ -2209,7 +2220,7 @@ func (EVM2EVMMultiOnRampAdminSet) Topic() common.Hash { } func (EVM2EVMMultiOnRampCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0xc79f9c3e610deac14de4e704195fe17eab0983ee9916866bc04d16a00f54daa6") + return common.HexToHash("0x0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29") } func (EVM2EVMMultiOnRampConfigSet) Topic() common.Hash { @@ -2217,11 +2228,11 @@ func (EVM2EVMMultiOnRampConfigSet) Topic() common.Hash { } func (EVM2EVMMultiOnRampDestChainAdded) Topic() common.Hash { - return common.HexToHash("0x4be92415590c4554edbd7d3fbf308eeb6e5d00ababade0791f835b4a18416ed6") + return common.HexToHash("0x66951b52bb33e5d462611460f7aa53069005b173e002d9224c15fb986e4ead8f") } func (EVM2EVMMultiOnRampDestChainDynamicConfigUpdated) Topic() common.Hash { - return common.HexToHash("0x1173725509a61aed633c58cd12e31c104cd26ca24f6c270c8ac81c5f6f12e8e9") + return common.HexToHash("0xd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb") } func (EVM2EVMMultiOnRampFeePaid) 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 f41fb552d4..8fb8d08b6f 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -28,19 +28,13 @@ var ( _ = abi.ConvertType ) -type ClientEVMTokenAmount struct { - Token common.Address - Amount *big.Int -} - type InternalAny2EVMRampMessage struct { - Header InternalRampMessageHeader - Sender []byte - Data []byte - Receiver common.Address - GasLimit *big.Int - TokenAmounts []ClientEVMTokenAmount - SourceTokenData [][]byte + Header InternalRampMessageHeader + Sender []byte + Data []byte + Receiver common.Address + GasLimit *big.Int + TokenAmounts []InternalRampTokenAmount } type InternalRampMessageHeader struct { @@ -51,9 +45,16 @@ type InternalRampMessageHeader struct { Nonce uint64 } +type InternalRampTokenAmount struct { + SourcePoolAddress []byte + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int +} + var MessageHasherMetaData = &bind.MetaData{ - ABI: "[{\"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\"},{\"internalType\":\"bytes32\",\"name\":\"sourceTokenDataHash\",\"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\":[{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"name\":\"encodeSourceTokenDataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"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\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"}],\"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: "0x608060405234801561001057600080fd5b50610bb8806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063bf0619ad11610050578063bf0619ad146100d0578063c2cfa165146100e3578063cd34ba82146100f657600080fd5b80633b61b52e14610077578063a1e747df1461009d578063a91d3aeb146100bd575b600080fd5b61008a6100853660046106e3565b610109565b6040519081526020015b60405180910390f35b6100b06100ab366004610812565b61011c565b60405161009491906108de565b6100b06100cb3660046108f1565b61014e565b6100b06100de366004610972565b610186565b6100b06100f13660046109b5565b6101bd565b6100b06101043660046109f2565b6101e6565b600061011583836101f9565b9392505050565b6060848484846040516020016101359493929190610a27565b6040516020818303038152906040529050949350505050565b606086868686868660405160200161016b96959493929190610a64565b60405160208183030381529060405290509695505050505050565b604080516020810188905290810186905260608181018690526080820185905260a0820184905260c082018390529060e00161016b565b6060816040516020016101d09190610ac4565b6040516020818303038152906040529050919050565b6060816040516020016101d09190610b46565b81516020808201516040928301519251600093849361023f937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610a27565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976102a69794969395929491939101610a64565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016102dd9190610b46565b604051602081830303815290604052805190602001208760c001516040516020016103089190610ac4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156103d8576103d8610386565b60405290565b60405160e0810167ffffffffffffffff811182821017156103d8576103d8610386565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561044857610448610386565b604052919050565b803567ffffffffffffffff8116811461046857600080fd5b919050565b600060a0828403121561047f57600080fd5b60405160a0810181811067ffffffffffffffff821117156104a2576104a2610386565b604052823581529050806104b860208401610450565b60208201526104c960408401610450565b60408201526104da60608401610450565b60608201526104eb60808401610450565b60808201525092915050565b600082601f83011261050857600080fd5b813567ffffffffffffffff81111561052257610522610386565b61055360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610401565b81815284602083860101111561056857600080fd5b816020850160208301376000918101602001919091529392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461046857600080fd5b600067ffffffffffffffff8211156105c3576105c3610386565b5060051b60200190565b600082601f8301126105de57600080fd5b813560206105f36105ee836105a9565b610401565b82815260069290921b8401810191818101908684111561061257600080fd5b8286015b84811015610658576040818903121561062f5760008081fd5b6106376103b5565b61064082610585565b81528185013585820152835291830191604001610616565b509695505050505050565b600082601f83011261067457600080fd5b813560206106846105ee836105a9565b82815260059290921b840181019181810190868411156106a357600080fd5b8286015b8481101561065857803567ffffffffffffffff8111156106c75760008081fd5b6106d58986838b01016104f7565b8452509183019183016106a7565b600080604083850312156106f657600080fd5b823567ffffffffffffffff8082111561070e57600080fd5b90840190610160828703121561072357600080fd5b61072b6103de565b610735878461046d565b815260a08301358281111561074957600080fd5b610755888286016104f7565b60208301525060c08301358281111561076d57600080fd5b610779888286016104f7565b60408301525061078b60e08401610585565b60608201526101008301356080820152610120830135828111156107ae57600080fd5b6107ba888286016105cd565b60a083015250610140830135828111156107d357600080fd5b6107df88828601610663565b60c083015250935060208501359150808211156107fb57600080fd5b50610808858286016104f7565b9150509250929050565b6000806000806080858703121561082857600080fd5b8435935061083860208601610450565b925061084660408601610450565b9150606085013567ffffffffffffffff81111561086257600080fd5b61086e878288016104f7565b91505092959194509250565b6000815180845260005b818110156108a057602081850181015186830182015201610884565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610115602083018461087a565b60008060008060008060c0878903121561090a57600080fd5b86359550602087013567ffffffffffffffff81111561092857600080fd5b61093489828a016104f7565b95505061094360408801610585565b935061095160608801610450565b92506080870135915061096660a08801610450565b90509295509295509295565b60008060008060008060c0878903121561098b57600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b6000602082840312156109c757600080fd5b813567ffffffffffffffff8111156109de57600080fd5b6109ea84828501610663565b949350505050565b600060208284031215610a0457600080fd5b813567ffffffffffffffff811115610a1b57600080fd5b6109ea848285016105cd565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610a5a608083018461087a565b9695505050505050565b86815260c060208201526000610a7d60c083018861087a565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015610b39577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452610b2785835161087a565b94509285019290850190600101610aed565b5092979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015610b9e578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101610b63565b509197965050505050505056fea164736f6c6343000818000a", + ABI: "[{\"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: "0x608060405234801561001057600080fd5b50610af3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806399df8d051161005057806399df8d05146100b6578063a1e747df14610101578063a91d3aeb1461011457600080fd5b8063902e94a01461006c5780639511afaa14610095575b600080fd5b61007f61007a3660046105d0565b610127565b60405161008c9190610671565b60405180910390f35b6100a86100a336600461074f565b610150565b60405190815260200161008c565b61007f6100c4366004610859565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b61007f61010f366004610894565b610163565b61007f6101223660046108fc565b610195565b60608160405160200161013a919061097d565b6040516020818303038152906040529050919050565b600061015c83836101cd565b9392505050565b60608484848460405160200161017c9493929190610a49565b6040516020818303038152906040529050949350505050565b60608686868686866040516020016101b296959493929190610a86565b60405160208183030381529060405290509695505050505050565b815160208082015160409283015192516000938493610213937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610a49565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761027a9794969395929491939101610a86565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016102b1919061097d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c00160405160208183030381529060405280519060200120905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561037c5761037c61032a565b60405290565b60405160c0810167ffffffffffffffff8111828210171561037c5761037c61032a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103ec576103ec61032a565b604052919050565b600082601f83011261040557600080fd5b813567ffffffffffffffff81111561041f5761041f61032a565b61045060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016103a5565b81815284602083860101111561046557600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261049357600080fd5b8135602067ffffffffffffffff808311156104b0576104b061032a565b8260051b6104bf8382016103a5565b93845285810183019383810190888611156104d957600080fd5b84880192505b858310156105c4578235848111156104f75760008081fd5b88016080818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181131561052d5760008081fd5b610535610359565b87830135878111156105475760008081fd5b6105558d8a838701016103f4565b8252506040808401358881111561056c5760008081fd5b61057a8e8b838801016103f4565b8a84015250606080850135898111156105935760008081fd5b6105a18f8c838901016103f4565b9284019290925293909201359281019290925250825291840191908401906104df565b98975050505050505050565b6000602082840312156105e257600080fd5b813567ffffffffffffffff8111156105f957600080fd5b61060584828501610482565b949350505050565b6000815180845260005b8181101561063357602081850181015186830182015201610617565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061015c602083018461060d565b803567ffffffffffffffff8116811461069c57600080fd5b919050565b600060a082840312156106b357600080fd5b60405160a0810181811067ffffffffffffffff821117156106d6576106d661032a565b604052823581529050806106ec60208401610684565b60208201526106fd60408401610684565b604082015261070e60608401610684565b606082015261071f60808401610684565b60808201525092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461069c57600080fd5b6000806040838503121561076257600080fd5b823567ffffffffffffffff8082111561077a57600080fd5b90840190610140828703121561078f57600080fd5b610797610382565b6107a187846106a1565b815260a0830135828111156107b557600080fd5b6107c1888286016103f4565b60208301525060c0830135828111156107d957600080fd5b6107e5888286016103f4565b6040830152506107f760e0840161072b565b606082015261010083013560808201526101208301358281111561081a57600080fd5b61082688828601610482565b60a0830152509350602085013591508082111561084257600080fd5b5061084f858286016103f4565b9150509250929050565b600080600080600060a0868803121561087157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600080600080608085870312156108aa57600080fd5b843593506108ba60208601610684565b92506108c860408601610684565b9150606085013567ffffffffffffffff8111156108e457600080fd5b6108f0878288016103f4565b91505092959194509250565b60008060008060008060c0878903121561091557600080fd5b86359550602087013567ffffffffffffffff81111561093357600080fd5b61093f89828a016103f4565b95505061094e6040880161072b565b935061095c60608801610684565b92506080870135915061097160a08801610684565b90509295509295509295565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610a3b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151608081518186526109ea8287018261060d565b915050888201518582038a870152610a02828261060d565b9150508782015185820389870152610a1a828261060d565b606093840151969093019590955250948701949250908601906001016109a6565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610a7c608083018461060d565b9695505050505050565b86815260c060208201526000610a9f60c083018861060d565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", } var MessageHasherABI = MessageHasherMetaData.ABI @@ -192,9 +193,9 @@ func (_MessageHasher *MessageHasherTransactorRaw) Transact(opts *bind.TransactOp return _MessageHasher.Contract.contract.Transact(opts, method, params...) } -func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeFinalHashPreimage", leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash) + err := _MessageHasher.contract.Call(opts, &out, "encodeFinalHashPreimage", leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash) if err != nil { return *new([]byte), err @@ -206,12 +207,12 @@ func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.Ca } -func (_MessageHasher *MessageHasherSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash) +func (_MessageHasher *MessageHasherSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash) } -func (_MessageHasher *MessageHasherCallerSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash, sourceTokenDataHash) +func (_MessageHasher *MessageHasherCallerSession) EncodeFinalHashPreimage(leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { + return _MessageHasher.Contract.EncodeFinalHashPreimage(&_MessageHasher.CallOpts, leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash) } func (_MessageHasher *MessageHasherCaller) EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) { @@ -258,9 +259,9 @@ func (_MessageHasher *MessageHasherCallerSession) EncodeMetadataHashPreimage(any return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) } -func (_MessageHasher *MessageHasherCaller) EncodeSourceTokenDataHashPreimage(opts *bind.CallOpts, sourceTokenData [][]byte) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeSourceTokenDataHashPreimage", sourceTokenData) + err := _MessageHasher.contract.Call(opts, &out, "encodeTokenAmountsHashPreimage", rampTokenAmounts) if err != nil { return *new([]byte), err @@ -272,34 +273,12 @@ func (_MessageHasher *MessageHasherCaller) EncodeSourceTokenDataHashPreimage(opt } -func (_MessageHasher *MessageHasherSession) EncodeSourceTokenDataHashPreimage(sourceTokenData [][]byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeSourceTokenDataHashPreimage(&_MessageHasher.CallOpts, sourceTokenData) +func (_MessageHasher *MessageHasherSession) EncodeTokenAmountsHashPreimage(rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, rampTokenAmounts) } -func (_MessageHasher *MessageHasherCallerSession) EncodeSourceTokenDataHashPreimage(sourceTokenData [][]byte) ([]byte, error) { - return _MessageHasher.Contract.EncodeSourceTokenDataHashPreimage(&_MessageHasher.CallOpts, sourceTokenData) -} - -func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmounts []ClientEVMTokenAmount) ([]byte, error) { - var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeTokenAmountsHashPreimage", tokenAmounts) - - if err != nil { - return *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - - return out0, err - -} - -func (_MessageHasher *MessageHasherSession) EncodeTokenAmountsHashPreimage(tokenAmounts []ClientEVMTokenAmount) ([]byte, error) { - return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmounts) -} - -func (_MessageHasher *MessageHasherCallerSession) EncodeTokenAmountsHashPreimage(tokenAmounts []ClientEVMTokenAmount) ([]byte, error) { - return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmounts) +func (_MessageHasher *MessageHasherCallerSession) EncodeTokenAmountsHashPreimage(rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, rampTokenAmounts) } func (_MessageHasher *MessageHasherCaller) Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) { @@ -329,15 +308,13 @@ func (_MessageHasher *MessageHasher) Address() common.Address { } type MessageHasherInterface interface { - EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte, sourceTokenDataHash [32]byte) ([]byte, error) + EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, error) EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) - EncodeSourceTokenDataHashPreimage(opts *bind.CallOpts, sourceTokenData [][]byte) ([]byte, error) - - EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmounts []ClientEVMTokenAmount) ([]byte, error) + EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, 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 02a4b18652..c4432d6860 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 @@ -9,14 +9,14 @@ ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../ commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin ddc26c10c2a52b59624faae9005827b09b98db4566887a736005e8cc37cf8a51 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 09ac589a267ac59ae3fef7534bebe6da38c427c48b60b5304b9e55408e028337 -evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 8edc6f93d7d5f045776cd843c0fae8b94a73835d2c939b2f94fa906ca5f26b97 +evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 2ab5cd4acb0c0b7087397d0c99e928119ef9e174bfd55628e6b2daf14f2da1fe +evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin e304765672aeab78529edc35f6ee44779c098643fe3a7b4f3c0f33a9493016ac evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b6132cb22370d62b1b20174bbe832ec87df61f6ab65f7fe2515733bdd10a30f5 evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 383e9930fbc1b7fbb6554cc8857229d207fd6742e87c7fb1a37002347e8de8e2 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin c65c226e1e4d38414bd4a1b76fc8aca3cb3dd98df61268424c44564f455d3752 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin 8b929fab79d1caeea4c57e08cc523eb8ab45ec5c08f46da866b82c15ba94d9ad 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 b16f2182c6f262f4864315c90d35efc0342f5ee3580896e9bca50a5b98d51282 +message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 9195ef458fee819595502b5b33263e4646f9526cbac0bd89cc322afe5a77ae19 mock_arm_contract: ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.abi ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.bin e7a3a6c3eda5fb882e16bcc2b4340f78523acb67907bcdcaf3c8ffc51488688e mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin e0cf17a38b438239fc6294ddca88f86b6c39e4542aefd9815b2d92987191b8bd mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin 33bdad70822e889de7c720ed20085cf9cd3f8eba8b68f26bd6535197749595fe diff --git a/core/services/ocr3/plugins/ccipevm/msghasher.go b/core/services/ocr3/plugins/ccipevm/msghasher.go index 948775a7be..13d0410ea3 100644 --- a/core/services/ocr3/plugins/ccipevm/msghasher.go +++ b/core/services/ocr3/plugins/ccipevm/msghasher.go @@ -12,7 +12,6 @@ import ( "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/evm_2_evm_multi_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" ) @@ -59,23 +58,26 @@ func NewMessageHasherV1( ) */ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.CCIPMsg) (cciptypes.Bytes32, error) { - tokenAmounts := make([]evm_2_evm_multi_onramp.ClientEVMTokenAmount, len(msg.TokenAmounts)) + if len(msg.TokenAmounts) != len(msg.SourceTokenData) { + return [32]byte{}, fmt.Errorf("token amounts and source token data must have the same length") + } + + // TODO: this is not fully correct, but will be fixed in future PRs. + // CCIPMsg is missing the source pool address and the dest token address. + rampTokenAmounts := make([]message_hasher.InternalRampTokenAmount, len(msg.TokenAmounts)) for i, ta := range msg.TokenAmounts { - tokenAmounts[i] = evm_2_evm_multi_onramp.ClientEVMTokenAmount{ - Token: common.HexToAddress(string(ta.Token)), - Amount: ta.Amount, + rampTokenAmounts[i] = message_hasher.InternalRampTokenAmount{ + // SourcePoolAddress: , // TODO: fill this in future PRs. + // DestTokenAddress: , // TODO: fill this in future PRs. + ExtraData: msg.SourceTokenData[i], + Amount: ta.Amount, } } - encodedTokens, err := h.abiEncode("encodeTokenAmountsHashPreimage", tokenAmounts) + encodedRampTokenAmounts, err := h.abiEncode("encodeTokenAmountsHashPreimage", rampTokenAmounts) if err != nil { return [32]byte{}, fmt.Errorf("abi encode token amounts: %w", err) } - encodedSourceTokenData, err := h.abiEncode("encodeSourceTokenDataHashPreimage", msg.SourceTokenData) - if err != nil { - return [32]byte{}, fmt.Errorf("pack source token data: %w", err) - } - metaDataHashInput, err := h.abiEncode( "encodeMetadataHashPreimage", ANY_2_EVM_MESSAGE_HASH, @@ -129,8 +131,7 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.CCIPMsg) (ccipty utils.Keccak256Fixed(metaDataHashInput), utils.Keccak256Fixed(fixedSizeFieldsEncoded), utils.Keccak256Fixed(msg.Data), - utils.Keccak256Fixed(encodedTokens), - utils.Keccak256Fixed(encodedSourceTokenData), + utils.Keccak256Fixed(encodedRampTokenAmounts), ) if err != nil { return [32]byte{}, fmt.Errorf("abi encode packed values: %w", err) diff --git a/core/services/ocr3/plugins/ccipevm/msghasher_test.go b/core/services/ocr3/plugins/ccipevm/msghasher_test.go index 0bdf2c04b9..a16815a0d7 100644 --- a/core/services/ocr3/plugins/ccipevm/msghasher_test.go +++ b/core/services/ocr3/plugins/ccipevm/msghasher_test.go @@ -43,11 +43,13 @@ func testHasher(ctx context.Context, t *testing.T, d *testSetupData) { onRampAddress := testutils.NewAddress().Bytes() ccipMsg := createCCIPMsg(t) - evmTokenAmounts := make([]message_hasher.ClientEVMTokenAmount, 0, len(ccipMsg.TokenAmounts)) - for _, ta := range ccipMsg.TokenAmounts { - evmTokenAmounts = append(evmTokenAmounts, message_hasher.ClientEVMTokenAmount{ - Token: common.HexToAddress(string(ta.Token)), - Amount: ta.Amount, + tokenAmounts := make([]message_hasher.InternalRampTokenAmount, 0, len(ccipMsg.TokenAmounts)) + for i := range ccipMsg.TokenAmounts { + tokenAmounts = append(tokenAmounts, message_hasher.InternalRampTokenAmount{ + // SourcePoolAddress: , // TODO: fill this in future PRs. + // DestTokenAddress: , // TODO: fill this in future PRs. + ExtraData: ccipMsg.SourceTokenData[i], + Amount: ccipMsg.TokenAmounts[i].Amount, }) } evmMsg := message_hasher.InternalAny2EVMRampMessage{ @@ -58,12 +60,11 @@ func testHasher(ctx context.Context, t *testing.T, d *testSetupData) { SequenceNumber: uint64(ccipMsg.SeqNum), Nonce: ccipMsg.Nonce, }, - Sender: common.HexToAddress(string(ccipMsg.Sender)).Bytes(), - Receiver: common.HexToAddress(string(ccipMsg.Receiver)), - GasLimit: ccipMsg.ChainFeeLimit.Int, - Data: ccipMsg.Data, - TokenAmounts: evmTokenAmounts, - SourceTokenData: ccipMsg.SourceTokenData, + Sender: common.HexToAddress(string(ccipMsg.Sender)).Bytes(), + Receiver: common.HexToAddress(string(ccipMsg.Receiver)), + GasLimit: ccipMsg.ChainFeeLimit.Int, + Data: ccipMsg.Data, + TokenAmounts: tokenAmounts, } expectedHash, err := d.contract.Hash(&bind.CallOpts{Context: ctx}, evmMsg, onRampAddress) @@ -94,19 +95,21 @@ func createCCIPMsg(t *testing.T) cciptypes.CCIPMsg { _, err = cryptorand.Read(messageData) require.NoError(t, err) - sourceTokenDatas := make([][]byte, rand.Intn(10)) - for i := range sourceTokenDatas { - sourceTokenDatas[i] = sourceTokenData + numTokens := rand.Intn(10) + var sourceTokenDatas [][]byte + for i := 0; i < numTokens; i++ { + sourceTokenDatas = append(sourceTokenDatas, sourceTokenData) } - numTokenAmounts := rand.Intn(50) - tokenAmounts := make([]cciptypes.TokenAmount, 0, numTokenAmounts) - for i := 0; i < numTokenAmounts; i++ { + var tokenAmounts []cciptypes.TokenAmount + for i := 0; i < len(sourceTokenDatas); i++ { tokenAmounts = append(tokenAmounts, cciptypes.TokenAmount{ - Token: types.Account(utils.RandomAddress().String()), + // Ignored by the hasher, will be removed in future PR. + // Token: types.Account(utils.RandomAddress().String()), Amount: big.NewInt(0).SetUint64(rand.Uint64()), }) } + return cciptypes.CCIPMsg{ CCIPMsgBaseDetails: cciptypes.CCIPMsgBaseDetails{ ID: hex.EncodeToString(messageID[:]), From 9a2b457588590381157ddc9156634db505b7a055 Mon Sep 17 00:00:00 2001 From: nogo <110664798+0xnogo@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:11:22 +0200 Subject: [PATCH 57/61] bump chainlink-common (#1162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumping `chainlink-common` to latest available commit (https://github.com/smartcontractkit/chainlink-common/commit/24440372521aae65102b9b94c02d17e35ed32dc5) Fixed a breaking change introduced by https://github.com/smartcontractkit/chainlink-common/commit/dc1fbe45acc016eb543106d4db97c16008bb0c83 Running: * make gomodtidy * make chainlink-dev (✅) --------- Co-authored-by: Makram --- .../v0.8/ccip/test/helpers/MessageHasher.sol | 20 ++ core/capabilities/registry.go | 4 + core/capabilities/remote/dispatcher_test.go | 2 +- core/capabilities/remote/types/messages.pb.go | 2 +- .../evm/headtracker/head_tracker_test.go | 3 +- .../message_hasher/message_hasher.go | 109 ++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/scripts/go.mod | 59 +++-- core/scripts/go.sum | 207 ++++++----------- .../ocr3/plugins/ccipevm/msghasher.go | 132 ++++++----- .../ocr3/plugins/ccipevm/msghasher_test.go | 174 +++++++++------ .../relay/evm/mercury/wsrpc/pb/mercury.pb.go | 2 +- go.mod | 60 ++--- go.sum | 211 ++++++------------ integration-tests/go.mod | 59 +++-- integration-tests/go.sum | 143 ++++++------ integration-tests/load/go.mod | 59 +++-- integration-tests/load/go.sum | 143 ++++++------ 18 files changed, 692 insertions(+), 699 deletions(-) diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol index f0ca898a6c..19f35df796 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -6,6 +6,7 @@ import {Internal} from "../../libraries/Internal.sol"; /// @notice MessageHasher is a contract that utility functions to hash an Any2EVMRampMessage /// and encode various preimages for the final hash of the message. +/// @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); @@ -48,4 +49,23 @@ contract MessageHasher { ) public pure returns (bytes memory) { return abi.encode(leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash); } + + function encodeEVMExtraArgsV1(Client.EVMExtraArgsV1 memory extraArgs) public pure returns (bytes memory) { + return Client._argsToBytes(extraArgs); + } + + function encodeEVMExtraArgsV2(Client.EVMExtraArgsV2 memory extraArgs) public pure returns (bytes memory) { + return Client._argsToBytes(extraArgs); + } + + function decodeEVMExtraArgsV1(uint256 gasLimit) public pure returns (Client.EVMExtraArgsV1 memory) { + return Client.EVMExtraArgsV1(gasLimit); + } + + function decodeEVMExtraArgsV2( + uint256 gasLimit, + bool allowOutOfOrderExecution + ) public pure returns (Client.EVMExtraArgsV2 memory) { + return Client.EVMExtraArgsV2(gasLimit, allowOutOfOrderExecution); + } } diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 3cfe1d169b..4cca25d03c 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -22,6 +22,10 @@ type Registry struct { mu sync.RWMutex } +func (r *Registry) GetLocalNode(_ context.Context) (capabilities.Node, error) { + return capabilities.Node{}, nil +} + // Get gets a capability from the registry. func (r *Registry) Get(_ context.Context, id string) (capabilities.BaseCapability, error) { r.mu.RLock() diff --git a/core/capabilities/remote/dispatcher_test.go b/core/capabilities/remote/dispatcher_test.go index 040ee849e0..173972375a 100644 --- a/core/capabilities/remote/dispatcher_test.go +++ b/core/capabilities/remote/dispatcher_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - commonMocks "github.com/smartcontractkit/chainlink-common/pkg/types/mocks" + 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" diff --git a/core/capabilities/remote/types/messages.pb.go b/core/capabilities/remote/types/messages.pb.go index d1b86d9feb..68d8f4a262 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.33.0 +// protoc-gen-go v1.34.1 // protoc v4.25.1 // source: core/capabilities/remote/types/messages.proto diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index 81ba3ea85f..21ff1b1a92 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -330,7 +330,6 @@ func TestHeadTracker_Start(t *testing.T) { func TestHeadTracker_CallsHeadTrackableCallbacks(t *testing.T) { t.Parallel() - g := gomega.NewWithT(t) db := pgtest.NewSqlxDB(t) config := testutils.NewTestChainScopedConfig(t, nil) @@ -360,7 +359,7 @@ func TestHeadTracker_CallsHeadTrackableCallbacks(t *testing.T) { headers := <-chchHeaders headers.TrySend(&evmtypes.Head{Number: 1, Hash: utils.NewHash(), EVMChainID: ubig.New(testutils.FixtureChainID)}) - g.Eventually(checker.OnNewLongestChainCount).Should(gomega.Equal(int32(1))) + tests.AssertEventually(t, func() bool { return checker.OnNewLongestChainCount() == 1 }) ht.Stop(t) assert.Equal(t, int32(1), checker.OnNewLongestChainCount()) diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index 8fb8d08b6f..52434b5049 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -28,6 +28,15 @@ var ( _ = abi.ConvertType ) +type ClientEVMExtraArgsV1 struct { + GasLimit *big.Int +} + +type ClientEVMExtraArgsV2 struct { + GasLimit *big.Int + AllowOutOfOrderExecution bool +} + type InternalAny2EVMRampMessage struct { Header InternalRampMessageHeader Sender []byte @@ -53,8 +62,8 @@ type InternalRampTokenAmount struct { } var MessageHasherMetaData = &bind.MetaData{ - ABI: "[{\"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: "0x608060405234801561001057600080fd5b50610af3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806399df8d051161005057806399df8d05146100b6578063a1e747df14610101578063a91d3aeb1461011457600080fd5b8063902e94a01461006c5780639511afaa14610095575b600080fd5b61007f61007a3660046105d0565b610127565b60405161008c9190610671565b60405180910390f35b6100a86100a336600461074f565b610150565b60405190815260200161008c565b61007f6100c4366004610859565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b61007f61010f366004610894565b610163565b61007f6101223660046108fc565b610195565b60608160405160200161013a919061097d565b6040516020818303038152906040529050919050565b600061015c83836101cd565b9392505050565b60608484848460405160200161017c9493929190610a49565b6040516020818303038152906040529050949350505050565b60608686868686866040516020016101b296959493929190610a86565b60405160208183030381529060405290509695505050505050565b815160208082015160409283015192516000938493610213937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610a49565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761027a9794969395929491939101610a86565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016102b1919061097d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c00160405160208183030381529060405280519060200120905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561037c5761037c61032a565b60405290565b60405160c0810167ffffffffffffffff8111828210171561037c5761037c61032a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103ec576103ec61032a565b604052919050565b600082601f83011261040557600080fd5b813567ffffffffffffffff81111561041f5761041f61032a565b61045060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016103a5565b81815284602083860101111561046557600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261049357600080fd5b8135602067ffffffffffffffff808311156104b0576104b061032a565b8260051b6104bf8382016103a5565b93845285810183019383810190888611156104d957600080fd5b84880192505b858310156105c4578235848111156104f75760008081fd5b88016080818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181131561052d5760008081fd5b610535610359565b87830135878111156105475760008081fd5b6105558d8a838701016103f4565b8252506040808401358881111561056c5760008081fd5b61057a8e8b838801016103f4565b8a84015250606080850135898111156105935760008081fd5b6105a18f8c838901016103f4565b9284019290925293909201359281019290925250825291840191908401906104df565b98975050505050505050565b6000602082840312156105e257600080fd5b813567ffffffffffffffff8111156105f957600080fd5b61060584828501610482565b949350505050565b6000815180845260005b8181101561063357602081850181015186830182015201610617565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061015c602083018461060d565b803567ffffffffffffffff8116811461069c57600080fd5b919050565b600060a082840312156106b357600080fd5b60405160a0810181811067ffffffffffffffff821117156106d6576106d661032a565b604052823581529050806106ec60208401610684565b60208201526106fd60408401610684565b604082015261070e60608401610684565b606082015261071f60808401610684565b60808201525092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461069c57600080fd5b6000806040838503121561076257600080fd5b823567ffffffffffffffff8082111561077a57600080fd5b90840190610140828703121561078f57600080fd5b610797610382565b6107a187846106a1565b815260a0830135828111156107b557600080fd5b6107c1888286016103f4565b60208301525060c0830135828111156107d957600080fd5b6107e5888286016103f4565b6040830152506107f760e0840161072b565b606082015261010083013560808201526101208301358281111561081a57600080fd5b61082688828601610482565b60a0830152509350602085013591508082111561084257600080fd5b5061084f858286016103f4565b9150509250929050565b600080600080600060a0868803121561087157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600080600080608085870312156108aa57600080fd5b843593506108ba60208601610684565b92506108c860408601610684565b9150606085013567ffffffffffffffff8111156108e457600080fd5b6108f0878288016103f4565b91505092959194509250565b60008060008060008060c0878903121561091557600080fd5b86359550602087013567ffffffffffffffff81111561093357600080fd5b61093f89828a016103f4565b95505061094e6040880161072b565b935061095c60608801610684565b92506080870135915061097160a08801610684565b90509295509295509295565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610a3b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151608081518186526109ea8287018261060d565b915050888201518582038a870152610a02828261060d565b9150508782015185820389870152610a1a828261060d565b606093840151969093019590955250948701949250908601906001016109a6565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610a7c608083018461060d565b9695505050505050565b86815260c060208201526000610a9f60c083018861060d565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", + 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", } var MessageHasherABI = MessageHasherMetaData.ABI @@ -193,6 +202,94 @@ func (_MessageHasher *MessageHasherTransactorRaw) Transact(opts *bind.TransactOp return _MessageHasher.Contract.contract.Transact(opts, method, params...) } +func (_MessageHasher *MessageHasherCaller) DecodeEVMExtraArgsV1(opts *bind.CallOpts, gasLimit *big.Int) (ClientEVMExtraArgsV1, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "decodeEVMExtraArgsV1", gasLimit) + + if err != nil { + return *new(ClientEVMExtraArgsV1), err + } + + out0 := *abi.ConvertType(out[0], new(ClientEVMExtraArgsV1)).(*ClientEVMExtraArgsV1) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) DecodeEVMExtraArgsV1(gasLimit *big.Int) (ClientEVMExtraArgsV1, error) { + return _MessageHasher.Contract.DecodeEVMExtraArgsV1(&_MessageHasher.CallOpts, gasLimit) +} + +func (_MessageHasher *MessageHasherCallerSession) DecodeEVMExtraArgsV1(gasLimit *big.Int) (ClientEVMExtraArgsV1, error) { + return _MessageHasher.Contract.DecodeEVMExtraArgsV1(&_MessageHasher.CallOpts, gasLimit) +} + +func (_MessageHasher *MessageHasherCaller) DecodeEVMExtraArgsV2(opts *bind.CallOpts, gasLimit *big.Int, allowOutOfOrderExecution bool) (ClientEVMExtraArgsV2, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "decodeEVMExtraArgsV2", gasLimit, allowOutOfOrderExecution) + + if err != nil { + return *new(ClientEVMExtraArgsV2), err + } + + out0 := *abi.ConvertType(out[0], new(ClientEVMExtraArgsV2)).(*ClientEVMExtraArgsV2) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) DecodeEVMExtraArgsV2(gasLimit *big.Int, allowOutOfOrderExecution bool) (ClientEVMExtraArgsV2, error) { + return _MessageHasher.Contract.DecodeEVMExtraArgsV2(&_MessageHasher.CallOpts, gasLimit, allowOutOfOrderExecution) +} + +func (_MessageHasher *MessageHasherCallerSession) DecodeEVMExtraArgsV2(gasLimit *big.Int, allowOutOfOrderExecution bool) (ClientEVMExtraArgsV2, error) { + return _MessageHasher.Contract.DecodeEVMExtraArgsV2(&_MessageHasher.CallOpts, gasLimit, allowOutOfOrderExecution) +} + +func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV1(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV1) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeEVMExtraArgsV1", extraArgs) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeEVMExtraArgsV1(extraArgs ClientEVMExtraArgsV1) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV1(&_MessageHasher.CallOpts, extraArgs) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeEVMExtraArgsV1(extraArgs ClientEVMExtraArgsV1) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV1(&_MessageHasher.CallOpts, extraArgs) +} + +func (_MessageHasher *MessageHasherCaller) EncodeEVMExtraArgsV2(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV2) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeEVMExtraArgsV2", extraArgs) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeEVMExtraArgsV2(extraArgs ClientEVMExtraArgsV2) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV2(&_MessageHasher.CallOpts, extraArgs) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeEVMExtraArgsV2(extraArgs ClientEVMExtraArgsV2) ([]byte, error) { + return _MessageHasher.Contract.EncodeEVMExtraArgsV2(&_MessageHasher.CallOpts, extraArgs) +} + func (_MessageHasher *MessageHasherCaller) EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) { var out []interface{} err := _MessageHasher.contract.Call(opts, &out, "encodeFinalHashPreimage", leafDomainSeparator, implicitMetadataHash, fixedSizeFieldsHash, dataHash, tokenAmountsHash) @@ -308,6 +405,14 @@ func (_MessageHasher *MessageHasher) Address() common.Address { } type MessageHasherInterface interface { + DecodeEVMExtraArgsV1(opts *bind.CallOpts, gasLimit *big.Int) (ClientEVMExtraArgsV1, error) + + DecodeEVMExtraArgsV2(opts *bind.CallOpts, gasLimit *big.Int, allowOutOfOrderExecution bool) (ClientEVMExtraArgsV2, error) + + EncodeEVMExtraArgsV1(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV1) ([]byte, error) + + EncodeEVMExtraArgsV2(opts *bind.CallOpts, extraArgs ClientEVMExtraArgsV2) ([]byte, error) + EncodeFinalHashPreimage(opts *bind.CallOpts, leafDomainSeparator [32]byte, implicitMetadataHash [32]byte, fixedSizeFieldsHash [32]byte, dataHash [32]byte, tokenAmountsHash [32]byte) ([]byte, error) EncodeFixedSizeFieldsHashPreimage(opts *bind.CallOpts, messageId [32]byte, sender []byte, receiver common.Address, sequenceNumber uint64, gasLimit *big.Int, nonce uint64) ([]byte, 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 c4432d6860..a8a838e6fd 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 @@ 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 c65c226e1e4d38414bd4a1b76fc8aca3cb3dd98df61268424c44564f455d3752 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin 8b929fab79d1caeea4c57e08cc523eb8ab45ec5c08f46da866b82c15ba94d9ad 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 9195ef458fee819595502b5b33263e4646f9526cbac0bd89cc322afe5a77ae19 +message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 1d5146d43e1b99cd2d6f9f06475be19087e4349f7cee0fdbbf134ba65e967c93 mock_arm_contract: ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.abi ../../../contracts/solc/v0.8.24/MockRMN1_0/MockRMN.bin e7a3a6c3eda5fb882e16bcc2b4340f78523acb67907bcdcaf3c8ffc51488688e mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin e0cf17a38b438239fc6294ddca88f86b6c39e4542aefd9815b2d92987191b8bd mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin 33bdad70822e889de7c720ed20085cf9cd3f8eba8b68f26bd6535197749595fe diff --git a/core/scripts/go.mod b/core/scripts/go.mod index d5dd252be7..777e0dce74 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -14,19 +14,19 @@ require ( github.com/gkampitakis/go-snaps v0.5.4 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 - github.com/jmoiron/sqlx v1.3.5 + github.com/jmoiron/sqlx v1.4.0 github.com/joho/godotenv v1.4.0 github.com/jonboulle/clockwork v0.4.0 github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f github.com/montanaflynn/stats v0.7.1 github.com/olekukonko/tablewriter v0.0.5 - github.com/pelletier/go-toml/v2 v2.1.1 + github.com/pelletier/go-toml/v2 v2.2.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.17 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e @@ -38,7 +38,7 @@ require ( github.com/urfave/cli v1.22.14 go.dedis.ch/kyber/v3 v3.1.0 go.uber.org/multierr v1.11.0 - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.34.1 k8s.io/api v0.30.0 k8s.io/apimachinery v0.30.0 k8s.io/client-go v0.30.0 @@ -51,7 +51,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 - filippo.io/edwards25519 v1.0.0 // 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 github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect @@ -79,7 +79,7 @@ require ( github.com/buger/jsonparser v1.1.1 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // 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/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect @@ -182,10 +182,10 @@ require ( github.com/graph-gophers/dataloader v5.0.0+incompatible // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect + 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.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.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 @@ -323,34 +323,33 @@ 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.46.1 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.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.uber.org/ratelimit v0.3.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect - golang.org/x/mod v0.15.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.25.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/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.18.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gonum.org/v1/gonum v0.14.0 // indirect - google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/grpc v1.62.1 // 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 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 479dee69e7..0e72427a72 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -9,23 +9,15 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= 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.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +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= 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= @@ -34,12 +26,9 @@ cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXE 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= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -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.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -62,8 +51,8 @@ cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= 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.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= -filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= @@ -197,8 +186,8 @@ github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiays github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -223,8 +212,6 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= 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= @@ -361,10 +348,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= @@ -485,9 +469,8 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91 github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -525,9 +508,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -535,7 +516,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -565,9 +545,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -582,7 +560,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -590,8 +567,6 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -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-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= @@ -638,16 +613,16 @@ github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLt github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5YbLR0/n2+wBxUpgf3HgfKgTyLI= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 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.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +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/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= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -795,8 +770,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= @@ -897,7 +872,7 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -1004,8 +979,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= @@ -1122,8 +1097,8 @@ github.com/smartcontractkit/chain-selectors v1.0.17 h1:otOlYUnutS8oQBEAi9RLQICqZ github.com/smartcontractkit/chain-selectors v1.0.17/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.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a h1:0HUP3qmHejg7FyFdY+R+8iFg0kNtrvnAxaQ//+fuZfc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= @@ -1291,7 +1266,6 @@ github.com/ydb-platform/ydb-go-sdk/v3 v3.54.2/go.mod h1:fjBLQ2TdQNl4bMjuWl9adoTG github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1329,28 +1303,28 @@ 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.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +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.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= 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.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +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/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.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +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.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= @@ -1405,8 +1379,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/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= @@ -1443,8 +1417,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.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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/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= @@ -1462,7 +1436,6 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1471,15 +1444,8 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1488,7 +1454,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1496,16 +1461,15 @@ 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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +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/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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.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= @@ -1513,13 +1477,12 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1557,15 +1520,9 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1597,8 +1554,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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.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/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= @@ -1606,8 +1563,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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +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/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= @@ -1617,12 +1574,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 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= @@ -1666,26 +1622,16 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +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/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= @@ -1705,13 +1651,8 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.155.0 h1:vBmGhCYs0djJttDNynWo44zosHlPvHmA0XiN2zP2DtA= google.golang.org/api v0.155.0/go.mod h1:GI5qK5f40kCpHfPn6+YzGAByIKWv8ujFnmoWm7Igduk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1720,9 +1661,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1742,29 +1680,18 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/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-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +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/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1777,15 +1704,11 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= +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/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= @@ -1794,13 +1717,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= @@ -1850,7 +1772,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 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= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= diff --git a/core/services/ocr3/plugins/ccipevm/msghasher.go b/core/services/ocr3/plugins/ccipevm/msghasher.go index 13d0410ea3..15483c822e 100644 --- a/core/services/ocr3/plugins/ccipevm/msghasher.go +++ b/core/services/ocr3/plugins/ccipevm/msghasher.go @@ -1,14 +1,15 @@ package ccipevm import ( + "bytes" "context" - "encoding/hex" "fmt" - "strings" + "math/big" 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" @@ -23,25 +24,21 @@ var ( 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: // - "EVM2EVMMultiOnRamp 1.6.0-dev" -type MessageHasherV1 struct { - // TODO: move these to CCIPMsg instead? - destChainSelector cciptypes.ChainSelector - onrampAddress []byte -} +type MessageHasherV1 struct{} -func NewMessageHasherV1( - onrampAddress []byte, - destChainSelector cciptypes.ChainSelector, -) *MessageHasherV1 { - return &MessageHasherV1{ - destChainSelector: destChainSelector, - onrampAddress: onrampAddress, - } +func NewMessageHasherV1() *MessageHasherV1 { + return &MessageHasherV1{} } // Hash implements the MessageHasher interface. @@ -53,79 +50,58 @@ func NewMessageHasherV1( keccak256(any_2_evm_message_hash, header.sourceChainSelector, header.destinationChainSelector, onRamp), keccak256(fixedSizeMessageFields), keccak256(messageData), - keccak256(encodedTokenAmounts), - keccak256(encodedSourceTokenData), + keccak256(encodedRampTokenAmounts), ) */ -func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.CCIPMsg) (cciptypes.Bytes32, error) { - if len(msg.TokenAmounts) != len(msg.SourceTokenData) { - return [32]byte{}, fmt.Errorf("token amounts and source token data must have the same length") +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, + }) } - - // TODO: this is not fully correct, but will be fixed in future PRs. - // CCIPMsg is missing the source pool address and the dest token address. - rampTokenAmounts := make([]message_hasher.InternalRampTokenAmount, len(msg.TokenAmounts)) - for i, ta := range msg.TokenAmounts { - rampTokenAmounts[i] = message_hasher.InternalRampTokenAmount{ - // SourcePoolAddress: , // TODO: fill this in future PRs. - // DestTokenAddress: , // TODO: fill this in future PRs. - ExtraData: msg.SourceTokenData[i], - Amount: ta.Amount, - } - } - encodedRampTokenAmounts, err := h.abiEncode("encodeTokenAmountsHashPreimage", rampTokenAmounts) + encodedRampTokenAmounts, err := abiEncode("encodeTokenAmountsHashPreimage", rampTokenAmounts) if err != nil { return [32]byte{}, fmt.Errorf("abi encode token amounts: %w", err) } - metaDataHashInput, err := h.abiEncode( + metaDataHashInput, err := abiEncode( "encodeMetadataHashPreimage", ANY_2_EVM_MESSAGE_HASH, - uint64(msg.SourceChain), - uint64(h.destChainSelector), - h.onrampAddress, + 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) } - var msgID [32]byte - decoded, err := hex.DecodeString(msg.ID) + // 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 := decodeExtraArgs(msg.ExtraArgs) if err != nil { - return [32]byte{}, fmt.Errorf("decode message ID: %w", err) - } - if len(decoded) != 32 { - return [32]byte{}, fmt.Errorf("message ID must be 32 bytes") + return [32]byte{}, fmt.Errorf("decode extra args: %w", err) } - copy(msgID[:], decoded) - - // NOTE: msg.Sender is not necessarily an EVM address since this is Any2EVM. - // Accordingly, sender is defined as "bytes" in the onchain message definition - // rather than "address". - // However, its not clear how best to translate from Sender being a string representation - // to bytes. For now, we assume that the string is hex encoded, but ideally Sender would - // just be a byte array in the CCIPMsg struct that represents a sender encoded in the - // source chain family encoding scheme. - decodedSender, err := hex.DecodeString( - strings.TrimPrefix(string(msg.Sender), "0x"), - ) - if err != nil { - return [32]byte{}, fmt.Errorf("decode sender '%s': %w", msg.Sender, err) - } - fixedSizeFieldsEncoded, err := h.abiEncode( + + fixedSizeFieldsEncoded, err := abiEncode( "encodeFixedSizeFieldsHashPreimage", - msgID, - decodedSender, - common.HexToAddress(string(msg.Receiver)), - uint64(msg.SeqNum), - msg.ChainFeeLimit.Int, - msg.Nonce, + 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 := h.abiEncode( + packedValues, err := abiEncode( "encodeFinalHashPreimage", leafDomainSeparator, utils.Keccak256Fixed(metaDataHashInput), @@ -140,7 +116,7 @@ func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.CCIPMsg) (ccipty return utils.Keccak256Fixed(packedValues), nil } -func (h *MessageHasherV1) abiEncode(method string, values ...interface{}) ([]byte, error) { +func abiEncode(method string, values ...interface{}) ([]byte, error) { res, err := messageHasherABI.Pack(method, values...) if err != nil { return nil, err @@ -149,5 +125,27 @@ func (h *MessageHasherV1) abiEncode(method string, values ...interface{}) ([]byt return res[4:], nil } +func decodeExtraArgs(extraArgs []byte) (gasLimit *big.Int, err error) { + 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 +} + // Interface compliance check var _ cciptypes.MessageHasher = (*MessageHasherV1)(nil) diff --git a/core/services/ocr3/plugins/ccipevm/msghasher_test.go b/core/services/ocr3/plugins/ccipevm/msghasher_test.go index a16815a0d7..ec856b4e9e 100644 --- a/core/services/ocr3/plugins/ccipevm/msghasher_test.go +++ b/core/services/ocr3/plugins/ccipevm/msghasher_test.go @@ -3,7 +3,6 @@ package ccipevm import ( "context" cryptorand "crypto/rand" - "encoding/hex" "fmt" "math/big" "math/rand" @@ -14,72 +13,77 @@ import ( "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/libocr/offchainreporting2plus/types" - "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" - - "github.com/stretchr/testify/require" ) -func TestMessageHasher_e2e(t *testing.T) { +// 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) - // low budget "fuzz" test. - // TODO: should actually write a real fuzz test. - for i := 0; i < 5; i++ { - testHasher(ctx, t, d) + 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 testHasher(ctx context.Context, t *testing.T, d *testSetupData) { - destChainSelector := rand.Uint64() - onRampAddress := testutils.NewAddress().Bytes() - ccipMsg := createCCIPMsg(t) +func testHasherEVM2EVM(ctx context.Context, t *testing.T, d *testSetupData, evmExtraArgs evmExtraArgs) { + ccipMsg := createEVM2EVMMessage(t, d.contract, evmExtraArgs) - tokenAmounts := make([]message_hasher.InternalRampTokenAmount, 0, len(ccipMsg.TokenAmounts)) - for i := range ccipMsg.TokenAmounts { + var tokenAmounts []message_hasher.InternalRampTokenAmount + for _, rta := range ccipMsg.TokenAmounts { tokenAmounts = append(tokenAmounts, message_hasher.InternalRampTokenAmount{ - // SourcePoolAddress: , // TODO: fill this in future PRs. - // DestTokenAddress: , // TODO: fill this in future PRs. - ExtraData: ccipMsg.SourceTokenData[i], - Amount: ccipMsg.TokenAmounts[i].Amount, + SourcePoolAddress: rta.SourcePoolAddress, + DestTokenAddress: rta.DestTokenAddress, + ExtraData: rta.ExtraData[:], + Amount: rta.Amount.Int, }) } evmMsg := message_hasher.InternalAny2EVMRampMessage{ Header: message_hasher.InternalRampMessageHeader{ - MessageId: mustMessageID(t, ccipMsg.ID), - SourceChainSelector: uint64(ccipMsg.SourceChain), - DestChainSelector: destChainSelector, - SequenceNumber: uint64(ccipMsg.SeqNum), - Nonce: ccipMsg.Nonce, + MessageId: ccipMsg.Header.MessageID, + SourceChainSelector: uint64(ccipMsg.Header.SourceChainSelector), + DestChainSelector: uint64(ccipMsg.Header.DestChainSelector), + SequenceNumber: uint64(ccipMsg.Header.SequenceNumber), + Nonce: ccipMsg.Header.Nonce, }, - Sender: common.HexToAddress(string(ccipMsg.Sender)).Bytes(), - Receiver: common.HexToAddress(string(ccipMsg.Receiver)), - GasLimit: ccipMsg.ChainFeeLimit.Int, + 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, onRampAddress) + expectedHash, err := d.contract.Hash(&bind.CallOpts{Context: ctx}, evmMsg, ccipMsg.Header.OnRamp) require.NoError(t, err) - evmMsgHasher := NewMessageHasherV1(onRampAddress, cciptypes.ChainSelector(destChainSelector)) + evmMsgHasher := NewMessageHasherV1() actualHash, err := evmMsgHasher.Hash(ctx, ccipMsg) require.NoError(t, err) require.Equal(t, fmt.Sprintf("%x", expectedHash), strings.TrimPrefix(actualHash.String(), "0x")) } -// TODO: fix this once messageID is part of CCIPMsg -func createCCIPMsg(t *testing.T) cciptypes.CCIPMsg { - // Setup random msg data +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)) @@ -88,8 +92,24 @@ func createCCIPMsg(t *testing.T) cciptypes.CCIPMsg { sourceChain := rand.Uint64() seqNum := rand.Uint64() - chainFeeLimit := 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) @@ -101,43 +121,41 @@ func createCCIPMsg(t *testing.T) cciptypes.CCIPMsg { sourceTokenDatas = append(sourceTokenDatas, sourceTokenData) } - var tokenAmounts []cciptypes.TokenAmount + var tokenAmounts []cciptypes.RampTokenAmount for i := 0; i < len(sourceTokenDatas); i++ { - tokenAmounts = append(tokenAmounts, cciptypes.TokenAmount{ - // Ignored by the hasher, will be removed in future PR. - // Token: types.Account(utils.RandomAddress().String()), - Amount: big.NewInt(0).SetUint64(rand.Uint64()), + 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.CCIPMsg{ - CCIPMsgBaseDetails: cciptypes.CCIPMsgBaseDetails{ - ID: hex.EncodeToString(messageID[:]), - SourceChain: cciptypes.ChainSelector(sourceChain), - SeqNum: cciptypes.SeqNum(seqNum), + 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), }, - ChainFeeLimit: cciptypes.NewBigInt(big.NewInt(0).SetUint64(chainFeeLimit)), - Nonce: nonce, - Sender: types.Account(utils.RandomAddress().String()), - Receiver: types.Account(utils.RandomAddress().String()), - // TODO: remove this field if not needed, not used by the hasher - // Strict: strict, - // NOTE: not used by the hasher - // FeeToken: types.Account(utils.RandomAddress().String()), - // FeeTokenAmount: cciptypes.NewBigInt(big.NewInt(0).SetUint64(feeTokenAmount)), - Data: messageData, - TokenAmounts: tokenAmounts, - SourceTokenData: sourceTokenDatas, + 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 mustMessageID(t *testing.T, msgIDHex string) [32]byte { - msgID, err := hex.DecodeString(msgIDHex) +func abiEncodedAddress(t *testing.T) []byte { + addr := utils.RandomAddress() + encoded, err := utils.ABIEncode(`[{"type": "address"}]`, addr) require.NoError(t, err) - require.Len(t, msgID, 32) - var msgID32 [32]byte - copy(msgID32[:], msgID) - return msgID32 + return encoded } type testSetupData struct { @@ -169,3 +187,33 @@ func testSetup(t *testing.T) *testSetupData { auth: transactor, } } + +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 := decodeExtraArgs(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 := decodeExtraArgs(encoded) + require.NoError(t, err) + + require.Equal(t, gasLimit, decodedGasLimit) + }) +} 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 0f4045bdf1..a1f0fef069 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.33.0 +// protoc-gen-go v1.34.1 // protoc v4.25.1 // source: mercury.proto diff --git a/go.mod b/go.mod index 77ae271f32..fe9dcbfc7d 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/jackc/pgconn v1.14.3 github.com/jackc/pgtype v1.14.0 github.com/jackc/pgx/v4 v4.18.2 - github.com/jmoiron/sqlx v1.3.5 + github.com/jmoiron/sqlx v1.4.0 github.com/jonboulle/clockwork v0.4.0 github.com/jpillora/backoff v1.0.0 github.com/kylelemons/godebug v1.1.0 @@ -59,7 +59,7 @@ require ( github.com/onsi/gomega v1.30.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pelletier/go-toml v1.9.5 - github.com/pelletier/go-toml/v2 v2.1.1 + github.com/pelletier/go-toml/v2 v2.2.0 github.com/pkg/errors v0.9.1 github.com/pressly/goose/v3 v3.16.0 github.com/prometheus/client_golang v1.17.0 @@ -67,15 +67,15 @@ require ( github.com/prometheus/common v0.45.0 github.com/prometheus/prometheus v0.48.1 github.com/robfig/cron/v3 v3.0.1 - github.com/rogpeppe/go-internal v1.11.0 + github.com/rogpeppe/go-internal v1.12.0 github.com/rs/zerolog v1.32.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/smartcontractkit/chain-selectors v1.0.17 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240702134133-a6d2f429671f - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240708100035-6d7cad39cc74 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 @@ -100,21 +100,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.24.0 + go.opentelemetry.io/otel v1.27.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.22.0 + golang.org/x/crypto v0.24.0 golang.org/x/exp v0.0.0-20240213143201-ec583247a57a - golang.org/x/mod v0.15.0 - golang.org/x/net v0.24.0 - golang.org/x/sync v0.6.0 - golang.org/x/term v0.19.0 - golang.org/x/text v0.14.0 + golang.org/x/mod v0.17.0 + golang.org/x/net v0.25.0 + golang.org/x/sync v0.7.0 + golang.org/x/term v0.21.0 + golang.org/x/text v0.16.0 golang.org/x/time v0.5.0 - golang.org/x/tools v0.18.0 + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d gonum.org/v1/gonum v0.14.0 - google.golang.org/grpc v1.62.1 - google.golang.org/protobuf v1.33.0 + google.golang.org/grpc v1.64.0 + google.golang.org/protobuf v1.34.1 gopkg.in/guregu/null.v4 v4.0.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 k8s.io/utils v0.0.0-20230711102312-30195339c3c7 @@ -137,7 +137,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 - filippo.io/edwards25519 v1.0.0 // 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 github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect @@ -156,7 +156,7 @@ require ( github.com/blendle/zapdriver v1.3.1 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // 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/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect @@ -228,10 +228,10 @@ require ( 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 - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect + 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.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.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 @@ -325,19 +325,19 @@ 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.46.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.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.uber.org/ratelimit v0.3.0 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/sys v0.19.0 // indirect + golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // 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 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 c339602e34..f5d8a8b269 100644 --- a/go.sum +++ b/go.sum @@ -9,21 +9,14 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= 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.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -34,12 +27,9 @@ cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXE 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= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -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.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= @@ -62,8 +52,8 @@ cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= 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.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= -filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= @@ -183,8 +173,8 @@ github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiays github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -209,8 +199,6 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= 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= @@ -342,10 +330,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8ntaA= github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= @@ -452,9 +437,8 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91 github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -493,9 +477,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -503,7 +485,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -531,9 +512,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -548,7 +527,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -556,8 +534,6 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -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-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= @@ -605,16 +581,16 @@ github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLt github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5YbLR0/n2+wBxUpgf3HgfKgTyLI= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 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.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +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/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= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -765,8 +741,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= @@ -863,7 +839,7 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -964,8 +940,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= @@ -1032,8 +1008,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1083,10 +1059,10 @@ github.com/smartcontractkit/chain-selectors v1.0.17 h1:otOlYUnutS8oQBEAi9RLQICqZ github.com/smartcontractkit/chain-selectors v1.0.17/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-20240702134133-a6d2f429671f h1:ohB9VgjJ+cvfOSzVEykZqpB/wGlzhzy3IjtdG3ZiO9E= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240702134133-a6d2f429671f/go.mod h1:vy2vEF1K61khqGcbOCrHBKFPvSQW0O1eg19Sv74Xq/4= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240708100035-6d7cad39cc74 h1:dsRsqoCRF+SrIvARgJXs6RQcJ6oGfh3XigIfrrEWO2E= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240708100035-6d7cad39cc74/go.mod h1:gyODeD1uMobe5VWRwVRiEXzL9wUzFTI80VvyCNLqWcw= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a h1:0HUP3qmHejg7FyFdY+R+8iFg0kNtrvnAxaQ//+fuZfc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= @@ -1250,7 +1226,6 @@ github.com/ydb-platform/ydb-go-sdk/v3 v3.54.2/go.mod h1:fjBLQ2TdQNl4bMjuWl9adoTG github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1288,28 +1263,28 @@ 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.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +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.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= 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.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +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/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.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +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.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= @@ -1364,8 +1339,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.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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/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= @@ -1402,8 +1377,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.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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/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= @@ -1420,7 +1395,6 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1429,15 +1403,8 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1445,7 +1412,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1454,16 +1420,15 @@ 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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +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/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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.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= @@ -1471,13 +1436,12 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1515,14 +1479,8 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1554,8 +1512,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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.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/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= @@ -1564,8 +1522,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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +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/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= @@ -1579,8 +1537,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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 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= @@ -1624,26 +1582,16 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +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/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= @@ -1663,13 +1611,8 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.155.0 h1:vBmGhCYs0djJttDNynWo44zosHlPvHmA0XiN2zP2DtA= google.golang.org/api v0.155.0/go.mod h1:GI5qK5f40kCpHfPn6+YzGAByIKWv8ujFnmoWm7Igduk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1678,9 +1621,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1700,29 +1640,18 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/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-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +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/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1735,15 +1664,11 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= +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/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= @@ -1752,13 +1677,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= @@ -1806,7 +1730,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 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= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index e73850580a..c86f91f2d8 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -18,7 +18,7 @@ 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/jmoiron/sqlx v1.3.5 + github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.10.9 github.com/manifoldco/promptui v0.9.0 github.com/montanaflynn/stats v0.7.1 @@ -33,7 +33,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chain-selectors v1.0.17 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 @@ -52,10 +52,10 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.22.0 + golang.org/x/crypto v0.24.0 golang.org/x/exp v0.0.0-20240213143201-ec583247a57a - golang.org/x/sync v0.6.0 - golang.org/x/text v0.14.0 + golang.org/x/sync v0.7.0 + golang.org/x/text v0.16.0 gopkg.in/guregu/null.v4 v4.0.0 k8s.io/apimachinery v0.28.2 ) @@ -76,7 +76,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 - filippo.io/edwards25519 v1.0.0 // 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 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect @@ -118,7 +118,7 @@ require ( github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // 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/chai2010/gettext-go v1.0.2 // indirect @@ -252,10 +252,10 @@ require ( 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 - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect + 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.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.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 @@ -373,7 +373,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday v1.6.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -437,35 +437,34 @@ 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.46.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.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.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect go.uber.org/goleak v1.3.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/mod v0.15.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.19.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.18.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect gonum.org/v1/gonum v0.14.0 // indirect - google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/grpc v1.62.1 // indirect - google.golang.org/protobuf v1.33.0 // 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/protobuf v1.34.1 // 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 1a563cb1e5..5bb7474bd1 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -22,10 +22,9 @@ 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.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +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= 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= @@ -64,8 +63,8 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/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.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= -filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= @@ -245,8 +244,8 @@ github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsn github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -286,8 +285,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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +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/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= @@ -438,7 +437,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= @@ -602,9 +600,8 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -821,16 +818,16 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:Fecb github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5YbLR0/n2+wBxUpgf3HgfKgTyLI= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 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.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +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-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= @@ -1007,8 +1004,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= @@ -1127,7 +1124,7 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -1359,8 +1356,8 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1426,8 +1423,8 @@ github.com/smartcontractkit/chain-selectors v1.0.17 h1:otOlYUnutS8oQBEAi9RLQICqZ github.com/smartcontractkit/chain-selectors v1.0.17/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.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a h1:0HUP3qmHejg7FyFdY+R+8iFg0kNtrvnAxaQ//+fuZfc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= @@ -1665,30 +1662,30 @@ go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUp go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= 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.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +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.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +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 v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= +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/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.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +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/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.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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 v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g= go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1752,8 +1749,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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/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= @@ -1790,8 +1787,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.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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/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= @@ -1837,7 +1834,6 @@ golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1850,17 +1846,16 @@ 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.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +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/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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.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= @@ -1875,8 +1870,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1970,8 +1965,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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.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/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= @@ -1982,8 +1977,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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +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/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= @@ -1993,13 +1988,12 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 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= @@ -2067,8 +2061,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.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +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/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= @@ -2107,8 +2101,6 @@ google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -2143,16 +2135,15 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/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-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +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/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= @@ -2172,11 +2163,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= +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/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= @@ -2190,8 +2179,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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/load/go.mod b/integration-tests/load/go.mod index c80766d23a..86f0dccaa8 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.32.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a github.com/smartcontractkit/chainlink-testing-framework v1.31.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 @@ -40,7 +40,7 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect dario.cat/mergo v1.0.0 // indirect - filippo.io/edwards25519 v1.0.0 // 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 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect @@ -86,7 +86,7 @@ require ( github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // 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/chai2010/gettext-go v1.0.2 // indirect @@ -225,10 +225,10 @@ require ( 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 - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect + 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.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.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 @@ -270,7 +270,7 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/jmoiron/sqlx v1.3.5 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect github.com/jonboulle/clockwork v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect @@ -351,7 +351,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday v1.6.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -425,15 +425,15 @@ 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.46.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.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.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/goleak v1.3.0 // indirect @@ -441,25 +441,24 @@ require ( go.uber.org/zap v1.26.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect - golang.org/x/mod v0.15.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.25.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/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.18.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect gonum.org/v1/gonum v0.14.0 // indirect - google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/grpc v1.62.1 // indirect - google.golang.org/protobuf v1.33.0 // 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/protobuf v1.34.1 // 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/integration-tests/load/go.sum b/integration-tests/load/go.sum index 8363c44371..2b5daf2156 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -22,10 +22,9 @@ 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.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +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= 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= @@ -64,8 +63,8 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/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.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= -filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= @@ -249,8 +248,8 @@ github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsn github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -280,8 +279,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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +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/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= @@ -432,7 +431,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= @@ -596,9 +594,8 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -819,16 +816,16 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:Fecb github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5YbLR0/n2+wBxUpgf3HgfKgTyLI= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 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.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +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-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= @@ -1003,8 +1000,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= @@ -1121,7 +1118,7 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -1349,8 +1346,8 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1416,8 +1413,8 @@ github.com/smartcontractkit/chain-selectors v1.0.17 h1:otOlYUnutS8oQBEAi9RLQICqZ github.com/smartcontractkit/chain-selectors v1.0.17/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.1.7-0.20240702120320-563bf07487fe h1:lYyWmjheglMu0y3JmfSqs9Dm4tZO34RmbUTOtQ4CadE= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240702120320-563bf07487fe/go.mod h1:EWvSuqIJUYXZLEHewC7WCaPylM2jyjF3Q36BZPS4MoI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a h1:0HUP3qmHejg7FyFdY+R+8iFg0kNtrvnAxaQ//+fuZfc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240708180634-24440372521a/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141 h1:TMOoYaeSDkkI3jkCH7lKHOZaLkeDuxFTNC+XblD6M0M= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240621143432-85370a54b141/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240702144807-761f63e7b527 h1:Vs6myS+bpPwb8chUY7XxveJyhvejknhOmhDTddgsK5I= @@ -1653,30 +1650,30 @@ go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUp go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= 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.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +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.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +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 v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= +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/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.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +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/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.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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 v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g= go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1740,8 +1737,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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/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= @@ -1778,8 +1775,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.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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/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= @@ -1825,7 +1822,6 @@ golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1838,17 +1834,16 @@ 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.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +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/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= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= +golang.org/x/oauth2 v0.20.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= @@ -1863,8 +1858,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1956,8 +1951,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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.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/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= @@ -1968,8 +1963,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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +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/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,13 +1974,12 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 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= @@ -2053,8 +2047,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.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +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/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= @@ -2093,8 +2087,6 @@ google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -2129,16 +2121,15 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/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-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +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/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= @@ -2158,11 +2149,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= +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/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= @@ -2176,8 +2165,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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= From 5f54e6de68ce1ff7a620ead8c2dac0118f4cc6c4 Mon Sep 17 00:00:00 2001 From: Makram Date: Tue, 9 Jul 2024 19:30:18 +0300 Subject: [PATCH 58/61] CODEOWNERS: update go.mod/go.sum owners (#1172) ## Motivation Reduce review turnaround times. ## Solution Update the go.mod/go.sum codeowners to include @smartcontractkit/ccip --- .github/CODEOWNERS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 96f5c5b70e..f3d79516f3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -139,6 +139,10 @@ flake.lock @smartcontractkit/prodsec-public # CCIP override /core/ @smartcontractkit/ccip /contracts/ @smartcontractkit/ccip-onchain @makramkd @elatoskinas @RayXpub +go.mod @smartcontractkit/ccip @smartcontractkit/prodsec-public @smartcontractkit/releng @smartcontractkit/foundations +go.sum @smartcontractkit/ccip @smartcontractkit/prodsec-public @smartcontractkit/releng @smartcontractkit/foundations +integration-tests/go.mod @smartcontractkit/ccip @smartcontractkit/prodsec-public +integration-tests/go.sum @smartcontractkit/ccip @smartcontractkit/prodsec-public # leave snapshots & changeset as ownerless /contracts/gas-snapshots/ From 93ce593984970c8be270b14b5496ecc5735253ab Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:13:30 -0700 Subject: [PATCH 59/61] CCIP-2694 : lane specific load Frequency (#1149) ## Motivation The load frequency is set as a global frequency for all lanes under test. We need to specify destination specific load frequency so that frequency for slow-destination network lanes can be set differently than frequency of fast-destination network lanes. ## Solution --- .../ccip-tests/load/ccip_loadgen.go | 6 +- integration-tests/ccip-tests/load/helper.go | 59 +++++++++---- .../ccip-tests/testconfig/README.md | 15 +++- .../ccip-tests/testconfig/ccip.go | 84 ++++++++++--------- .../ccip1.4-stress-2024-06-27/baseline.toml | 3 +- .../ccip1.4-stress-2024-06-27/tier-a.toml | 26 ++++-- .../ccip-tests/testsetups/ccip.go | 34 +++++++- .../ccip-tests/testsetups/test_env.go | 17 +++- 8 files changed, 170 insertions(+), 74 deletions(-) diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index ab74dd4509..e02f118095 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -248,10 +248,7 @@ func (c *CCIPE2ELoad) Call(_ *wasp.Generator) *wasp.Response { // if the token address is 0x0 it will use Native as fee token and the fee amount should be mentioned in bind.TransactOpts's value fee, err := sourceCCIP.Common.Router.GetFee(destChainSelector, msg) if err != nil { - res.Error = fmt.Sprintf("reqNo %d err %s - while getting fee from router - msg Data %x FeeToken %s TokenAmounts %+v ExtraArgs %x Receiver %x", - msgSerialNo, err.Error(), - msg.Data, msg.FeeToken, msg.TokenAmounts, msg.ExtraArgs, msg.Receiver) - + res.Error = fmt.Sprintf("reqNo %d err %s - while getting fee from router", msgSerialNo, err.Error()) res.Failed = true return res } @@ -271,7 +268,6 @@ func (c *CCIPE2ELoad) Call(_ *wasp.Generator) *wasp.Response { } txConfirmationTime := time.Now().UTC() - // wait for the tx to be mined, timeout is set to 10 minutes lggr.Info().Str("tx", sendTx.Hash().Hex()).Msg("waiting for tx to be mined") lggr = lggr.With().Str("Msg Tx", sendTx.Hash().String()).Logger() diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go index 64c43bc161..9522a6c346 100644 --- a/integration-tests/ccip-tests/load/helper.go +++ b/integration-tests/ccip-tests/load/helper.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "math/big" + "strings" "sync" "testing" "time" @@ -16,6 +17,8 @@ import ( "go.uber.org/atomic" "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" @@ -32,11 +35,30 @@ type ChaosConfig struct { WaitBetweenChaos time.Duration } +// WaspSchedule calculates the load schedule based on the provided request per unit time and duration +// if multiple step durations are provided, it will calculate the schedule based on the step duration and +// corresponding request per unit time by matching the index of the request per unit time and step duration slice +func WaspSchedule(rps []int64, duration *config.Duration, steps []*config.Duration) []*wasp.Segment { + var segments []*wasp.Segment + var segmentDuration time.Duration + + if len(rps) > 1 { + for i, req := range rps { + duration := steps[i].Duration() + segmentDuration += duration + segments = append(segments, wasp.Plain(req, duration)...) + } + totalDuration := duration.Duration() + repeatTimes := totalDuration.Seconds() / segmentDuration.Seconds() + return wasp.CombineAndRepeat(int(math.Round(repeatTimes)), segments) + } + return wasp.Plain(rps[0], duration.Duration()) +} + type LoadArgs struct { t *testing.T Ctx context.Context lggr *zerolog.Logger - schedules []*wasp.Segment RunnerWg *errgroup.Group // to wait on individual load generators run LoadStarterWg *sync.WaitGroup // waits for all the runners to start TestCfg *testsetups.CCIPTestConfig @@ -82,23 +104,27 @@ func (l *LoadArgs) Setup() { l.SetReportParams() } -func (l *LoadArgs) setSchedule() { - var segments []*wasp.Segment - var segmentDuration time.Duration +func (l *LoadArgs) scheduleForDest(destNetworkName string) []*wasp.Segment { require.Greater(l.t, len(l.TestCfg.TestGroupInput.LoadProfile.RequestPerUnitTime), 0, "RequestPerUnitTime must be set") - - if len(l.TestCfg.TestGroupInput.LoadProfile.RequestPerUnitTime) > 1 { - for i, req := range l.TestCfg.TestGroupInput.LoadProfile.RequestPerUnitTime { - duration := l.TestCfg.TestGroupInput.LoadProfile.StepDuration[i].Duration() - segmentDuration += duration - segments = append(segments, wasp.Plain(req, duration)...) + // try to locate if there is a frequency provided for the destination network + // to locate the frequency, we check if the destination network name contains the network name in the frequency map + // if found, use that frequency for the destination network + // 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) { + return WaspSchedule( + freq.RequestPerUnitTime, + l.TestCfg.TestGroupInput.LoadProfile.TestDuration, + freq.StepDuration) + } } - totalDuration := l.TestCfg.TestGroupInput.LoadProfile.TestDuration.Duration() - repeatTimes := totalDuration.Seconds() / segmentDuration.Seconds() - l.schedules = wasp.CombineAndRepeat(int(math.Round(repeatTimes)), segments) - } else { - l.schedules = wasp.Plain(l.TestCfg.TestGroupInput.LoadProfile.RequestPerUnitTime[0], l.TestCfg.TestGroupInput.LoadProfile.TestDuration.Duration()) } + + return WaspSchedule( + l.TestCfg.TestGroupInput.LoadProfile.RequestPerUnitTime, + l.TestCfg.TestGroupInput.LoadProfile.TestDuration, + l.TestCfg.TestGroupInput.LoadProfile.StepDuration) } func (l *LoadArgs) SanityCheck() { @@ -233,7 +259,6 @@ func (l *LoadArgs) ValidateCurseFollowedByUncurse() { } func (l *LoadArgs) TriggerLoadByLane() { - l.setSchedule() l.TestSetupArgs.Reporter.SetDuration(l.TestCfg.TestGroupInput.LoadProfile.TestDuration.Duration()) // start load for a lane @@ -269,7 +294,7 @@ func (l *LoadArgs) TriggerLoadByLane() { waspCfg := &wasp.Config{ T: l.TestCfg.Test, GenName: fmt.Sprintf("lane %s-> %s", lane.SourceNetworkName, lane.DestNetworkName), - Schedule: l.schedules, + Schedule: l.scheduleForDest(lane.DestNetworkName), LoadType: wasp.RPS, RateLimitUnitDuration: l.TestCfg.TestGroupInput.LoadProfile.TimeUnit.Duration(), CallResultBufLen: 10, // we keep the last 10 call results for each generator, as the detailed report is generated at the end of the test diff --git a/integration-tests/ccip-tests/testconfig/README.md b/integration-tests/ccip-tests/testconfig/README.md index a402c218d0..3f069934c4 100644 --- a/integration-tests/ccip-tests/testconfig/README.md +++ b/integration-tests/ccip-tests/testconfig/README.md @@ -528,7 +528,12 @@ 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 select the first 2 lanes between all possible pairs `SIMULATED_1`, `SIMULATED_2`, and `SIMULATED_3` for the test run. +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. +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'. @@ -595,14 +600,16 @@ This is only valid if the tests are run on remote runners in k8s. If set to true ### CCIP.Groups.[testgroup].LoadProfile 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. +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. +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. +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. diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index 1af5c5baee..60d7055cb3 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -204,19 +204,26 @@ func (m *MsgProfile) Validate() error { return nil } +type LoadFrequency struct { + RequestPerUnitTime []int64 `toml:",omitempty"` + TimeUnit *config.Duration `toml:",omitempty"` + StepDuration []*config.Duration `toml:",omitempty"` +} + type LoadProfile struct { - MsgProfile *MsgProfile `toml:",omitempty"` - RequestPerUnitTime []int64 `toml:",omitempty"` - TimeUnit *config.Duration `toml:",omitempty"` - StepDuration []*config.Duration `toml:",omitempty"` - TestDuration *config.Duration `toml:",omitempty"` - NetworkChaosDelay *config.Duration `toml:",omitempty"` - WaitBetweenChaosDuringLoad *config.Duration `toml:",omitempty"` - SkipRequestIfAnotherRequestTriggeredWithin *config.Duration `toml:",omitempty"` - OptimizeSpace *bool `toml:",omitempty"` - FailOnFirstErrorInLoad *bool `toml:",omitempty"` - SendMaxDataInEveryMsgCount *int64 `toml:",omitempty"` - TestRunName string `toml:",omitempty"` + MsgProfile *MsgProfile `toml:",omitempty"` + FrequencyByDestination map[string]*LoadFrequency `toml:",omitempty"` + RequestPerUnitTime []int64 `toml:",omitempty"` + TimeUnit *config.Duration `toml:",omitempty"` + StepDuration []*config.Duration `toml:",omitempty"` + TestDuration *config.Duration `toml:",omitempty"` + NetworkChaosDelay *config.Duration `toml:",omitempty"` + WaitBetweenChaosDuringLoad *config.Duration `toml:",omitempty"` + SkipRequestIfAnotherRequestTriggeredWithin *config.Duration `toml:",omitempty"` + OptimizeSpace *bool `toml:",omitempty"` + FailOnFirstErrorInLoad *bool `toml:",omitempty"` + SendMaxDataInEveryMsgCount *int64 `toml:",omitempty"` + TestRunName string `toml:",omitempty"` } func (l *LoadProfile) Validate() error { @@ -246,32 +253,33 @@ func (l *LoadProfile) SetTestRunName(name string) { // CCIPTestGroupConfig defines configuration input to change how a particular CCIP test group should run type CCIPTestGroupConfig struct { - Type string `toml:",omitempty"` - KeepEnvAlive *bool `toml:",omitempty"` - BiDirectionalLane *bool `toml:",omitempty"` - CommitAndExecuteOnSameDON *bool `toml:",omitempty"` - NoOfCommitNodes int `toml:",omitempty"` - MsgDetails *MsgDetails `toml:",omitempty"` - TokenConfig *TokenConfig `toml:",omitempty"` - MulticallInOneTx *bool `toml:",omitempty"` - NoOfSendsInMulticall int `toml:",omitempty"` - PhaseTimeout *config.Duration `toml:",omitempty"` - LocalCluster *bool `toml:",omitempty"` - ExistingDeployment *bool `toml:",omitempty"` - ReuseContracts *bool `toml:",omitempty"` - NodeFunding float64 `toml:",omitempty"` - NetworkPairs []string `toml:",omitempty"` - NoOfNetworks int `toml:",omitempty"` - NoOfRoutersPerPair int `toml:",omitempty"` - MaxNoOfLanes int `toml:",omitempty"` - ChaosDuration *config.Duration `toml:",omitempty"` - USDCMockDeployment *bool `toml:",omitempty"` - CommitOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` - ExecOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` - OffRampConfig *OffRampConfig `toml:",omitempty"` - CommitInflightExpiry *config.Duration `toml:",omitempty"` - StoreLaneConfig *bool `toml:",omitempty"` - LoadProfile *LoadProfile `toml:",omitempty"` + Type string `toml:",omitempty"` + KeepEnvAlive *bool `toml:",omitempty"` + BiDirectionalLane *bool `toml:",omitempty"` + CommitAndExecuteOnSameDON *bool `toml:",omitempty"` + NoOfCommitNodes int `toml:",omitempty"` + MsgDetails *MsgDetails `toml:",omitempty"` + TokenConfig *TokenConfig `toml:",omitempty"` + MulticallInOneTx *bool `toml:",omitempty"` + NoOfSendsInMulticall int `toml:",omitempty"` + PhaseTimeout *config.Duration `toml:",omitempty"` + LocalCluster *bool `toml:",omitempty"` + ExistingDeployment *bool `toml:",omitempty"` + ReuseContracts *bool `toml:",omitempty"` + NodeFunding float64 `toml:",omitempty"` + NetworkPairs []string `toml:",omitempty"` + DenselyConnectedNetworkChainIds []string `toml:",omitempty"` + NoOfNetworks int `toml:",omitempty"` + NoOfRoutersPerPair int `toml:",omitempty"` + MaxNoOfLanes int `toml:",omitempty"` + ChaosDuration *config.Duration `toml:",omitempty"` + USDCMockDeployment *bool `toml:",omitempty"` + CommitOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` + ExecOCRParams *contracts.OffChainAggregatorV2Config `toml:",omitempty"` + OffRampConfig *OffRampConfig `toml:",omitempty"` + CommitInflightExpiry *config.Duration `toml:",omitempty"` + StoreLaneConfig *bool `toml:",omitempty"` + LoadProfile *LoadProfile `toml:",omitempty"` } func (c *CCIPTestGroupConfig) Validate() error { diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/baseline.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/baseline.toml index 9bcdbff61d..ef7fbadee2 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/baseline.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/baseline.toml @@ -5,7 +5,7 @@ ## throughput 1msg / 5s ## 20% Token, 60% DataWithToken, 15% Regular size msgs, 5% Large msgs ## -## make test_load_ccip testimage=amazonaws.com/chainlink-ccip-tests:ccip-develop \ +## make test_load_ccip testimage=.dkr.ecr..amazonaws.com/chainlink-ccip-tests:ccip-develop \ ## testname=TestLoadCCIPStableRequestTriggeringWithNetworkChaos \ ## override_toml=./testconfig/tomls/baseline.toml \ ## secret_toml=./testconfig/tomls/secrets.toml @@ -58,6 +58,7 @@ evm_finality_depth = 200 [CCIP.Env.Network.AnvilConfigs.PRIVATE-CHAIN-1] block_time = 1 + # [CCIP.Env.Network.AnvilConfigs.PRIVATE-CHAIN-2] block_time = 1 diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/tier-a.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/tier-a.toml index b7595906e6..e3ece56203 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/tier-a.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress-2024-06-27/tier-a.toml @@ -5,9 +5,9 @@ ## throughput 1msg / 5s ## 20% Token, 60% DataWithToken, 15% Regular size msgs, 5% Large msgs ## -## make test_load_ccip testimage=795953128386.dkr.ecr.us-west-2.amazonaws.com/chainlink-ccip-tests:ccip-develop \ +## make test_load_ccip testimage=.dkr.ecr..amazonaws.com/chainlink-ccip-tests:ccip-develop \ ## testname=TestLoadCCIPStableRequestTriggeringWithNetworkChaos \ -## override_toml=./testconfig/tomls/baseline.toml \ +## override_toml=./testconfig/tomls/ccip1.4-stress-2024-06-27/tier-a.toml \ ## secret_toml=./testconfig/tomls/secrets.toml [CCIP] @@ -89,7 +89,8 @@ evm_default_gas_limit = 6000000 evm_finality_depth = 1 [CCIP.Env.Network.AnvilConfigs.PRIVATE-CHAIN-1] -block_time = 1 +block_time = 2 + # [CCIP.Env.Network.AnvilConfigs.SLOW-CHAIN-1] block_time = 12 @@ -172,6 +173,7 @@ DeltaReconcile = '5s' [CCIP.Groups] [CCIP.Groups.load] +DenselyConnectedNetworkChainIds = ['90000001', '90000002', '1337'] KeepEnvAlive = true NoOfCommitNodes = 16 PhaseTimeout = '40m' @@ -187,15 +189,27 @@ BatchGasLimit = 11000000 TimeoutForPriceUpdate = '15m' NoOfTokensPerChain = 60 NoOfTokensWithDynamicPrice = 15 -DynamicPriceUpdateInterval ='15s' +DynamicPriceUpdateInterval ='5m' CCIPOwnerTokens = true [CCIP.Groups.load.LoadProfile] TestDuration = '4h' -TimeUnit = '5s' -RequestPerUnitTime = [1] OptimizeSpace = true NetworkChaosDelay = '100ms' +TimeUnit = '5s' +RequestPerUnitTime = [1] + +[CCIP.Groups.load.LoadProfile.LoadFrequency.slow-chain-1] +TimeUnit = '10s' +RequestPerUnitTime = [1] + +[CCIP.Groups.load.LoadProfile.LoadFrequency.slow-chain-2] +TimeUnit = '10s' +RequestPerUnitTime = [1] + +[CCIP.Groups.load.LoadProfile.LoadFrequency.slow-chain-3] +TimeUnit = '10s' +RequestPerUnitTime = [1] # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index 68ef532ea2..27980517d8 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -4,8 +4,10 @@ import ( "context" "fmt" "math/big" + "math/rand" "os" "regexp" + "strconv" "strings" "sync" "testing" @@ -287,7 +289,37 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { // if the number of lanes is lesser than the number of network pairs, choose first c.TestGroupInput.MaxNoOfLanes pairs if c.TestGroupInput.MaxNoOfLanes > 0 && c.TestGroupInput.MaxNoOfLanes < len(c.NetworkPairs) { - c.NetworkPairs = c.NetworkPairs[:c.TestGroupInput.MaxNoOfLanes] + var newNetworkPairs []NetworkPair + denselyConnectedNetworks := make(map[string]struct{}) + // if densely connected networks are provided, choose all the network pairs containing the networks mentioned in the list for DenselyConnectedNetworkChainIds + if c.TestGroupInput.DenselyConnectedNetworkChainIds != nil && len(c.TestGroupInput.DenselyConnectedNetworkChainIds) > 0 { + for _, n := range c.TestGroupInput.DenselyConnectedNetworkChainIds { + denselyConnectedNetworks[n] = struct{}{} + } + for _, pair := range c.NetworkPairs { + if _, exists := denselyConnectedNetworks[strconv.FormatInt(pair.NetworkA.ChainID, 10)]; exists { + newNetworkPairs = append(newNetworkPairs, pair) + } + } + } + // shuffle the network pairs, we want to randomly distribute the network pairs among all available networks + rand.Shuffle(len(c.NetworkPairs), func(i, j int) { + c.NetworkPairs[i], c.NetworkPairs[j] = c.NetworkPairs[j], c.NetworkPairs[i] + }) + // now add the remaining network pairs by skipping the already covered networks + // and adding the remaining pair from the shuffled list + i := len(newNetworkPairs) + j := 0 + for i < c.TestGroupInput.MaxNoOfLanes { + pair := c.NetworkPairs[j] + // if the network is already covered, skip it + if _, exists := denselyConnectedNetworks[strconv.FormatInt(pair.NetworkA.ChainID, 10)]; !exists { + newNetworkPairs = append(newNetworkPairs, pair) + i++ + } + j++ + } + c.NetworkPairs = newNetworkPairs } for _, n := range c.NetworkPairs { diff --git a/integration-tests/ccip-tests/testsetups/test_env.go b/integration-tests/ccip-tests/testsetups/test_env.go index bea0dbfa32..87ca1c8c9e 100644 --- a/integration-tests/ccip-tests/testsetups/test_env.go +++ b/integration-tests/ccip-tests/testsetups/test_env.go @@ -476,11 +476,22 @@ func DeployEnvironments( // if anvilconfig is specified for a network addhelm for anvil if anvilConfig, exists := testInputs.EnvInput.Network.AnvilConfigs[strings.ToUpper(network.Name)]; exists { charts = append(charts, foundry.ChartName) + if anvilConfig.BaseFee == nil { + anvilConfig.BaseFee = pointer.ToInt64(1000000) + } + if anvilConfig.BlockGaslimit == nil { + anvilConfig.BlockGaslimit = pointer.ToInt64(100000000) + } testEnvironment. - AddHelm(foundry.New(&foundry.Props{ + AddHelm(foundry.NewVersioned("0.1.9", &foundry.Props{ NetworkName: network.Name, Values: map[string]interface{}{ "fullnameOverride": actions.NetworkName(network.Name), + "image": map[string]interface{}{ + "repository": "ghcr.io/foundry-rs/foundry", + "tag": "nightly-5ac78a9cd4b94dc53d1fe5e0f42372b28b5a7559", + // "tag": "nightly-ea2eff95b5c17edd3ffbdfc6daab5ce5cc80afc0", + }, "anvil": map[string]interface{}{ "chainId": fmt.Sprintf("%d", network.ChainID), "blockTime": anvilConfig.BlockTime, @@ -491,8 +502,10 @@ func DeployEnvironments( "forkComputeUnitsPerSecond": anvilConfig.ComputePerSecond, "forkNoRateLimit": anvilConfig.RateLimitDisabled, "blocksToKeepInMemory": anvilConfig.BlocksToKeepInMem, + "blockGasLimit": fmt.Sprintf("%d", pointer.GetInt64(anvilConfig.BlockGaslimit)), + "baseFee": fmt.Sprintf("%d", pointer.GetInt64(anvilConfig.BaseFee)), }, - "resources": testInputs.GethResourceProfile, + "resources": GethResourceProfile, }, })) selectedNetworks[i].Simulated = true From a8b921c553a365e5ba1102e15df1c6d94256d62b Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 9 Jul 2024 17:22:47 -0400 Subject: [PATCH 60/61] using provider based commitStoreReader for exec (#1150) ## Motivation Follow on to #1080, using a provider based commitStoreReader in the exec plugin --------- Co-authored-by: ilija42 <57732589+ilija42@users.noreply.github.com> Co-authored-by: Aaron Lu <50029043+aalu1418@users.noreply.github.com> --- core/services/ocr2/delegate.go | 12 +----------- .../plugins/ccip/ccipcommit/initializers.go | 5 ++++- .../plugins/ccip/ccipexec/initializers.go | 17 +++++++---------- core/services/relay/evm/evm.go | 2 ++ core/services/relay/evm/exec_provider.go | 19 +++++++++++++------ 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index eca2cdc31c..f080356730 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -1976,10 +1976,6 @@ func (d *Delegate) newServicesCCIPExecution(ctx context.Context, lggr logger.Sug if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: string(spec.PluginType)} } - dstChain, err := d.legacyChains.Get(dstRid.ChainID) - if err != nil { - return nil, fmt.Errorf("ccip services; failed to get chain %s: %w", dstRid.ChainID, err) - } logError := func(msg string) { lggr.ErrorIf(d.jobORM.RecordError(context.Background(), jb.ID, msg), "unable to record error") @@ -2008,12 +2004,6 @@ func (d *Delegate) newServicesCCIPExecution(ctx context.Context, lggr logger.Sug return nil, err } - srcChainIDstr := strconv.FormatUint(srcChainID, 10) - srcChain, err := d.legacyChains.Get(srcChainIDstr) - if err != nil { - return nil, fmt.Errorf("open source chain: %w", err) - } - oracleArgsNoPlugin2 := libocr2.OCR2OracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -2033,7 +2023,7 @@ func (d *Delegate) newServicesCCIPExecution(ctx context.Context, lggr logger.Sug MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": jb.Name.ValueOrZero()}, prometheus.DefaultRegisterer), } - return ccipexec.NewExecServices(ctx, lggr, jb, srcProvider, dstProvider, srcChain, dstChain, int64(srcChainID), dstChainID, d.legacyChains, d.isNewlyCreatedJob, oracleArgsNoPlugin2, logError) + return ccipexec.NewExecServices(ctx, lggr, jb, srcProvider, dstProvider, int64(srcChainID), dstChainID, d.isNewlyCreatedJob, oracleArgsNoPlugin2, logError) } func (d *Delegate) ccipExecGetDstProvider(ctx context.Context, jb job.Job, pluginJobSpecConfig ccipconfig.ExecPluginJobSpecConfig, transmitterID string) (types.CCIPExecProvider, error) { diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go index 729d8ca5c1..fde5d61d73 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/initializers.go @@ -56,6 +56,9 @@ func NewCommitServices(ctx context.Context, ds sqlutil.DataSource, srcProvider c } commitStoreAddress := common.HexToAddress(spec.ContractID) + + // commit store contract doesn't exist on the source chain, but we have an implementation of it + // to get access to a gas estimator on the source chain srcCommitStore, err := srcProvider.NewCommitStoreReader(ctx, ccipcalc.EvmAddrToGeneric(commitStoreAddress)) if err != nil { return nil, err @@ -222,7 +225,7 @@ func CommitReportToEthTxMeta(typ ccipconfig.ContractType, ver semver.Version) (f // https://github.com/smartcontractkit/ccip/blob/68e2197472fb017dd4e5630d21e7878d58bc2a44/core/services/feeds/service.go#L716 // TODO once that transaction is broken up, we should be able to simply rely on oracle.Close() to cleanup the filters. // Until then we have to deterministically reload the readers from the spec (and thus their filters) and close them. -func UnregisterCommitPluginLpFilters(ctx context.Context, lggr logger.Logger, jb job.Job, chainSet legacyevm.LegacyChainContainer) error { +func UnregisterCommitPluginLpFilters(_ context.Context, lggr logger.Logger, jb job.Job, chainSet legacyevm.LegacyChainContainer) error { params, err := extractJobSpecParams(jb, chainSet) if err != nil { return err diff --git a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go index a9f474c17d..e30ebd32c7 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go @@ -50,7 +50,7 @@ var ( var defaultNewReportingPluginRetryConfig = ccipdata.RetryConfig{InitialDelay: time.Second, MaxDelay: 5 * time.Minute} -func NewExecServices(ctx context.Context, lggr logger.Logger, jb job.Job, srcProvider types.CCIPExecProvider, dstProvider types.CCIPExecProvider, srcChain legacyevm.Chain, dstChain legacyevm.Chain, srcChainID int64, dstChainID int64, chainSet legacyevm.LegacyChainContainer, new bool, argsNoPlugin libocr2.OCR2OracleArgs, logError func(string)) ([]job.ServiceCtx, error) { +func NewExecServices(ctx context.Context, lggr logger.Logger, jb job.Job, srcProvider types.CCIPExecProvider, dstProvider types.CCIPExecProvider, srcChainID int64, dstChainID int64, new bool, argsNoPlugin libocr2.OCR2OracleArgs, logError func(string)) ([]job.ServiceCtx, error) { if jb.OCR2OracleSpec == nil { return nil, fmt.Errorf("spec is nil") } @@ -89,21 +89,18 @@ func NewExecServices(ctx context.Context, lggr logger.Logger, jb job.Job, srcPro return nil, fmt.Errorf("get source wrapped native token: %w", err) } - versionFinder := ccip.NewEvmVersionFinder() - commitStoreReader, err := factory.NewCommitStoreReader(lggr, versionFinder, offRampConfig.CommitStore, dstChain.Client(), dstChain.LogPoller()) + srcCommitStore, err := srcProvider.NewCommitStoreReader(ctx, offRampConfig.CommitStore) if err != nil { - return nil, fmt.Errorf("could not load commitStoreReader reader: %w", err) + return nil, fmt.Errorf("could not create src commitStoreReader reader: %w", err) } - err = commitStoreReader.SetGasEstimator(ctx, srcChain.GasEstimator()) + dstCommitStore, err := dstProvider.NewCommitStoreReader(ctx, offRampConfig.CommitStore) if err != nil { - return nil, fmt.Errorf("could not set gas estimator: %w", err) + return nil, fmt.Errorf("could not create dst commitStoreReader reader: %w", err) } - err = commitStoreReader.SetSourceMaxGasPrice(ctx, srcChain.Config().EVM().GasEstimator().PriceMax().ToInt()) - if err != nil { - return nil, fmt.Errorf("could not set source max gas price: %w", err) - } + var commitStoreReader ccipdata.CommitStoreReader + commitStoreReader = ccip.NewProviderProxyCommitStoreReader(srcCommitStore, dstCommitStore) tokenDataProviders := make(map[cciptypes.Address]tokendata.Reader) // init usdc token data provider diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 780bf4749b..3cc7633aa3 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -478,6 +478,8 @@ func (r *Relayer) NewCCIPExecProvider(rargs commontypes.RelayArgs, pargs commont r.lggr, versionFinder, r.chain.Client(), + r.chain.GasEstimator(), + r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), r.chain.LogPoller(), execPluginConfig.SourceStartBlock, execPluginConfig.JobID, diff --git a/core/services/relay/evm/exec_provider.go b/core/services/relay/evm/exec_provider.go index 757ca3a498..740a61f23d 100644 --- a/core/services/relay/evm/exec_provider.go +++ b/core/services/relay/evm/exec_provider.go @@ -28,6 +28,8 @@ type SrcExecProvider struct { client client.Client lp logpoller.LogPoller startBlock uint64 + estimator gas.EvmFeeEstimator + maxGasPrice *big.Int usdcReader *ccip.USDCReaderImpl usdcAttestationAPI string usdcAttestationAPITimeoutSeconds int @@ -39,6 +41,8 @@ func NewSrcExecProvider( lggr logger.Logger, versionFinder ccip.VersionFinder, client client.Client, + estimator gas.EvmFeeEstimator, + maxGasPrice *big.Int, lp logpoller.LogPoller, startBlock uint64, jobID string, @@ -60,6 +64,8 @@ func NewSrcExecProvider( lggr: lggr, versionFinder: versionFinder, client: client, + estimator: estimator, + maxGasPrice: maxGasPrice, lp: lp, startBlock: startBlock, usdcReader: usdcReader, @@ -120,9 +126,9 @@ func (s SrcExecProvider) Codec() commontypes.Codec { return nil } -func (s SrcExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptypes.Address) (cciptypes.CommitStoreReader, error) { - // TODO CCIP-2493 - return nil, fmt.Errorf("invalid: NewCommitStoreReader not implemented") +func (s SrcExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { + commitStoreReader = NewIncompleteSourceCommitStoreReader(s.estimator, s.maxGasPrice) + return } func (s SrcExecProvider) NewOffRampReader(ctx context.Context, addr cciptypes.Address) (cciptypes.OffRampReader, error) { @@ -262,9 +268,10 @@ func (d DstExecProvider) Codec() commontypes.Codec { return nil } -func (d DstExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptypes.Address) (cciptypes.CommitStoreReader, error) { - // TODO CCIP-2493 - return nil, fmt.Errorf("invalid: NewCommitStoreReader not yet implemented") +func (d DstExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { + versionFinder := ccip.NewEvmVersionFinder() + commitStoreReader, err = NewIncompleteDestCommitStoreReader(d.lggr, versionFinder, addr, d.client, d.lp) + return } func (d DstExecProvider) NewOffRampReader(ctx context.Context, offRampAddress cciptypes.Address) (offRampReader cciptypes.OffRampReader, err error) { From c10a0f0969dc3c2d0cc3ddedfb0ba78ced517530 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:35:05 +0400 Subject: [PATCH 61/61] Remove `prevOnRamp` from multi onramp (#1130) ## Motivation Missed in https://github.com/smartcontractkit/ccip/pull/985. With the introduction of the `NonceManager` the `prevOnRamp` sequencing check isn't performed in the onramp anymore. ## Solution Remove `DestChainConfig.prevOnRamp` and `DestChainConfigArgs.prevOnRamp`. --- contracts/gas-snapshots/ccip.gas-snapshot | 139 +++++++++--------- .../v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol | 11 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 1 - .../ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol | 28 +--- .../test/onRamp/EVM2EVMMultiOnRampSetup.t.sol | 4 +- .../evm_2_evm_multi_onramp.go | 8 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 79 insertions(+), 114 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index d76d62a606..7dc723cb77 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -245,27 +245,26 @@ EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176601) EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178672) EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141533) EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51505) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16917) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 34341) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16770) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigNewPrevOnRampOnExistingChain_Revert() (gas: 31306) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16842) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput() (gas: 12336) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 177813) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11449) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54003) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44785) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12302) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86917) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13111) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17106) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12290) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkChainSelectorEqZero_Revert() (gas: 143541) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkTokenEqAddressZero_Revert() (gas: 139156) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 141442) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 146463) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 141509) -EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 5447902) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16764) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 33948) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16639) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16689) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput() (gas: 12380) +EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 174823) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11427) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 53981) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44763) +EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12280) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86785) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17084) +EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12268) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkChainSelectorEqZero_Revert() (gas: 143130) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkTokenEqAddressZero_Revert() (gas: 138745) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 141031) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 146052) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 141098) +EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 5372179) EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsDefault_Success() (gas: 18235) EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 22580) EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 19677) @@ -273,71 +272,71 @@ EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsInvalidExtraArgsTag_R EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsV1_Success() (gas: 19292) EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsV2_Success() (gas: 19431) EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EmptyExtraArgs_Success() (gas: 19657) -EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 105130) -EVM2EVMMultiOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 109612) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 138405) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 169217) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 168640) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 168046) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 168914) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 168275) +EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 105069) +EVM2EVMMultiOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 109195) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 138322) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 169134) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 168557) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 167963) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 168831) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 168192) EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 31992) EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 27934) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidEVMAddressDestToken_Revert() (gas: 3525966) +EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidEVMAddressDestToken_Revert() (gas: 3525905) EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidEVMAddress_Revert() (gas: 32232) EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 37388) EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 38351) EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107541) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 152145) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 152074) EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 33678) EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 23015) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 41487) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 41465) EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25860) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 244399) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 270405) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 152708) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 179642) -EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3821022) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 242526) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 268532) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 152647) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 179581) +EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3820695) EVM2EVMMultiOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 29961) EVM2EVMMultiOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 44169) -EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 144163) +EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 144102) EVM2EVMMultiOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 250642) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 107224) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 283983) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 126323) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 107163) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 283856) +EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 125164) EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 12013) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 24974) +EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 24707) EVM2EVMMultiOnRamp_getFee:test_DestinationChainNotEnabled_Revert() (gas: 15422) -EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 102285) -EVM2EVMMultiOnRamp_getFee:test_HighGasMessage_Success() (gas: 258923) +EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 101749) +EVM2EVMMultiOnRamp_getFee:test_HighGasMessage_Success() (gas: 258343) EVM2EVMMultiOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 42468) EVM2EVMMultiOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95014) -EVM2EVMMultiOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 183629) +EVM2EVMMultiOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 182871) EVM2EVMMultiOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 21863) -EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 141949) +EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 141280) EVM2EVMMultiOnRamp_getFee:test_TooManyTokens_Revert() (gas: 17439) -EVM2EVMMultiOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 84431) +EVM2EVMMultiOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 83471) EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 47357) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35335) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28409) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130389) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15255) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28217) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21265) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 41270) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28240) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40601) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 31720) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11378) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12978) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11335) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16331) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 60104) -EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10851) -EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6711) -EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6417) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 47313) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35291) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28365) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130125) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15233) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28173) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21243) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 41226) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28196) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40557) +EVM2EVMMultiOnRamp_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 31676) +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: 60060) +EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10895) +EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6755) +EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6461) EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97211) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38076) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 108251) @@ -649,7 +648,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) -MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1457196) +MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1457013) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) @@ -661,10 +660,10 @@ NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success( NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 248762) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236748) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 144907) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 185811) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 242327) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 185728) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 242161) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125653) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 133309) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 133226) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122899) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) diff --git a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol index bcb7a74c5f..d3e560b5fe 100644 --- a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol @@ -146,8 +146,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre /// @dev Struct to hold the configs for a destination chain struct DestChainConfig { - DestChainDynamicConfig dynamicConfig; // ──╮ Dynamic configs for a destination chain - address prevOnRamp; // ────────────────────╯ Address of previous-version OnRamp + DestChainDynamicConfig dynamicConfig; // Dynamic configs for a destination chain uint64 sequenceNumber; // The last used sequence number. This is zero in the case where no messages has been sent yet. // 0 is not a valid sequence number for any real transaction. /// @dev metadataHash is a lane-specific prefix for a message hash preimage which ensures global uniqueness @@ -157,14 +156,12 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre bytes32 metadataHash; } - /// @dev Struct to hold the dynamic configs, its destination chain selector and previous onRamp. - /// Same as DestChainConfig but with the destChainSelector and the prevOnRamp so that an array of these + /// @dev Struct to hold the dynamic configs, its destination chain selector. Same as DestChainConfig but with the destChainSelector so that an array of these /// can be passed in the constructor and the applyDestChainConfigUpdates function //solhint-disable gas-struct-packing struct DestChainConfigArgs { uint64 destChainSelector; // Destination chain selector DestChainDynamicConfig dynamicConfig; // Struct to hold the configs for a destination chain - address prevOnRamp; // Address of previous-version OnRamp. } // STATIC CONFIG @@ -761,11 +758,9 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre } DestChainConfig storage destChainConfig = s_destChainConfig[destChainSelector]; - address prevOnRamp = destChainConfigArg.prevOnRamp; DestChainConfig memory newDestChainConfig = DestChainConfig({ dynamicConfig: destChainConfigArg.dynamicConfig, - prevOnRamp: prevOnRamp, sequenceNumber: destChainConfig.sequenceNumber, metadataHash: destChainConfig.metadataHash }); @@ -776,11 +771,9 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre newDestChainConfig.metadataHash = keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))); destChainConfig.metadataHash = newDestChainConfig.metadataHash; - if (prevOnRamp != address(0)) destChainConfig.prevOnRamp = prevOnRamp; emit DestChainAdded(destChainSelector, destChainConfig); } else { - if (destChainConfig.prevOnRamp != prevOnRamp) revert InvalidDestChainConfig(destChainSelector); if (destChainConfigArg.dynamicConfig.defaultTokenDestBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { revert InvalidDestBytesOverhead(address(0), destChainConfigArg.dynamicConfig.defaultTokenDestBytesOverhead); } diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index a9b248eb72..a99fc0c77a 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -245,7 +245,6 @@ contract NonceManager_OnRampUpgrade is EVM2EVMMultiOnRampSetup { s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - destChainConfigArgs[0].prevOnRamp = address(s_prevOnRamp); (s_onRamp, s_metadataHash) = _deployOnRamp( SOURCE_CHAIN_SELECTOR, address(s_sourceRouter), address(s_outboundNonceManager), address(s_tokenAdminRegistry) diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol index 253012570b..2cc1de1ddd 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol @@ -41,7 +41,6 @@ contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { DEST_CHAIN_SELECTOR, EVM2EVMMultiOnRamp.DestChainConfig({ dynamicConfig: destChainConfigArg.dynamicConfig, - prevOnRamp: address(0), sequenceNumber: 0, metadataHash: "" }) @@ -61,7 +60,6 @@ contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig = EVM2EVMMultiOnRamp.DestChainConfig({ dynamicConfig: destChainConfigArg.dynamicConfig, - prevOnRamp: address(0), sequenceNumber: 0, metadataHash: keccak256( abi.encode( @@ -197,18 +195,13 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet ); destChainConfigArgs.dynamicConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - bool isNewChain = true; + bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; - if (destChainConfigArgs.destChainSelector == DEST_CHAIN_SELECTOR) { - destChainConfigArgs.prevOnRamp = address(0); - isNewChain = false; - } EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory newDestChainConfigArgs = new EVM2EVMMultiOnRamp.DestChainConfigArgs[](1); newDestChainConfigArgs[0] = destChainConfigArgs; EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig = EVM2EVMMultiOnRamp.DestChainConfig({ dynamicConfig: destChainConfigArgs.dynamicConfig, - prevOnRamp: destChainConfigArgs.prevOnRamp, sequenceNumber: 0, metadataHash: keccak256( abi.encode( @@ -244,7 +237,6 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig0 = EVM2EVMMultiOnRamp.DestChainConfig({ dynamicConfig: destChainConfigArgs[0].dynamicConfig, - prevOnRamp: address(0), sequenceNumber: 0, metadataHash: keccak256( abi.encode( @@ -258,7 +250,6 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig1 = EVM2EVMMultiOnRamp.DestChainConfig({ dynamicConfig: destChainConfigArgs[1].dynamicConfig, - prevOnRamp: address(0), sequenceNumber: 0, metadataHash: keccak256( abi.encode( @@ -320,17 +311,6 @@ contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSet s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_InvalidDestChainConfigNewPrevOnRampOnExistingChain_Revert() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.prevOnRamp = address(1); - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - } - function test_InvalidDestBytesOverhead_Revert() public { EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -1100,8 +1080,7 @@ contract EVM2EVMMultiOnRamp_getDataAvailabilityCost is EVM2EVMMultiOnRamp_getFee EVM2EVMMultiOnRamp.DestChainConfig memory destChainConfig = s_onRamp.getDestChainConfig(destChainSelector); destChainConfigArgs[0] = EVM2EVMMultiOnRamp.DestChainConfigArgs({ destChainSelector: destChainSelector, - dynamicConfig: destChainConfig.dynamicConfig, - prevOnRamp: destChainConfig.prevOnRamp + dynamicConfig: destChainConfig.dynamicConfig }); destChainConfigArgs[0].dynamicConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; destChainConfigArgs[0].dynamicConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; @@ -1173,8 +1152,7 @@ contract EVM2EVMMultiOnRamp_getFee is EVM2EVMMultiOnRamp_getFeeSetup { EVM2EVMMultiOnRamp.DestChainConfig memory destChainConfig = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR); destChainConfigArgs[0] = EVM2EVMMultiOnRamp.DestChainConfigArgs({ destChainSelector: DEST_CHAIN_SELECTOR, - dynamicConfig: destChainConfig.dynamicConfig, - prevOnRamp: destChainConfig.prevOnRamp + dynamicConfig: destChainConfig.dynamicConfig }); destChainConfigArgs[0].dynamicConfig.destDataAvailabilityMultiplierBps = 0; s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol index 97136d048f..24a47d1aca 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol @@ -276,8 +276,7 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { networkFeeUSDCents: 1_00, enforceOutOfOrder: false, chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM - }), - prevOnRamp: address(0) + }) }); return destChainConfigs; } @@ -367,7 +366,6 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { assertEq(a.dynamicConfig.defaultTokenDestGasOverhead, b.dynamicConfig.defaultTokenDestGasOverhead); assertEq(a.dynamicConfig.defaultTokenDestBytesOverhead, b.dynamicConfig.defaultTokenDestBytesOverhead); assertEq(a.dynamicConfig.defaultTxGasLimit, b.dynamicConfig.defaultTxGasLimit); - assertEq(a.prevOnRamp, b.prevOnRamp); assertEq(a.sequenceNumber, b.sequenceNumber); assertEq(a.metadataHash, b.metadataHash); } diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go index 4fdc2e8136..66a4769dd7 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go @@ -45,7 +45,6 @@ type ClientEVMTokenAmount struct { type EVM2EVMMultiOnRampDestChainConfig struct { DynamicConfig EVM2EVMMultiOnRampDestChainDynamicConfig - PrevOnRamp common.Address SequenceNumber uint64 MetadataHash [32]byte } @@ -53,7 +52,6 @@ type EVM2EVMMultiOnRampDestChainConfig struct { type EVM2EVMMultiOnRampDestChainConfigArgs struct { DestChainSelector uint64 DynamicConfig EVM2EVMMultiOnRampDestChainDynamicConfig - PrevOnRamp common.Address } type EVM2EVMMultiOnRampDestChainDynamicConfig struct { @@ -148,8 +146,8 @@ type InternalRampTokenAmount struct { } var EVM2EVMMultiOnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"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\":[{\"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\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"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\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainDynamicConfigUpdated\",\"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\"},{\"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\":\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"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\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":[{\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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: "0x6101406040523480156200001257600080fd5b506040516200740738038062007407833981016040819052620000359162001528565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000214565b505085516001600160a01b031615905080620000e6575060208501516001600160401b0316155b80620000fd575060608501516001600160a01b0316155b8062000114575060808501516001600160a01b0316155b806200012b575060a08501516001600160a01b0316155b156200014a576040516306b7c75960e31b815260040160405180910390fd5b84516001600160a01b0390811660a090815260208701516001600160401b031660c05260408701516001600160601b031660809081526060880151831660e0528701518216610100528601511661012052620001a684620002bf565b620001b18362000482565b620001bc8262000a4b565b60408051600080825260208201909252620002099183919062000202565b6040805180820190915260008082526020820152815260200190600190039081620001da5790505b5062000b17565b50505050506200199a565b336001600160a01b038216036200026e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b03161580620002e5575060608101516001600160a01b0316155b1562000304576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b039283166001600160a01b0319918216179091556020808401516003805491851691841691909117905560408085015160048054918616918516919091179055606080860151600580549187169190951617909355805160c0808201835260a080518716835290516001600160401b031693820193909352608080516001600160601b03168284015260e05186169482019490945261010051851693810193909352610120519093169082015290517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916200047791849082516001600160a01b0390811682526020808501516001600160401b0316818401526040808601516001600160601b03168185015260608087015184168186015260808088015185169086015260a0968701518416968501969096528451831660c085015290840151821660e084015283015181166101008301529190920151166101208201526101400190565b60405180910390a150565b60005b815181101562000a47576000828281518110620004a657620004a66200166e565b602002602001015190506000838381518110620004c757620004c76200166e565b6020026020010151600001519050806001600160401b031660001480620004fe5750602082015161018001516001600160401b0316155b80620005245750602082015161020001516001600160e01b031916630a04b54b60e21b14155b156200054f5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b600060066000836001600160401b03166001600160401b0316815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a90046001600160401b03166001600160401b031681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505082600301546000801b03620009645760c051604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f732160208201526001600160401b0392831691810191909152908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b038216156200091b576002830180546001600160a01b0319166001600160a01b0384161790555b836001600160401b03167f66951b52bb33e5d462611460f7aa53069005b173e002d9224c15fb986e4ead8f8460405162000956919062001684565b60405180910390a262000a36565b60028301546001600160a01b03838116911614620009a15760405163c35aa79d60e01b81526001600160401b038516600482015260240162000083565b60208560200151610160015163ffffffff161015620009ee57602085015161016001516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000083565b836001600160401b03167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb866020015160405162000a2d919062001843565b60405180910390a25b505050505080600101905062000485565b5050565b60005b815181101562000a4757600082828151811062000a6f5762000a6f6200166e565b6020026020010151600001519050600083838151811062000a945762000a946200166e565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a4e565b60005b825181101562000d8457600083828151811062000b3b5762000b3b6200166e565b6020026020010151905060008160000151905060005b82602001515181101562000d755760008360200151828151811062000b7a5762000b7a6200166e565b602002602001015160200151905060008460200151838151811062000ba35762000ba36200166e565b60200260200101516000015190506020826080015163ffffffff16101562000bfc5760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d62908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b51565b50505080600101905062000b1a565b5060005b815181101562000e4a57600082828151811062000da95762000da96200166e565b6020026020010151600001519050600083838151811062000dce5762000dce6200166e565b6020908102919091018101518101516001600160401b03841660008181526008845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d88565b505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b60405290565b60405161022081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b604080519081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b60405160c081016001600160401b038111828210171562000e8a5762000e8a62000e4f565b604051601f8201601f191681016001600160401b038111828210171562000f2b5762000f2b62000e4f565b604052919050565b80516001600160a01b038116811462000f4b57600080fd5b919050565b80516001600160401b038116811462000f4b57600080fd5b60006080828403121562000f7b57600080fd5b604051608081016001600160401b038111828210171562000fa05762000fa062000e4f565b60405290508062000fb18362000f33565b815262000fc16020840162000f33565b602082015262000fd46040840162000f33565b604082015262000fe76060840162000f33565b60608201525092915050565b60006001600160401b038211156200100f576200100f62000e4f565b5060051b60200190565b8051801515811462000f4b57600080fd5b805161ffff8116811462000f4b57600080fd5b805163ffffffff8116811462000f4b57600080fd5b80516001600160e01b03198116811462000f4b57600080fd5b600082601f8301126200107d57600080fd5b8151602062001096620010908362000ff3565b62000f00565b8281526102609283028501820192828201919087851115620010b757600080fd5b8387015b858110156200128b5780890382811215620010d65760008081fd5b620010e062000e65565b620010eb8362000f50565b815261022080601f1984011215620011035760008081fd5b6200110d62000e90565b92506200111c88850162001019565b835260406200112d8186016200102a565b898501526060620011408187016200103d565b828601526080620011538188016200103d565b8287015260a09150620011688288016200103d565b9086015260c06200117b8782016200102a565b8287015260e09150620011908288016200103d565b90860152610100620011a48782016200102a565b828701526101209150620011ba8288016200102a565b90860152610140620011ce8782016200102a565b828701526101609150620011e48288016200103d565b90860152610180620011f88782016200103d565b828701526101a091506200120e82880162000f50565b908601526101c06200122287820162000f50565b828701526101e09150620012388288016200103d565b908601526102006200124c87820162001019565b828701526200125d84880162001052565b818701525050838984015262001277610240860162000f33565b9083015250855250928401928101620010bb565b5090979650505050505050565b600082601f830112620012aa57600080fd5b81516020620012bd620010908362000ff3565b82815260069290921b84018101918181019086841115620012dd57600080fd5b8286015b84811015620013335760408189031215620012fc5760008081fd5b6200130662000eb6565b620013118262000f33565b81526200132085830162000f50565b81860152835291830191604001620012e1565b509695505050505050565b600082601f8301126200135057600080fd5b8151602062001363620010908362000ff3565b82815260059290921b840181019181810190868411156200138357600080fd5b8286015b84811015620013335780516001600160401b0380821115620013a857600080fd5b908801906040601f19838c038101821315620013c357600080fd5b620013cd62000eb6565b620013da89860162000f50565b81528285015184811115620013ee57600080fd5b8086019550508c603f8601126200140457600080fd5b88850151935062001419620010908562000ff3565b84815260e09094028501830193898101908e8611156200143857600080fd5b958401955b858710156200151157868f0360e08112156200145857600080fd5b6200146262000eb6565b6200146d8962000f33565b815260c086830112156200148057600080fd5b6200148a62000edb565b9150620014998d8a016200103d565b8252620014a8878a016200103d565b8d830152620014ba60608a016200102a565b87830152620014cc60808a016200103d565b6060830152620014df60a08a016200103d565b6080830152620014f260c08a0162001019565b60a0830152808d0191909152825260e09690960195908a01906200143d565b828b01525087525050509284019250830162001387565b60008060008060008587036101a08112156200154357600080fd5b60c08112156200155257600080fd5b506200155d62000edb565b620015688762000f33565b8152620015786020880162000f50565b602082015260408701516001600160601b03811681146200159857600080fd5b6040820152620015ab6060880162000f33565b6060820152620015be6080880162000f33565b6080820152620015d160a0880162000f33565b60a08201529450620015e78760c0880162000f68565b6101408701519094506001600160401b03808211156200160657600080fd5b6200161489838a016200106b565b94506101608801519150808211156200162c57600080fd5b6200163a89838a0162001298565b93506101808801519150808211156200165257600080fd5b5062001661888289016200133e565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b815460ff81161515825261028082019061ffff600882901c8116602085015263ffffffff601883901c81166040860152620016cc60608601828560381c1663ffffffff169052565b620016e460808601828560581c1663ffffffff169052565b620016fa60a08601838560781c1661ffff169052565b6200171260c08601828560881c1663ffffffff169052565b6200172860e08601838560a81c1661ffff169052565b6200173f6101008601838560b81c1661ffff169052565b620017566101208601838560c81c1661ffff169052565b6200176f6101408601828560d81c1663ffffffff169052565b600186015463ffffffff8282161661016087015292506001600160401b03602084901c81166101808701529150620017b86101a08601838560601c166001600160401b03169052565b620017d16101c08601828560a01c1663ffffffff169052565b50620017e86101e0850160ff8460c01c1615159052565b6001600160e01b0319601883901b1661020085015260028501546001600160a01b0381166102208601529150620018306102408501828460a01c166001600160401b03169052565b5050600383015461026083015292915050565b8151151581526102208101602083015162001864602084018261ffff169052565b5060408301516200187d604084018263ffffffff169052565b50606083015162001896606084018263ffffffff169052565b506080830151620018af608084018263ffffffff169052565b5060a0830151620018c660a084018261ffff169052565b5060c0830151620018df60c084018263ffffffff169052565b5060e0830151620018f660e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b03908116918501919091526101a080860151909116908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b60805160a05160c05160e05161010051610120516159b462001a53600039600081816102da015281816111820152612c640152600081816102ab01528181612c3c015261350001526000818161027c01528181612c120152612d77015260008181610218015281816123f501528181612bad01526135910152600081816101e901528181612b880152818161302901526130bb01526000818161024801528181612bdf0152818161317d01526131ed01526159b46000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063770e2dc4116100cd578063a69c64c011610081578063df0aa9e911610066578063df0aa9e9146108e5578063f2fde38b146108f8578063fbca3b741461090b57600080fd5b8063a69c64c0146108bf578063a6f3ab6c146108d257600080fd5b806382b49eb0116100b257806382b49eb0146107385780638da5cb5b1461089b5780639041be3d146108ac57600080fd5b8063770e2dc41461071d57806379ba50971461073057600080fd5b80633a019940116101245780636def4ce7116101095780636def4ce7146103b6578063714f5ec5146106975780637437ff9f146106aa57600080fd5b80633a0199401461038157806348a98aa41461038b57600080fd5b8063061877e31461015657806306285c69146101a7578063181f5a771461031757806320487ded14610360575b600080fd5b61018961016436600461418f565b6001600160a01b031660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61030a6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161019e91906141ac565b6103536040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161019e9190614268565b61037361036e3660046142b4565b61092b565b60405190815260200161019e565b610389610f83565b005b61039e610399366004614304565b611147565b6040516001600160a01b03909116815260200161019e565b61068a6103c436600461433d565b604080516102a08101825260006080820181815260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e083018290526102008301829052610220830182905261024083018290526102608301829052610280830182905282526020820181905291810182905260608101919091525067ffffffffffffffff90811660009081526006602090815260409182902082516102a081018452815460ff80821615156080840190815261010080840461ffff90811660a08701526301000000850463ffffffff90811660c08801526701000000000000008604811660e0808901919091526b01000000000000000000000087048216938801939093526f0100000000000000000000000000000086048216610120880152710100000000000000000000000000000000008604811661014088015275010000000000000000000000000000000000000000008604821661016088015277010000000000000000000000000000000000000000000000860482166101808801527901000000000000000000000000000000000000000000000000008087049092166101a08801527b0100000000000000000000000000000000000000000000000000000090950485166101c087015260018701548086166101e088015264010000000081048b166102008801526c0100000000000000000000000081048b166102208801527401000000000000000000000000000000000000000080820490961661024088015278010000000000000000000000000000000000000000000000008104909416151561026087015290920490911b6001600160e01b031916610280840152825260028301546001600160a01b0381169483019490945290920490931691810191909152600390910154606082015290565b60405161019e91906144a0565b6103896106a536600461465b565b6111f6565b61071060408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526002546001600160a01b03908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161019e9190614880565b61038961072b366004614958565b61120a565b610389611220565b61083b610746366004614304565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff9190911660009081526008602090815260408083206001600160a01b0394909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b60405161019e9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b6000546001600160a01b031661039e565b6101896108ba36600461433d565b6112e9565b6103896108cd366004614bd2565b61132d565b6103896108e0366004614c90565b61133e565b6103736108f3366004614d15565b61134f565b61038961090636600461418f565b6117c7565b61091e61091936600461433d565b6117d8565b60405161019e9190614d81565b67ffffffffffffffff82166000908152600660205260408120805460ff16610990576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6109c1846109a16020860186614dce565b90506109b06040870187614e1c565b90506109bc8780614dce565b61180c565b60006007816109d6608087016060880161418f565b6001600160a01b03168152602081019190915260400160009081205467ffffffffffffffff169150819003610a5357610a15608085016060860161418f565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b60035460009081906001600160a01b031663ffdb4b37610a796080890160608a0161418f565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8a1660248201526044016040805180830381865afa158015610acc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af09190614e7d565b90925090506000808080610b0760408b018b614e1c565b90501115610b4257610b368a610b2360808c0160608d0161418f565b87610b3160408e018e614e1c565b611934565b91945092509050610b79565b6001870154610b769074010000000000000000000000000000000000000000900463ffffffff16662386f26fc10000614ed6565b92505b865460009077010000000000000000000000000000000000000000000000900461ffff1615610be257610bdf8b6dffffffffffffffffffffffffffff607088901c16610bc860208e018e614dce565b9050610bd760408f018f614e1c565b905086611d10565b90505b875460009063ffffffff8516906f01000000000000000000000000000000900461ffff16610c1360208e018e614dce565b610c1e929150614ed6565b8a54610c3f91906b010000000000000000000000900463ffffffff16614eed565b610c499190614eed565b9050610edc610c5b60808d018d614dce565b8b604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050611e16565b51610ee79082614eed565b60018a01549091506000906c01000000000000000000000000900467ffffffffffffffff16610f26836dffffffffffffffffffffffffffff8a16614ed6565b610f309190614ed6565b90506001600160e01b0388168382610f5267ffffffffffffffff8d168a614ed6565b610f5c9190614eed565b610f669190614eed565b610f709190614f00565b9a50505050505050505050505b92915050565b600354604080517fcdc73d5100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163cdc73d5191600480830192869291908290030181865afa158015610fe5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261100d9190810190614f3b565b6005549091506001600160a01b031660005b825181101561114257600083828151811061103c5761103c614fca565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ce9190614ff9565b90508015611138576110ea6001600160a01b0383168583611ed1565b816001600160a01b0316846001600160a01b03167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161112f91815260200190565b60405180910390a35b505060010161101f565b505050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190615012565b9392505050565b6111fe611f3c565b61120781611f98565b50565b611212611f3c565b61121c82826125ee565b5050565b6001546001600160a01b0316331461127a5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610987565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120600201549091610f7d9174010000000000000000000000000000000000000000900416600161502f565b611335611f3c565b611207816129ce565b611346611f3c565b61120781612aab565b67ffffffffffffffff84166000908152600660205260408120816113768288888888612cc4565b905060005b8160e00151518110156117635760006113976040890189614e1c565b838181106113a7576113a7614fca565b9050604002018036038101906113bd9190615057565b905080602001516000036113fd576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061140d8a8360000151611147565b90506001600160a01b03811615806114c357506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801561149d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c19190615091565b155b156115085781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b6000816001600160a01b0316639a4575b96040518060a001604052808d80600001906115349190614dce565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff8f166020808301919091526001600160a01b03808e16604080850191909152918901516060840152885116608090920191909152516001600160e01b031960e084901b1681526115c791906004016150ae565b6000604051808303816000875af11580156115e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261160e919081019061517b565b9050602081602001515111801561166f575067ffffffffffffffff8b16600090815260086020908152604080832086516001600160a01b0316845282529091205490820151516e01000000000000000000000000000090910463ffffffff16105b156116b45782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b600186015481516116e591790100000000000000000000000000000000000000000000000000900460e01b90613a20565b60408051608081019091526001600160a01b03831660a08201528060c081016040516020818303038152906040528152602001826000015181526020018260200151815260200184602001518152508560e00151858151811061174a5761174a614fca565b602002602001018190525050505080600101905061137b565b50611772818360030154613a5a565b81515260405167ffffffffffffffff8816907f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29906117b19084906152b0565b60405180910390a251519150505b949350505050565b6117cf611f3c565b61120781613b3c565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8516600090815260066020526040902080546301000000900463ffffffff168511156118855780546040517f86933789000000000000000000000000000000000000000000000000000000008152630100000090910463ffffffff16600482015260248101869052604401610987565b8054610100900461ffff168411156118c9576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154604080516020601f860181900481028201810190925284815261192c92790100000000000000000000000000000000000000000000000000900460e01b918690869081908401838280828437600092019190915250613a2092505050565b505050505050565b6000808083815b81811015611d0357600087878381811061195757611957614fca565b90506040020180360381019061196d9190615057565b905060006001600160a01b03166119888c8360000151611147565b6001600160a01b0316036119d65780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610987565b67ffffffffffffffff8b16600090815260086020908152604080832084516001600160a01b03168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052611b445767ffffffffffffffff8c1660009081526006602052604090208054611ae490790100000000000000000000000000000000000000000000000000900461ffff16662386f26fc10000614ed6565b611aee9089614eed565b8154909850611b22907b01000000000000000000000000000000000000000000000000000000900463ffffffff16886153c6565b6001820154909750611b3a9063ffffffff16876153c6565b9550505050611cfb565b604081015160009061ffff1615611c4b5760008c6001600160a01b031684600001516001600160a01b031614611c035760035484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015611bd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bfc91906153e3565b9050611c06565b508a5b620186a0836040015161ffff16611c338660200151846001600160e01b0316613bfd90919063ffffffff16565b611c3d9190614ed6565b611c479190614f00565b9150505b6060820151611c5a90886153c6565b9650816080015186611c6c91906153c6565b8251909650600090611c8b9063ffffffff16662386f26fc10000614ed6565b905080821015611caa57611c9f818a614eed565b985050505050611cfb565b6000836020015163ffffffff16662386f26fc10000611cc99190614ed6565b905080831115611ce957611cdd818b614eed565b99505050505050611cfb565b611cf3838b614eed565b995050505050505b60010161193b565b5050955095509592505050565b60008063ffffffff8316611d2560e086614ed6565b611d31876101c0614eed565b611d3b9190614eed565b611d459190614eed565b67ffffffffffffffff8816600090815260066020526040812080549293509171010000000000000000000000000000000000810463ffffffff1690611da7907501000000000000000000000000000000000000000000900461ffff1685614ed6565b611db19190614eed565b825490915077010000000000000000000000000000000000000000000000900461ffff16611def6dffffffffffffffffffffffffffff8a1683614ed6565b611df99190614ed6565b611e0990655af3107a4000614ed6565b9998505050505050505050565b60408051808201909152600080825260208201526000611e3c8585856101800151613c25565b9050826060015163ffffffff1681600001511115611e86576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015611e9a57508060200151155b156117bf576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611142908490613d9e565b6000546001600160a01b03163314611f965760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610987565b565b60005b815181101561121c576000828281518110611fb857611fb8614fca565b602002602001015190506000838381518110611fd657611fd6614fca565b60200260200101516000015190508067ffffffffffffffff166000148061200e57506020820151610180015167ffffffffffffffff16155b8061204c5750602082015161020001516001600160e01b0319167f2812d52c0000000000000000000000000000000000000000000000000000000014155b1561208f576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610987565b6000600660008367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002090506000836040015190506000604051806080016040528086602001518152602001836001600160a01b031681526020018460020160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020018460030154815250905080600001518360000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505082600301546000801b036124de57604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908516606082015230608082015260a00160408051601f1981840301815291905280516020909101206060820181905260038401556001600160a01b03821615612497576002830180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555b8367ffffffffffffffff167f66951b52bb33e5d462611460f7aa53069005b173e002d9224c15fb986e4ead8f846040516124d191906153fe565b60405180910390a26125de565b60028301546001600160a01b03838116911614612533576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610987565b60208560200151610160015163ffffffff16101561259757602085015161016001516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610987565b8367ffffffffffffffff167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb86602001516040516125d591906155b4565b60405180910390a25b5050505050806001019050611f9b565b60005b82518110156128f757600083828151811061260e5761260e614fca565b6020026020010151905060008160000151905060005b8260200151518110156128e95760008360200151828151811061264957612649614fca565b602002602001015160200151905060008460200151838151811061266f5761266f614fca565b60200260200101516000015190506020826080015163ffffffff1610156126df5760808201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015263ffffffff9091166024820152604401610987565b67ffffffffffffffff841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906128d7908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612624565b5050508060010190506125f1565b5060005b815181101561114257600082828151811061291857612918614fca565b6020026020010151600001519050600083838151811061293a5761293a614fca565b60209081029190910181015181015167ffffffffffffffff841660008181526008845260408082206001600160a01b038516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a350506001016128fb565b60005b815181101561121c5760008282815181106129ee576129ee614fca565b60200260200101516000015190506000838381518110612a1057612a10614fca565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016129d1565b60208101516001600160a01b03161580612ad0575060608101516001600160a01b0316155b15612b07576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556020808401516003805484169185169190911790556040808501516004805485169186169190911790556060808601516005805490951690861617909355805160c0810182527f0000000000000000000000000000000000000000000000000000000000000000851681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16928101929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16828201527f00000000000000000000000000000000000000000000000000000000000000008416928201929092527f0000000000000000000000000000000000000000000000000000000000000000831660808201527f000000000000000000000000000000000000000000000000000000000000000090921660a0830152517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa91612cb99184906155c3565b60405180910390a150565b604080516101a08101825260006101008201818152610120830182905261014083018290526101608301829052610180830182905282526020820181905260609282018390528282018390526080820183905260a0820181905260c082015260e08101919091526040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608086901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dea9190615091565b15612e2d576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610987565b6001600160a01b038216612e6d576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546001600160a01b03163314612eb1576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460ff16612ef8576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610987565b6000612f076040860186614e1c565b9150612f29905086612f1c6020880188614dce565b9050836109bc8980614dce565b801561301d576004546001600160a01b0316801561301b576040517fe0a0e5060000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063e0a0e50690612f88908a908a90600401615730565b600060405180830381600087803b158015612fa257600080fd5b505af1925050508015612fb3575060015b61301b573d808015612fe1576040519150601f19603f3d011682016040523d82523d6000602084013e612fe6565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016109879190614268565b505b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016613059608088016060890161418f565b6001600160a01b03160361306e575083613129565b6003546001600160a01b03166241e5be61308e6080890160608a0161418f565b60405160e083901b6001600160e01b03191681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015613102573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131269190614ff9565b90505b613139608087016060880161418f565b6001600160a01b03167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8260405161317391815260200190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681111561321a576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018290526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610987565b60006134b061322c6080890189614dce565b8b600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050611e16565b60200151613570576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff891660048201526001600160a01b0386811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015613549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061356d919061584e565b90505b604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528b811661014085015260028d018054939493849392610160850192916014916135f9917401000000000000000000000000000000000000000090041661586b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020018567ffffffffffffffff168152508152602001876001600160a01b0316815260200189806020019061365f9190614dce565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016136a38a80614dce565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016139716136ed60808c018c614dce565b8e600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050613e83565b815260200161398660808b0160608c0161418f565b6001600160a01b031681526020018881526020018567ffffffffffffffff8111156139b3576139b36144ed565b604051908082528060200260200182016040528015613a0f57816020015b6139fc6040518060800160405280606081526020016060815260200160608152602001600081525090565b8152602001906001900390816139d15790505b5090529a9950505050505050505050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b031983160161121c5761114281613f03565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001613a9c96959493929190615892565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001613ad391906158e6565b60408051601f1981840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b336001600160a01b03821603613b945760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610987565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a7640000613c1b836001600160e01b038616614ed6565b6111ef9190614f00565b60408051808201909152600080825260208201526000839003613c6657506040805180820190915267ffffffffffffffff82168152600060208201526111ef565b6000613c7284866158f9565b90506000613c838560048189615929565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b031982167fe7e230f00000000000000000000000000000000000000000000000000000000001613d085780806020019051810190613cff9190615953565b925050506111ef565b7f6859a837000000000000000000000000000000000000000000000000000000006001600160e01b0319831601613d6c57604051806040016040528082806020019051810190613d589190614ff9565b8152600060209091015292506111ef915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613df3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613f5e9092919063ffffffff16565b8051909150156111425780806020019051810190613e119190615091565b6111425760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610987565b6102008101516060907fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b0319821601613efb57613ec8858585611e16565b604080518251602080830191909152909201511515908201526060016040516020818303038152906040529150506111ef565b509392505050565b60008151602014613f4257816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109879190614268565b610f7d82806020019051810190613f599190614ff9565b613f6d565b60606117bf8484600085613fda565b60006001600160a01b03821180613f85575061040082105b15613fd65760408051602081018490520160408051601f19818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261098791600401614268565b5090565b6060824710156140525760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610987565b600080866001600160a01b0316858760405161406e919061598b565b60006040518083038185875af1925050503d80600081146140ab576040519150601f19603f3d011682016040523d82523d6000602084013e6140b0565b606091505b50915091506140c1878383876140cc565b979650505050505050565b6060831561413b578251600003614134576001600160a01b0385163b6141345760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610987565b50816117bf565b6117bf83838151156141505781518083602001fd5b8060405162461bcd60e51b81526004016109879190614268565b6001600160a01b038116811461120757600080fd5b803561418a8161416a565b919050565b6000602082840312156141a157600080fd5b81356111ef8161416a565b60c08101610f7d82846001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60005b8381101561423357818101518382015260200161421b565b50506000910152565b60008151808452614254816020860160208601614218565b601f01601f19169290920160200192915050565b6020815260006111ef602083018461423c565b67ffffffffffffffff8116811461120757600080fd5b803561418a8161427b565b600060a082840312156142ae57600080fd5b50919050565b600080604083850312156142c757600080fd5b82356142d28161427b565b9150602083013567ffffffffffffffff8111156142ee57600080fd5b6142fa8582860161429c565b9150509250929050565b6000806040838503121561431757600080fd5b82356143228161427b565b915060208301356143328161416a565b809150509250929050565b60006020828403121561434f57600080fd5b81356111ef8161427b565b8051151582526020810151614375602084018261ffff169052565b50604081015161438d604084018263ffffffff169052565b5060608101516143a5606084018263ffffffff169052565b5060808101516143bd608084018263ffffffff169052565b5060a08101516143d360a084018261ffff169052565b5060c08101516143eb60c084018263ffffffff169052565b5060e081015161440160e084018261ffff169052565b506101008181015161ffff9081169184019190915261012080830151909116908301526101408082015163ffffffff90811691840191909152610160808301518216908401526101808083015167ffffffffffffffff908116918501919091526101a080840151909116908401526101c080830151909116908301526101e080820151151590830152610200908101516001600160e01b031916910152565b6000610280820190506144b482845161435a565b60208301516001600160a01b0316610220830152604083015167ffffffffffffffff166102408301526060909201516102609091015290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561453f5761453f6144ed565b60405290565b604051610220810167ffffffffffffffff8111828210171561453f5761453f6144ed565b6040805190810167ffffffffffffffff8111828210171561453f5761453f6144ed565b60405160c0810167ffffffffffffffff8111828210171561453f5761453f6144ed565b604051601f8201601f1916810167ffffffffffffffff811182821017156145d8576145d86144ed565b604052919050565b600067ffffffffffffffff8211156145fa576145fa6144ed565b5060051b60200190565b801515811461120757600080fd5b803561418a81614604565b803561ffff8116811461418a57600080fd5b803563ffffffff8116811461418a57600080fd5b80356001600160e01b03198116811461418a57600080fd5b6000602080838503121561466e57600080fd5b823567ffffffffffffffff81111561468557600080fd5b8301601f8101851361469657600080fd5b80356146a96146a4826145e0565b6145af565b81815261026091820283018401918482019190888411156146c957600080fd5b938501935b8385101561487457848903818112156146e75760008081fd5b6146ef61451c565b86356146fa8161427b565b8152610220601f1983018113156147115760008081fd5b614719614545565b9250614726898901614612565b83526040614735818a0161461d565b8a8501526060614746818b0161462f565b828601526080614757818c0161462f565b8287015260a0915061476a828c0161462f565b9086015260c061477b8b820161461d565b8287015260e0915061478e828c0161462f565b908601526101006147a08b820161461d565b8287015261012091506147b4828c0161461d565b908601526101406147c68b820161461d565b8287015261016091506147da828c0161462f565b908601526101806147ec8b820161462f565b828701526101a09150614800828c01614291565b908601526101c06148128b8201614291565b828701526101e09150614826828c0161462f565b908601526102006148388b8201614612565b82870152614847848c01614643565b818701525050838a84015261485f6102408a0161417f565b908301525084525093840193918501916146ce565b50979650505050505050565b60808101610f7d828480516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b600082601f8301126148cd57600080fd5b813560206148dd6146a4836145e0565b82815260069290921b840181019181810190868411156148fc57600080fd5b8286015b8481101561494d57604081890312156149195760008081fd5b614921614569565b813561492c8161427b565b81528185013561493b8161416a565b81860152835291830191604001614900565b509695505050505050565b6000806040838503121561496b57600080fd5b67ffffffffffffffff8335111561498157600080fd5b83601f84358501011261499357600080fd5b6149a36146a484358501356145e0565b8335840180358083526020808401939260059290921b909101018610156149c957600080fd5b602085358601015b85358601803560051b01602001811015614b9c5767ffffffffffffffff813511156149fb57600080fd5b6040601f19823588358901018903011215614a1557600080fd5b614a1d614569565b614a306020833589358a0101013561427b565b863587018235016020810135825267ffffffffffffffff6040909101351115614a5857600080fd5b86358701823501604081013501603f81018913614a7457600080fd5b614a846146a460208301356145e0565b602082810135808352908201919060e00283016040018b1015614aa657600080fd5b604083015b604060e0602086013502850101811015614b835760e0818d031215614acf57600080fd5b614ad7614569565b614ae1823561416a565b8135815260c0601f19838f03011215614af957600080fd5b614b0161458c565b614b0d6020840161462f565b8152614b1b6040840161462f565b6020820152614b2c6060840161461d565b6040820152614b3d6080840161462f565b6060820152614b4e60a0840161462f565b6080820152614b6060c0840135614604565b60c083013560a0820152602082810191909152908452929092019160e001614aab565b50602084810191909152928652505092830192016149d1565b5092505067ffffffffffffffff60208401351115614bb957600080fd5b614bc984602085013585016148bc565b90509250929050565b60006020808385031215614be557600080fd5b823567ffffffffffffffff811115614bfc57600080fd5b8301601f81018513614c0d57600080fd5b8035614c1b6146a4826145e0565b81815260069190911b82018301908381019087831115614c3a57600080fd5b928401925b828410156140c15760408489031215614c585760008081fd5b614c60614569565b8435614c6b8161416a565b815284860135614c7a8161427b565b8187015282526040939093019290840190614c3f565b600060808284031215614ca257600080fd5b6040516080810181811067ffffffffffffffff82111715614cc557614cc56144ed565b6040528235614cd38161416a565b81526020830135614ce38161416a565b60208201526040830135614cf68161416a565b60408201526060830135614d098161416a565b60608201529392505050565b60008060008060808587031215614d2b57600080fd5b8435614d368161427b565b9350602085013567ffffffffffffffff811115614d5257600080fd5b614d5e8782880161429c565b935050604085013591506060850135614d768161416a565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b81811015614dc25783516001600160a01b031683529284019291840191600101614d9d565b50909695505050505050565b6000808335601e19843603018112614de557600080fd5b83018035915067ffffffffffffffff821115614e0057600080fd5b602001915036819003821315614e1557600080fd5b9250929050565b6000808335601e19843603018112614e3357600080fd5b83018035915067ffffffffffffffff821115614e4e57600080fd5b6020019150600681901b3603821315614e1557600080fd5b80516001600160e01b038116811461418a57600080fd5b60008060408385031215614e9057600080fd5b614e9983614e66565b9150614bc960208401614e66565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f7d57610f7d614ea7565b80820180821115610f7d57610f7d614ea7565b600082614f36577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020808385031215614f4e57600080fd5b825167ffffffffffffffff811115614f6557600080fd5b8301601f81018513614f7657600080fd5b8051614f846146a4826145e0565b81815260059190911b82018301908381019087831115614fa357600080fd5b928401925b828410156140c1578351614fbb8161416a565b82529284019290840190614fa8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561500b57600080fd5b5051919050565b60006020828403121561502457600080fd5b81516111ef8161416a565b67ffffffffffffffff81811683821601908082111561505057615050614ea7565b5092915050565b60006040828403121561506957600080fd5b615071614569565b823561507c8161416a565b81526020928301359281019290925250919050565b6000602082840312156150a357600080fd5b81516111ef81614604565b602081526000825160a060208401526150ca60c084018261423c565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f83011261512857600080fd5b815167ffffffffffffffff811115615142576151426144ed565b6151556020601f19601f840116016145af565b81815284602083860101111561516a57600080fd5b6117bf826020830160208701614218565b60006020828403121561518d57600080fd5b815167ffffffffffffffff808211156151a557600080fd5b90830190604082860312156151b957600080fd5b6151c1614569565b8251828111156151d057600080fd5b6151dc87828601615117565b8252506020830151828111156151f157600080fd5b6151fd87828601615117565b60208301525095945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156152a357601f1986840301895281516080815181865261524f8287018261423c565b9150508582015185820387870152615267828261423c565b91505060408083015186830382880152615281838261423c565b6060948501519790940196909652505098840198925090830190600101615229565b5090979650505050505050565b6020815261530160208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161531d60c08401826001600160a01b03169052565b5060408301516101808060e085015261533a6101a085018361423c565b91506060850151601f198086850301610100870152615359848361423c565b9350608087015191508086850301610120870152615377848361423c565b935060a087015191506153966101408701836001600160a01b03169052565b60c087015161016087015260e08701519150808685030183870152506153bc838261520c565b9695505050505050565b63ffffffff81811683821601908082111561505057615050614ea7565b6000602082840312156153f557600080fd5b6111ef82614e66565b815460ff81161515825261028082019061ffff600882901c8116602085015263ffffffff601883901c8116604086015261544560608601828560381c1663ffffffff169052565b61545c60808601828560581c1663ffffffff169052565b61547160a08601838560781c1661ffff169052565b61548860c08601828560881c1663ffffffff169052565b61549d60e08601838560a81c1661ffff169052565b6154b36101008601838560b81c1661ffff169052565b6154c96101208601838560c81c1661ffff169052565b6154e16101408601828560d81c1663ffffffff169052565b600186015463ffffffff82821616610160870152925067ffffffffffffffff602084901c8116610180870152915061552b6101a08601838560601c1667ffffffffffffffff169052565b6155436101c08601828560a01c1663ffffffff169052565b506155596101e0850160ff8460c01c1615159052565b601882901b6001600160e01b03191661020085015260028501546001600160a01b03811661022086015291506155a16102408501828460a01c1667ffffffffffffffff169052565b5050600383015461026083015292915050565b6102208101610f7d828461435a565b610140810161563082856001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b82516001600160a01b0390811660c08401526020840151811660e0840152604084015181166101008401526060840151166101208301526111ef565b6000808335601e1984360301811261568357600080fd5b830160208101925035905067ffffffffffffffff8111156156a357600080fd5b803603821315614e1557600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8183526000602080850194508260005b858110156157255781356157008161416a565b6001600160a01b031687528183013583880152604096870196909101906001016156ed565b509495945050505050565b600067ffffffffffffffff808516835260406020840152615751848561566c565b60a0604086015261576660e0860182846156b2565b915050615776602086018661566c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808785030160608801526157ac8483856156b2565b935060408801359250601e198836030183126157c757600080fd5b602092880192830192359150848211156157e057600080fd5b8160061b36038313156157f257600080fd5b808785030160808801526158078483856156dd565b94506158156060890161417f565b6001600160a01b03811660a08901529350615833608089018961566c565b94509250808786030160c088015250506140c18383836156b2565b60006020828403121561586057600080fd5b81516111ef8161427b565b600067ffffffffffffffff80831681810361588857615888614ea7565b6001019392505050565b60006001600160a01b03808916835260c060208401526158b560c084018961423c565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b6020815260006111ef602083018461520c565b6001600160e01b031981358181169160048510156159215780818660040360031b1b83161692505b505092915050565b6000808585111561593957600080fd5b8386111561594657600080fd5b5050820193919092039150565b60006040828403121561596557600080fd5b61596d614569565b82518152602083015161597f81614604565b60208201529392505050565b6000825161599d818460208701614218565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"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\":[{\"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\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"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\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainDynamicConfigUpdated\",\"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\"},{\"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\":\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"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\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"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\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"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\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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\":[{\"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\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.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: "0x6101406040523480156200001257600080fd5b50604051620071bf380380620071bf83398101604081905262000035916200146f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000214565b505085516001600160a01b031615905080620000e6575060208501516001600160401b0316155b80620000fd575060608501516001600160a01b0316155b8062000114575060808501516001600160a01b0316155b806200012b575060a08501516001600160a01b0316155b156200014a576040516306b7c75960e31b815260040160405180910390fd5b84516001600160a01b0390811660a090815260208701516001600160401b031660c05260408701516001600160601b031660809081526060880151831660e0528701518216610100528601511661012052620001a684620002bf565b620001b18362000482565b620001bc82620009c9565b60408051600080825260208201909252620002099183919062000202565b6040805180820190915260008082526020820152815260200190600190039081620001da5790505b5062000a95565b5050505050620018be565b336001600160a01b038216036200026e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b03161580620002e5575060608101516001600160a01b0316155b1562000304576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b039283166001600160a01b0319918216179091556020808401516003805491851691841691909117905560408085015160048054918616918516919091179055606080860151600580549187169190951617909355805160c0808201835260a080518716835290516001600160401b031693820193909352608080516001600160601b03168284015260e05186169482019490945261010051851693810193909352610120519093169082015290517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916200047791849082516001600160a01b0390811682526020808501516001600160401b0316818401526040808601516001600160601b03168185015260608087015184168186015260808088015185169086015260a0968701518416968501969096528451831660c085015290840151821660e084015283015181166101008301529190920151166101208201526101400190565b60405180910390a150565b60005b8151811015620009c5576000828281518110620004a657620004a6620015b5565b602002602001015190506000838381518110620004c757620004c7620015b5565b6020026020010151600001519050806001600160401b031660001480620004fe5750602082015161018001516001600160401b0316155b80620005245750602082015161020001516001600160e01b031916630a04b54b60e21b14155b156200054f5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b600060066000836001600160401b03166001600160401b03168152602001908152602001600020905060006040518060600160405280856020015181526020018360020160009054906101000a90046001600160401b03166001600160401b031681526020018360030154815250905080600001518260000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505081600301546000801b03620009205760c051604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f732160208201526001600160401b0392831691810191909152908416606082015230608082015260a00160408051601f1981840301815291815281516020909201919091208282018190526003840155516001600160401b038416907f26f8c55bd3f591fd6042c98ad4d707257cd565dc47609bfa3ba517400d0570449062000912908590620015cb565b60405180910390a2620009b5565b60208460200151610160015163ffffffff1610156200096d57602084015161016001516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000083565b826001600160401b03167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb8560200151604051620009ac919062001767565b60405180910390a25b5050505080600101905062000485565b5050565b60005b8151811015620009c5576000828281518110620009ed57620009ed620015b5565b6020026020010151600001519050600083838151811062000a125762000a12620015b5565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101620009cc565b60005b825181101562000d0257600083828151811062000ab95762000ab9620015b5565b6020026020010151905060008160000151905060005b82602001515181101562000cf35760008360200151828151811062000af85762000af8620015b5565b602002602001015160200151905060008460200151838151811062000b215762000b21620015b5565b60200260200101516000015190506020826080015163ffffffff16101562000b7a5760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000ce0908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000acf565b50505080600101905062000a98565b5060005b815181101562000dc857600082828151811062000d275762000d27620015b5565b6020026020010151600001519050600083838151811062000d4c5762000d4c620015b5565b6020908102919091018101518101516001600160401b03841660008181526008845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d06565b505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171562000e085762000e0862000dcd565b60405290565b60405161022081016001600160401b038111828210171562000e085762000e0862000dcd565b60405160c081016001600160401b038111828210171562000e085762000e0862000dcd565b604051601f8201601f191681016001600160401b038111828210171562000e845762000e8462000dcd565b604052919050565b80516001600160a01b038116811462000ea457600080fd5b919050565b80516001600160401b038116811462000ea457600080fd5b60006080828403121562000ed457600080fd5b604051608081016001600160401b038111828210171562000ef95762000ef962000dcd565b60405290508062000f0a8362000e8c565b815262000f1a6020840162000e8c565b602082015262000f2d6040840162000e8c565b604082015262000f406060840162000e8c565b60608201525092915050565b60006001600160401b0382111562000f685762000f6862000dcd565b5060051b60200190565b8051801515811462000ea457600080fd5b805161ffff8116811462000ea457600080fd5b805163ffffffff8116811462000ea457600080fd5b80516001600160e01b03198116811462000ea457600080fd5b600082601f83011262000fd657600080fd5b8151602062000fef62000fe98362000f4c565b62000e59565b82815261024092830285018201928282019190878511156200101057600080fd5b8387015b85811015620011d257808903828112156200102f5760008081fd5b6200103962000de3565b620010448362000ea9565b815261022080601f19840112156200105c5760008081fd5b6200106662000e0e565b92506200107588850162000f72565b835260406200108681860162000f83565b8985015260606200109981870162000f96565b8286015260809150620010ae82870162000f96565b9085015260a0620010c186820162000f96565b8286015260c09150620010d682870162000f83565b9085015260e0620010e986820162000f96565b828601526101009150620010ff82870162000f83565b908501526101206200111386820162000f83565b8286015261014091506200112982870162000f83565b908501526101606200113d86820162000f96565b8286015261018091506200115382870162000f96565b908501526101a06200116786820162000ea9565b828601526101c091506200117d82870162000ea9565b908501526101e06200119186820162000f96565b828601526102009150620011a782870162000f72565b90850152620011b885830162000fab565b908401525080870191909152845292840192810162001014565b5090979650505050505050565b600082601f830112620011f157600080fd5b815160206200120462000fe98362000f4c565b82815260069290921b840181019181810190868411156200122457600080fd5b8286015b848110156200127a5760408189031215620012435760008081fd5b6200124d62000de3565b620012588262000e8c565b81526200126785830162000ea9565b8186015283529183019160400162001228565b509695505050505050565b600082601f8301126200129757600080fd5b81516020620012aa62000fe98362000f4c565b82815260059290921b84018101918181019086841115620012ca57600080fd5b8286015b848110156200127a5780516001600160401b0380821115620012ef57600080fd5b908801906040601f19838c0381018213156200130a57600080fd5b6200131462000de3565b6200132189860162000ea9565b815282850151848111156200133557600080fd5b8086019550508c603f8601126200134b57600080fd5b8885015193506200136062000fe98562000f4c565b84815260e09094028501830193898101908e8611156200137f57600080fd5b958401955b858710156200145857868f0360e08112156200139f57600080fd5b620013a962000de3565b620013b48962000e8c565b815260c08683011215620013c757600080fd5b620013d162000e34565b9150620013e08d8a0162000f96565b8252620013ef878a0162000f96565b8d8301526200140160608a0162000f83565b878301526200141360808a0162000f96565b60608301526200142660a08a0162000f96565b60808301526200143960c08a0162000f72565b60a0830152808d0191909152825260e09690960195908a019062001384565b828b015250875250505092840192508301620012ce565b60008060008060008587036101a08112156200148a57600080fd5b60c08112156200149957600080fd5b50620014a462000e34565b620014af8762000e8c565b8152620014bf6020880162000ea9565b602082015260408701516001600160601b0381168114620014df57600080fd5b6040820152620014f26060880162000e8c565b6060820152620015056080880162000e8c565b60808201526200151860a0880162000e8c565b60a082015294506200152e8760c0880162000ec1565b6101408701519094506001600160401b03808211156200154d57600080fd5b6200155b89838a0162000fc4565b94506101608801519150808211156200157357600080fd5b6200158189838a01620011df565b93506101808801519150808211156200159957600080fd5b50620015a88882890162001285565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c811660408601526200161360608601828560381c1663ffffffff169052565b6200162b60808601828560581c1663ffffffff169052565b6200164160a08601838560781c1661ffff169052565b6200165960c08601828560881c1663ffffffff169052565b6200166f60e08601838560a81c1661ffff169052565b620016866101008601838560b81c1661ffff169052565b6200169d6101208601838560c81c1661ffff169052565b620016b66101408601828560d81c1663ffffffff169052565b600186015463ffffffff8282161661016087015292506001600160401b03602084901c81166101808701529150620016ff6101a08601838560601c166001600160401b03169052565b620017186101c08601828560a01c1663ffffffff169052565b5050620017306101e0840160ff8360c01c1615159052565b60181b6001600160e01b03191661020083015260028301546001600160401b03166102208301526003909201546102409091015290565b8151151581526102208101602083015162001788602084018261ffff169052565b506040830151620017a1604084018263ffffffff169052565b506060830151620017ba606084018263ffffffff169052565b506080830151620017d3608084018263ffffffff169052565b5060a0830151620017ea60a084018261ffff169052565b5060c08301516200180360c084018263ffffffff169052565b5060e08301516200181a60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b03908116918501919091526101a080860151909116908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b60805160a05160c05160e051610100516101205161584862001977600039600081816102da0152818161116101526125d50152600081816102ab015281816125ad015261341601526000818161027c015281816125830152612c8d0152600081816102180152818161251e01528181612a7a01526134a70152600081816101e9015281816124f901528181612f3f0152612fd10152600081816102480152818161255001528181613093015261310301526158486000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e9146108c4578063f2fde38b146108d7578063fbca3b74146108ea57600080fd5b8063a6f3ab6c1461089e578063ca643213146108b157600080fd5b80638da5cb5b116100b25780638da5cb5b146108675780639041be3d14610878578063a69c64c01461088b57600080fd5b806379ba5097146106fc57806382b49eb01461070457600080fd5b80633a019940116101245780636def4ce7116101095780636def4ce7146103b65780637437ff9f14610676578063770e2dc4146106e957600080fd5b80633a0199401461038157806348a98aa41461038b57600080fd5b8063061877e31461015657806306285c69146101a7578063181f5a771461031757806320487ded14610360575b600080fd5b61018961016436600461408c565b6001600160a01b031660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61030a6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161019e91906140a9565b6103536040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161019e9190614165565b61037361036e3660046141b1565b61090a565b60405190815260200161019e565b610389610f62565b005b61039e610399366004614201565b611126565b6040516001600160a01b03909116815260200161019e565b6106696103c436600461423a565b60408051610280810182526000606082018181526080830182905260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e083018290526102008301829052610220830182905261024083018290526102608301829052825260208201819052918101919091525067ffffffffffffffff908116600090815260066020908152604091829020825161028081018452815460ff80821615156060840190815261ffff6101008085048216608087015263ffffffff63010000008604811660a08801526701000000000000008604811660c08801526b0100000000000000000000008604811660e0808901919091526f010000000000000000000000000000008704841692880192909252710100000000000000000000000000000000008604811661012088015275010000000000000000000000000000000000000000008604831661014088015277010000000000000000000000000000000000000000000000860483166101608801527901000000000000000000000000000000000000000000000000008087049093166101808801527b0100000000000000000000000000000000000000000000000000000090950485166101a087015260018701548086166101c088015264010000000081048b166101e08801526c0100000000000000000000000081048b166102008801527401000000000000000000000000000000000000000081049095166102208701527801000000000000000000000000000000000000000000000000850490931615156102408601526001600160e01b0319930490911b919091166102608301528152600282015490941691840191909152600301549082015290565b60405161019e919061439d565b6106dc60408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526002546001600160a01b03908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161019e91906143d6565b6103896106f73660046145e6565b6111d5565b6103896111eb565b610807610712366004614201565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff9190911660009081526008602090815260408083206001600160a01b0394909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b60405161019e9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b6000546001600160a01b031661039e565b61018961088636600461423a565b6112b4565b610389610899366004614860565b6112e0565b6103896108ac36600461491e565b6112f4565b6103896108bf3660046149bb565b611305565b6103736108d2366004614bcb565b611316565b6103896108e536600461408c565b61178e565b6108fd6108f836600461423a565b61179f565b60405161019e9190614c37565b67ffffffffffffffff82166000908152600660205260408120805460ff1661096f576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6109a0846109806020860186614c84565b905061098f6040870187614cd2565b905061099b8780614c84565b6117d3565b60006007816109b5608087016060880161408c565b6001600160a01b03168152602081019190915260400160009081205467ffffffffffffffff169150819003610a32576109f4608085016060860161408c565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b60035460009081906001600160a01b031663ffdb4b37610a586080890160608a0161408c565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8a1660248201526044016040805180830381865afa158015610aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acf9190614d33565b90925090506000808080610ae660408b018b614cd2565b90501115610b2157610b158a610b0260808c0160608d0161408c565b87610b1060408e018e614cd2565b6118fb565b91945092509050610b58565b6001870154610b559074010000000000000000000000000000000000000000900463ffffffff16662386f26fc10000614d8c565b92505b865460009077010000000000000000000000000000000000000000000000900461ffff1615610bc157610bbe8b6dffffffffffffffffffffffffffff607088901c16610ba760208e018e614c84565b9050610bb660408f018f614cd2565b905086611cd7565b90505b875460009063ffffffff8516906f01000000000000000000000000000000900461ffff16610bf260208e018e614c84565b610bfd929150614d8c565b8a54610c1e91906b010000000000000000000000900463ffffffff16614da3565b610c289190614da3565b9050610ebb610c3a60808d018d614c84565b8b604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050611ddd565b51610ec69082614da3565b60018a01549091506000906c01000000000000000000000000900467ffffffffffffffff16610f05836dffffffffffffffffffffffffffff8a16614d8c565b610f0f9190614d8c565b90506001600160e01b0388168382610f3167ffffffffffffffff8d168a614d8c565b610f3b9190614da3565b610f459190614da3565b610f4f9190614db6565b9a50505050505050505050505b92915050565b600354604080517fcdc73d5100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163cdc73d5191600480830192869291908290030181865afa158015610fc4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fec9190810190614df1565b6005549091506001600160a01b031660005b825181101561112157600083828151811061101b5761101b614e80565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611089573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ad9190614eaf565b90508015611117576110c96001600160a01b0383168583611e98565b816001600160a01b0316846001600160a01b03167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161110e91815260200190565b60405180910390a35b5050600101610ffe565b505050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156111aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ce9190614ec8565b9392505050565b6111dd611f03565b6111e78282611f5f565b5050565b6001546001600160a01b031633146112455760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610966565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120600201549091610f5c91166001614ee5565b6112e8611f03565b6112f18161233f565b50565b6112fc611f03565b6112f18161241c565b61130d611f03565b6112f181612635565b67ffffffffffffffff841660009081526006602052604081208161133d8288888888612bda565b905060005b8160e001515181101561172a57600061135e6040890189614cd2565b8381811061136e5761136e614e80565b9050604002018036038101906113849190614f0d565b905080602001516000036113c4576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006113d48a8360000151611126565b90506001600160a01b038116158061148a57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015611464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114889190614f47565b155b156114cf5781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b6000816001600160a01b0316639a4575b96040518060a001604052808d80600001906114fb9190614c84565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff8f166020808301919091526001600160a01b03808e16604080850191909152918901516060840152885116608090920191909152516001600160e01b031960e084901b16815261158e9190600401614f64565b6000604051808303816000875af11580156115ad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115d59190810190615031565b90506020816020015151118015611636575067ffffffffffffffff8b16600090815260086020908152604080832086516001600160a01b0316845282529091205490820151516e01000000000000000000000000000090910463ffffffff16105b1561167b5782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b600186015481516116ac91790100000000000000000000000000000000000000000000000000900460e01b9061391d565b60408051608081019091526001600160a01b03831660a08201528060c081016040516020818303038152906040528152602001826000015181526020018260200151815260200184602001518152508560e00151858151811061171157611711614e80565b6020026020010181905250505050806001019050611342565b50611739818360030154613957565b81515260405167ffffffffffffffff8816907f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab2990611778908490615166565b60405180910390a251519150505b949350505050565b611796611f03565b6112f181613a39565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8516600090815260066020526040902080546301000000900463ffffffff1685111561184c5780546040517f86933789000000000000000000000000000000000000000000000000000000008152630100000090910463ffffffff16600482015260248101869052604401610966565b8054610100900461ffff16841115611890576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154604080516020601f86018190048102820181019092528481526118f392790100000000000000000000000000000000000000000000000000900460e01b91869086908190840183828082843760009201919091525061391d92505050565b505050505050565b6000808083815b81811015611cca57600087878381811061191e5761191e614e80565b9050604002018036038101906119349190614f0d565b905060006001600160a01b031661194f8c8360000151611126565b6001600160a01b03160361199d5780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b67ffffffffffffffff8b16600090815260086020908152604080832084516001600160a01b03168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052611b0b5767ffffffffffffffff8c1660009081526006602052604090208054611aab90790100000000000000000000000000000000000000000000000000900461ffff16662386f26fc10000614d8c565b611ab59089614da3565b8154909850611ae9907b01000000000000000000000000000000000000000000000000000000900463ffffffff168861527c565b6001820154909750611b019063ffffffff168761527c565b9550505050611cc2565b604081015160009061ffff1615611c125760008c6001600160a01b031684600001516001600160a01b031614611bca5760035484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015611b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc39190615299565b9050611bcd565b508a5b620186a0836040015161ffff16611bfa8660200151846001600160e01b0316613afa90919063ffffffff16565b611c049190614d8c565b611c0e9190614db6565b9150505b6060820151611c21908861527c565b9650816080015186611c33919061527c565b8251909650600090611c529063ffffffff16662386f26fc10000614d8c565b905080821015611c7157611c66818a614da3565b985050505050611cc2565b6000836020015163ffffffff16662386f26fc10000611c909190614d8c565b905080831115611cb057611ca4818b614da3565b99505050505050611cc2565b611cba838b614da3565b995050505050505b600101611902565b5050955095509592505050565b60008063ffffffff8316611cec60e086614d8c565b611cf8876101c0614da3565b611d029190614da3565b611d0c9190614da3565b67ffffffffffffffff8816600090815260066020526040812080549293509171010000000000000000000000000000000000810463ffffffff1690611d6e907501000000000000000000000000000000000000000000900461ffff1685614d8c565b611d789190614da3565b825490915077010000000000000000000000000000000000000000000000900461ffff16611db66dffffffffffffffffffffffffffff8a1683614d8c565b611dc09190614d8c565b611dd090655af3107a4000614d8c565b9998505050505050505050565b60408051808201909152600080825260208201526000611e038585856101800151613b22565b9050826060015163ffffffff1681600001511115611e4d576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015611e6157508060200151155b15611786576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611121908490613c9b565b6000546001600160a01b03163314611f5d5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610966565b565b60005b8251811015612268576000838281518110611f7f57611f7f614e80565b6020026020010151905060008160000151905060005b82602001515181101561225a57600083602001518281518110611fba57611fba614e80565b6020026020010151602001519050600084602001518381518110611fe057611fe0614e80565b60200260200101516000015190506020826080015163ffffffff1610156120505760808201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015263ffffffff9091166024820152604401610966565b67ffffffffffffffff841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612248908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101611f95565b505050806001019050611f62565b5060005b815181101561112157600082828151811061228957612289614e80565b602002602001015160000151905060008383815181106122ab576122ab614e80565b60209081029190910181015181015167ffffffffffffffff841660008181526008845260408082206001600160a01b038516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010161226c565b60005b81518110156111e757600082828151811061235f5761235f614e80565b6020026020010151600001519050600083838151811061238157612381614e80565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101612342565b60208101516001600160a01b03161580612441575060608101516001600160a01b0316155b15612478576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556020808401516003805484169185169190911790556040808501516004805485169186169190911790556060808601516005805490951690861617909355805160c0810182527f0000000000000000000000000000000000000000000000000000000000000000851681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16928101929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16828201527f00000000000000000000000000000000000000000000000000000000000000008416928201929092527f0000000000000000000000000000000000000000000000000000000000000000831660808201527f000000000000000000000000000000000000000000000000000000000000000090921660a0830152517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa9161262a9184906152b4565b60405180910390a150565b60005b81518110156111e757600082828151811061265557612655614e80565b60200260200101519050600083838151811061267357612673614e80565b60200260200101516000015190508067ffffffffffffffff16600014806126ab57506020820151610180015167ffffffffffffffff16155b806126e95750602082015161020001516001600160e01b0319167f2812d52c0000000000000000000000000000000000000000000000000000000014155b1561272c576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610966565b6000600660008367ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020905060006040518060600160405280856020015181526020018360020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020018360030154815250905080600001518260000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505081600301546000801b03612b2057604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908416606082015230608082015260a00160408051601f19818403018152918152815160209092019190912082820181905260038401555167ffffffffffffffff8416907f26f8c55bd3f591fd6042c98ad4d707257cd565dc47609bfa3ba517400d05704490612b1390859061535d565b60405180910390a2612bcb565b60208460200151610160015163ffffffff161015612b8457602084015161016001516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610966565b8267ffffffffffffffff167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb8560200151604051612bc291906154f1565b60405180910390a25b50505050806001019050612638565b604080516101a08101825260006101008201818152610120830182905261014083018290526101608301829052610180830182905282526020820181905260609282018390528282018390526080820183905260a0820181905260c082015260e08101919091526040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608086901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d009190614f47565b15612d43576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610966565b6001600160a01b038216612d83576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546001600160a01b03163314612dc7576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460ff16612e0e576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610966565b6000612e1d6040860186614cd2565b9150612e3f905086612e326020880188614c84565b90508361099b8980614c84565b8015612f33576004546001600160a01b03168015612f31576040517fe0a0e5060000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063e0a0e50690612e9e908a908a906004016155c4565b600060405180830381600087803b158015612eb857600080fd5b505af1925050508015612ec9575060015b612f31573d808015612ef7576040519150601f19603f3d011682016040523d82523d6000602084013e612efc565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016109669190614165565b505b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612f6f608088016060890161408c565b6001600160a01b031603612f8457508361303f565b6003546001600160a01b03166241e5be612fa46080890160608a0161408c565b60405160e083901b6001600160e01b03191681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa158015613018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303c9190614eaf565b90505b61304f608087016060880161408c565b6001600160a01b03167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8260405161308991815260200190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16811115613130576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018290526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610966565b60006133c66131426080890189614c84565b8b600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050611ddd565b60200151613486576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff891660048201526001600160a01b0386811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af115801561345f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348391906156e2565b90505b604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528b811661014085015260028d0180549394938493926101608501929187916134f691166156ff565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020018567ffffffffffffffff168152508152602001876001600160a01b0316815260200189806020019061355c9190614c84565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016135a08a80614c84565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161386e6135ea60808c018c614c84565b8e600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b6001600160e01b0319166001600160e01b03191681525050613d80565b815260200161388360808b0160608c0161408c565b6001600160a01b031681526020018881526020018567ffffffffffffffff8111156138b0576138b0614412565b60405190808252806020026020018201604052801561390c57816020015b6138f96040518060800160405280606081526020016060815260200160608152602001600081525090565b8152602001906001900390816138ce5790505b5090529a9950505050505050505050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b03198316016111e75761112181613e00565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c0015160405160200161399996959493929190615726565b604051602081830303815290604052805190602001208560400151805190602001208660e001516040516020016139d0919061577a565b60408051601f1981840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b336001600160a01b03821603613a915760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610966565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a7640000613b18836001600160e01b038616614d8c565b6111ce9190614db6565b60408051808201909152600080825260208201526000839003613b6357506040805180820190915267ffffffffffffffff82168152600060208201526111ce565b6000613b6f848661578d565b90506000613b8085600481896157bd565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b031982167fe7e230f00000000000000000000000000000000000000000000000000000000001613c055780806020019051810190613bfc91906157e7565b925050506111ce565b7f6859a837000000000000000000000000000000000000000000000000000000006001600160e01b0319831601613c6957604051806040016040528082806020019051810190613c559190614eaf565b8152600060209091015292506111ce915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613cf0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e5b9092919063ffffffff16565b8051909150156111215780806020019051810190613d0e9190614f47565b6111215760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610966565b6102008101516060907fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b0319821601613df857613dc5858585611ddd565b604080518251602080830191909152909201511515908201526060016040516020818303038152906040529150506111ce565b509392505050565b60008151602014613e3f57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109669190614165565b610f5c82806020019051810190613e569190614eaf565b613e6a565b60606117868484600085613ed7565b60006001600160a01b03821180613e82575061040082105b15613ed35760408051602081018490520160408051601f19818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261096691600401614165565b5090565b606082471015613f4f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610966565b600080866001600160a01b03168587604051613f6b919061581f565b60006040518083038185875af1925050503d8060008114613fa8576040519150601f19603f3d011682016040523d82523d6000602084013e613fad565b606091505b5091509150613fbe87838387613fc9565b979650505050505050565b60608315614038578251600003614031576001600160a01b0385163b6140315760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610966565b5081611786565b611786838381511561404d5781518083602001fd5b8060405162461bcd60e51b81526004016109669190614165565b6001600160a01b03811681146112f157600080fd5b803561408781614067565b919050565b60006020828403121561409e57600080fd5b81356111ce81614067565b60c08101610f5c82846001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60005b83811015614130578181015183820152602001614118565b50506000910152565b60008151808452614151816020860160208601614115565b601f01601f19169290920160200192915050565b6020815260006111ce6020830184614139565b67ffffffffffffffff811681146112f157600080fd5b803561408781614178565b600060a082840312156141ab57600080fd5b50919050565b600080604083850312156141c457600080fd5b82356141cf81614178565b9150602083013567ffffffffffffffff8111156141eb57600080fd5b6141f785828601614199565b9150509250929050565b6000806040838503121561421457600080fd5b823561421f81614178565b9150602083013561422f81614067565b809150509250929050565b60006020828403121561424c57600080fd5b81356111ce81614178565b8051151582526020810151614272602084018261ffff169052565b50604081015161428a604084018263ffffffff169052565b5060608101516142a2606084018263ffffffff169052565b5060808101516142ba608084018263ffffffff169052565b5060a08101516142d060a084018261ffff169052565b5060c08101516142e860c084018263ffffffff169052565b5060e08101516142fe60e084018261ffff169052565b506101008181015161ffff9081169184019190915261012080830151909116908301526101408082015163ffffffff90811691840191909152610160808301518216908401526101808083015167ffffffffffffffff908116918501919091526101a080840151909116908401526101c080830151909116908301526101e080820151151590830152610200908101516001600160e01b031916910152565b6000610260820190506143b1828451614257565b602083015167ffffffffffffffff166102208301526040909201516102409091015290565b60808101610f5c828480516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561446457614464614412565b60405290565b60405160c0810167ffffffffffffffff8111828210171561446457614464614412565b604051610220810167ffffffffffffffff8111828210171561446457614464614412565b604051601f8201601f1916810167ffffffffffffffff811182821017156144da576144da614412565b604052919050565b600067ffffffffffffffff8211156144fc576144fc614412565b5060051b60200190565b803563ffffffff8116811461408757600080fd5b803561ffff8116811461408757600080fd5b80151581146112f157600080fd5b80356140878161452c565b600082601f83011261455657600080fd5b8135602061456b614566836144e2565b6144b1565b82815260069290921b8401810191818101908684111561458a57600080fd5b8286015b848110156145db57604081890312156145a75760008081fd5b6145af614441565b81356145ba81614178565b8152818501356145c981614067565b8186015283529183019160400161458e565b509695505050505050565b600080604083850312156145f957600080fd5b67ffffffffffffffff8335111561460f57600080fd5b83601f84358501011261462157600080fd5b61463161456684358501356144e2565b8335840180358083526020808401939260059290921b9091010186101561465757600080fd5b602085358601015b85358601803560051b0160200181101561482a5767ffffffffffffffff8135111561468957600080fd5b6040601f198235883589010189030112156146a357600080fd5b6146ab614441565b6146be6020833589358a01010135614178565b863587018235016020810135825267ffffffffffffffff60409091013511156146e657600080fd5b86358701823501604081013501603f8101891361470257600080fd5b61471261456660208301356144e2565b602082810135808352908201919060e00283016040018b101561473457600080fd5b604083015b604060e06020860135028501018110156148115760e0818d03121561475d57600080fd5b614765614441565b61476f8235614067565b8135815260c0601f19838f0301121561478757600080fd5b61478f61446a565b61479b60208401614506565b81526147a960408401614506565b60208201526147ba6060840161451a565b60408201526147cb60808401614506565b60608201526147dc60a08401614506565b60808201526147ee60c084013561452c565b60c083013560a0820152602082810191909152908452929092019160e001614739565b506020848101919091529286525050928301920161465f565b5092505067ffffffffffffffff6020840135111561484757600080fd5b6148578460208501358501614545565b90509250929050565b6000602080838503121561487357600080fd5b823567ffffffffffffffff81111561488a57600080fd5b8301601f8101851361489b57600080fd5b80356148a9614566826144e2565b81815260069190911b820183019083810190878311156148c857600080fd5b928401925b82841015613fbe57604084890312156148e65760008081fd5b6148ee614441565b84356148f981614067565b81528486013561490881614178565b81870152825260409390930192908401906148cd565b60006080828403121561493057600080fd5b6040516080810181811067ffffffffffffffff8211171561495357614953614412565b604052823561496181614067565b8152602083013561497181614067565b6020820152604083013561498481614067565b6040820152606083013561499781614067565b60608201529392505050565b80356001600160e01b03198116811461408757600080fd5b600060208083850312156149ce57600080fd5b823567ffffffffffffffff8111156149e557600080fd5b8301601f810185136149f657600080fd5b8035614a04614566826144e2565b8181526102409182028301840191848201919088841115614a2457600080fd5b938501935b83851015614bbf5784890381811215614a425760008081fd5b614a4a614441565b8635614a5581614178565b8152610220601f198301811315614a6c5760008081fd5b614a7461448d565b9250614a8189890161453a565b83526040614a90818a0161451a565b8a8501526060614aa1818b01614506565b8286015260809150614ab4828b01614506565b9085015260a0614ac58a8201614506565b8286015260c09150614ad8828b0161451a565b9085015260e0614ae98a8201614506565b828601526101009150614afd828b0161451a565b90850152610120614b0f8a820161451a565b828601526101409150614b23828b0161451a565b90850152610160614b358a8201614506565b828601526101809150614b49828b01614506565b908501526101a0614b5b8a820161418e565b828601526101c09150614b6f828b0161418e565b908501526101e0614b818a8201614506565b828601526102009150614b95828b0161453a565b90850152614ba48983016149a3565b90840152508088019190915283529384019391850191614a29565b50979650505050505050565b60008060008060808587031215614be157600080fd5b8435614bec81614178565b9350602085013567ffffffffffffffff811115614c0857600080fd5b614c1487828801614199565b935050604085013591506060850135614c2c81614067565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b81811015614c785783516001600160a01b031683529284019291840191600101614c53565b50909695505050505050565b6000808335601e19843603018112614c9b57600080fd5b83018035915067ffffffffffffffff821115614cb657600080fd5b602001915036819003821315614ccb57600080fd5b9250929050565b6000808335601e19843603018112614ce957600080fd5b83018035915067ffffffffffffffff821115614d0457600080fd5b6020019150600681901b3603821315614ccb57600080fd5b80516001600160e01b038116811461408757600080fd5b60008060408385031215614d4657600080fd5b614d4f83614d1c565b915061485760208401614d1c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f5c57610f5c614d5d565b80820180821115610f5c57610f5c614d5d565b600082614dec577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020808385031215614e0457600080fd5b825167ffffffffffffffff811115614e1b57600080fd5b8301601f81018513614e2c57600080fd5b8051614e3a614566826144e2565b81815260059190911b82018301908381019087831115614e5957600080fd5b928401925b82841015613fbe578351614e7181614067565b82529284019290840190614e5e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215614ec157600080fd5b5051919050565b600060208284031215614eda57600080fd5b81516111ce81614067565b67ffffffffffffffff818116838216019080821115614f0657614f06614d5d565b5092915050565b600060408284031215614f1f57600080fd5b614f27614441565b8235614f3281614067565b81526020928301359281019290925250919050565b600060208284031215614f5957600080fd5b81516111ce8161452c565b602081526000825160a06020840152614f8060c0840182614139565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f830112614fde57600080fd5b815167ffffffffffffffff811115614ff857614ff8614412565b61500b6020601f19601f840116016144b1565b81815284602083860101111561502057600080fd5b611786826020830160208701614115565b60006020828403121561504357600080fd5b815167ffffffffffffffff8082111561505b57600080fd5b908301906040828603121561506f57600080fd5b615077614441565b82518281111561508657600080fd5b61509287828601614fcd565b8252506020830151828111156150a757600080fd5b6150b387828601614fcd565b60208301525095945050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561515957601f1986840301895281516080815181865261510582870182614139565b915050858201518582038787015261511d8282614139565b915050604080830151868303828801526151378382614139565b60609485015197909401969096525050988401989250908301906001016150df565b5090979650505050505050565b602081526151b760208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516151d360c08401826001600160a01b03169052565b5060408301516101808060e08501526151f06101a0850183614139565b91506060850151601f19808685030161010087015261520f8483614139565b935060808701519150808685030161012087015261522d8483614139565b935060a0870151915061524c6101408701836001600160a01b03169052565b60c087015161016087015260e087015191508086850301838701525061527283826150c2565b9695505050505050565b63ffffffff818116838216019080821115614f0657614f06614d5d565b6000602082840312156152ab57600080fd5b6111ce82614d1c565b610140810161532182856001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b82516001600160a01b0390811660c08401526020840151811660e0840152604084015181166101008401526060840151166101208301526111ce565b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c811660408601526153a460608601828560381c1663ffffffff169052565b6153bb60808601828560581c1663ffffffff169052565b6153d060a08601838560781c1661ffff169052565b6153e760c08601828560881c1663ffffffff169052565b6153fc60e08601838560a81c1661ffff169052565b6154126101008601838560b81c1661ffff169052565b6154286101208601838560c81c1661ffff169052565b6154406101408601828560d81c1663ffffffff169052565b600186015463ffffffff82821616610160870152925067ffffffffffffffff602084901c8116610180870152915061548a6101a08601838560601c1667ffffffffffffffff169052565b6154a26101c08601828560a01c1663ffffffff169052565b50506154b96101e0840160ff8360c01c1615159052565b60181b6001600160e01b031916610200830152600283015467ffffffffffffffff166102208301526003909201546102409091015290565b6102208101610f5c8284614257565b6000808335601e1984360301811261551757600080fd5b830160208101925035905067ffffffffffffffff81111561553757600080fd5b803603821315614ccb57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8183526000602080850194508260005b858110156155b957813561559481614067565b6001600160a01b03168752818301358388015260409687019690910190600101615581565b509495945050505050565b600067ffffffffffffffff8085168352604060208401526155e58485615500565b60a060408601526155fa60e086018284615546565b91505061560a6020860186615500565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152615640848385615546565b935060408801359250601e1988360301831261565b57600080fd5b6020928801928301923591508482111561567457600080fd5b8160061b360383131561568657600080fd5b8087850301608088015261569b848385615571565b94506156a96060890161407c565b6001600160a01b03811660a089015293506156c76080890189615500565b94509250808786030160c08801525050613fbe838383615546565b6000602082840312156156f457600080fd5b81516111ce81614178565b600067ffffffffffffffff80831681810361571c5761571c614d5d565b6001019392505050565b60006001600160a01b03808916835260c0602084015261574960c0840189614139565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b6020815260006111ce60208301846150c2565b6001600160e01b031981358181169160048510156157b55780818660040360031b1b83161692505b505092915050565b600080858511156157cd57600080fd5b838611156157da57600080fd5b5050820193919092039150565b6000604082840312156157f957600080fd5b615801614441565b8251815260208301516158138161452c565b60208201529392505050565b60008251615831818460208701614115565b919091019291505056fea164736f6c6343000818000a", } var EVM2EVMMultiOnRampABI = EVM2EVMMultiOnRampMetaData.ABI @@ -2228,7 +2226,7 @@ func (EVM2EVMMultiOnRampConfigSet) Topic() common.Hash { } func (EVM2EVMMultiOnRampDestChainAdded) Topic() common.Hash { - return common.HexToHash("0x66951b52bb33e5d462611460f7aa53069005b173e002d9224c15fb986e4ead8f") + return common.HexToHash("0x26f8c55bd3f591fd6042c98ad4d707257cd565dc47609bfa3ba517400d057044") } func (EVM2EVMMultiOnRampDestChainDynamicConfigUpdated) 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 a8a838e6fd..117d6ca710 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 @@ -10,7 +10,7 @@ commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../ commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 2ab5cd4acb0c0b7087397d0c99e928119ef9e174bfd55628e6b2daf14f2da1fe -evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin e304765672aeab78529edc35f6ee44779c098643fe3a7b4f3c0f33a9493016ac +evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 85698e5c4c6cb10f4f969cc1740b9ff094c469530e0a763670cf388311f00619 evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b6132cb22370d62b1b20174bbe832ec87df61f6ab65f7fe2515733bdd10a30f5 evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 383e9930fbc1b7fbb6554cc8857229d207fd6742e87c7fb1a37002347e8de8e2 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin c65c226e1e4d38414bd4a1b76fc8aca3cb3dd98df61268424c44564f455d3752