From 52676f13cd629f575e69df0ce3b802e8d4097626 Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:10:06 +0100 Subject: [PATCH 01/55] TT-1832 Add slack notification for nightly run with detailed flaky test summary (#15446) * Update slack notification for flaky test detector * Bump flakeguard and support shuffle flag * bump flakeguard * update notification * Fix * Add separate job for nightly flakeguard workflow * trigger * fix * Fix * Fix codeowners issue * fix * fix * Fix * Fix codeowners issue * revert: fail test * Fix all tests path * fix notification * Fix format * Revert "revert: fail test" This reverts commit 6abd3796e8919be3094e47f51bc6d8140fca0d90. * debug * bump * Fix * bump * fix * fix * bump * revert * Fix * bump flakeguard to fix codeowners * bump * fix * Bump flakeguard * fail test on purpose * fix * Fix * Fix * fix * fix lint --- .github/workflows/flakeguard-nightly.yml | 2 +- .github/workflows/flakeguard-on-demand.yml | 2 +- .github/workflows/flakeguard.yml | 98 ++++++++++++++++++---- 3 files changed, 86 insertions(+), 16 deletions(-) diff --git a/.github/workflows/flakeguard-nightly.yml b/.github/workflows/flakeguard-nightly.yml index a4f3ab31f18..37c00fa0a8f 100644 --- a/.github/workflows/flakeguard-nightly.yml +++ b/.github/workflows/flakeguard-nightly.yml @@ -12,7 +12,7 @@ jobs: uses: ./.github/workflows/flakeguard.yml with: repoUrl: 'https://github.com/smartcontractkit/chainlink' - baseRef: 'origin/develop' + headRef: 'develop' projectPath: '.' maxPassRatio: '1.0' runAllTests: true diff --git a/.github/workflows/flakeguard-on-demand.yml b/.github/workflows/flakeguard-on-demand.yml index 9a3aff67d45..fe972894594 100644 --- a/.github/workflows/flakeguard-on-demand.yml +++ b/.github/workflows/flakeguard-on-demand.yml @@ -65,7 +65,7 @@ jobs: runAllTests: ${{ inputs.runAllTests }} findByTestFilesDiff: ${{ inputs.findByTestFilesDiff }} findByAffectedPackages: ${{ inputs.findByAffectedPackages }} - slackNotificationAfterTestsChannelId: ${{ inputs.slack_notification_after_tests_channel_id }} + slackNotificationAfterTestsChannelId: ${{ inputs.slack_notification_after_tests_channel_id || 'C07TRF65CNS' }} #flaky-test-detector-notifications extraArgs: ${{ inputs.extraArgs }} secrets: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/flakeguard.yml b/.github/workflows/flakeguard.yml index 1ba3c840499..ecc56e2f291 100644 --- a/.github/workflows/flakeguard.yml +++ b/.github/workflows/flakeguard.yml @@ -13,7 +13,7 @@ on: description: 'The path to the project to run the flaky test detection.' default: '.' baseRef: - required: true + required: false type: string description: 'The base reference or branch to compare changes for detecting flaky tests.' headRef: @@ -66,6 +66,7 @@ env: DEFAULT_RUNNER: 'ubuntu-latest' # The default runner to use for running tests. UPLOAD_ALL_TEST_RESULTS: ${{ fromJson(inputs.extraArgs)['upload_all_test_results'] || 'false' }} # Whether to upload all test results as artifacts. PRINT_FAILED_TESTS: ${{ fromJson(inputs.extraArgs)['print_failed_tests'] || 'false' }} # Whether to print failed tests in the GitHub console. + jobs: get-tests: @@ -100,7 +101,7 @@ jobs: - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@f03577def97a20a38c0e1de1cbe7fc98d416dd86 # flakguard@0.1.0 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9e40f2765df01f20b3bf53f0fb3ead920e3a1f4a # flakguard@0.1.0 - name: Find new or updated test packages if: ${{ inputs.runAllTests == false }} @@ -259,7 +260,7 @@ jobs: - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@f03577def97a20a38c0e1de1cbe7fc98d416dd86 # flakguard@0.1.0 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9e40f2765df01f20b3bf53f0fb3ead920e3a1f4a # flakguard@0.1.0 - name: Run tests with flakeguard shell: bash @@ -306,7 +307,7 @@ jobs: - name: Install flakeguard shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@f03577def97a20a38c0e1de1cbe7fc98d416dd86 # flakguard@0.1.0 + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9e40f2765df01f20b3bf53f0fb3ead920e3a1f4a # flakguard@0.1.0 - name: Set combined test results id: set_test_results @@ -341,10 +342,27 @@ jobs: fi echo "Failed tests count: $FAILED_TESTS_COUNT" echo "failed_tests_count=$FAILED_TESTS_COUNT" >> "$GITHUB_OUTPUT" + + # Calculate failed ratio (failed / non-failed tests ratio in %) + if [ "$ALL_TESTS_COUNT" -gt 0 ]; then + NON_FAILED_COUNT=$((ALL_TESTS_COUNT - FAILED_TESTS_COUNT)) + + if [ "$NON_FAILED_COUNT" -gt 0 ]; then + FAILED_RATIO=$(awk "BEGIN {printf \"%.2f\", ($FAILED_TESTS_COUNT / $NON_FAILED_COUNT) * 100}") + else + FAILED_RATIO=0 + fi + else + NON_FAILED_COUNT=0 + FAILED_RATIO=0 + fi + echo "Failed tests ratio: $FAILED_RATIO%" + echo "failed_ratio=$FAILED_RATIO" >> "$GITHUB_OUTPUT" else echo "No test results directory found." echo "all_tests_count=0" >> "$GITHUB_OUTPUT" echo "failed_tests_count=0" >> "$GITHUB_OUTPUT" + echo "failed_ratio=0" >> "$GITHUB_OUTPUT" fi - name: Tests Summary @@ -368,7 +386,7 @@ jobs: with: path: all_tests.md name: all-summary.md - retention-days: 7 + retention-days: 90 - name: Upload All Test Results as Artifact if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} @@ -376,7 +394,7 @@ jobs: with: path: all_tests.json name: all-test-results.json - retention-days: 7 + retention-days: 90 - name: Upload Failed Tests Summary as Artifact if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} @@ -384,7 +402,7 @@ jobs: with: path: failed_tests.md name: failed-summary.md - retention-days: 7 + retention-days: 90 - name: Upload Failed Test Results as Artifact if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} @@ -392,7 +410,7 @@ jobs: with: path: failed_tests.json name: failed-test-results.json - retention-days: 7 + retention-days: 90 - name: Upload Failed Test Logs as Artifact if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} @@ -400,7 +418,7 @@ jobs: with: path: failed_test_logs.json name: failed-test-logs.json - retention-days: 7 + retention-days: 90 - name: Upload All Test Results as Artifact if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 && env.UPLOAD_ALL_TEST_RESULTS == 'true' }} @@ -408,7 +426,7 @@ jobs: with: path: all_tests.json name: all-test-results.json - retention-days: 7 + retention-days: 90 - name: Post comment on PR if flaky tests found if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 && github.event_name == 'pull_request' }} @@ -427,9 +445,61 @@ jobs: body: commentBody }); - - name: Send Slack message + - name: Send Slack message for failed tests + if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} + uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + with: + channel-id: ${{ inputs.slackNotificationAfterTestsChannelId }} + payload: | + { + "attachments": [ + { + "color": "#C62828", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Flaky Test Detector for `${{ steps.set_project_path_pretty.outputs.path }}` project - ${{ contains(join(needs.*.result, ','), 'failure') && 'Failed :x:' || contains(join(needs.*.result, ','), 'cancelled') && 'Was cancelled :warning:' || 'Passed :white_check_mark:' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ inputs.runAllTests == true && format('Ran all tests for `{0}` branch.', inputs.headRef) || format('Ran changed tests between `{0}` and `{1}` (`{2}`).', inputs.baseRef, needs.get-tests.outputs.git_head_short_sha, env.GIT_HEAD_REF) }}" + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "Total Failed Tests: ${{ steps.set_test_results.outputs.failed_tests_count }}" + }, + { + "type": "mrkdwn", + "text": "Failed to Non-Failed Ratio: ${{ steps.set_test_results.outputs.failed_ratio }}%" + } + ] + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" + } + } + ] + } + ] + } + + - name: Send general Slack message uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} + if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJson(steps.set_test_results.outputs.failed_tests_count) == 0 && fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} id: slack env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} @@ -452,14 +522,14 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "Ran changed tests between `${{ inputs.baseRef }}` and `${{ needs.get-tests.outputs.git_head_short_sha }}` (`${{ env.GIT_HEAD_REF }}`)." + "text": "${{ inputs.runAllTests == true && format('Ran all tests for `{0}` branch.', env.GIT_HEAD_REF) || format('Ran changed tests between `{0}` and `{1}` (`{2}`).', inputs.baseRef, needs.get-tests.outputs.git_head_short_sha, env.GIT_HEAD_REF) }}" } }, { "type": "section", "text": { "type": "mrkdwn", - "text": "${{ format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" + "text": "${{ inputs.runAllTests == true && format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details>', github.server_url, github.repository, github.run_id) || format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" } } ] From c7cb608c3eedcf72e4cfad8eb8ccdbcf511ffa9f Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Wed, 4 Dec 2024 06:36:04 -0800 Subject: [PATCH 02/55] [KS-590][bugfix] Auto-approval of workflow deletion - use correct ID (#15499) --- core/services/feeds/service.go | 16 +++++++++++----- core/services/feeds/service_test.go | 9 +++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 852bab6c63a..04ab747c9ab 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -529,12 +529,18 @@ func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, er return proposal.ID, nil } if job.WorkflowSpecID != nil { // this is a Workflow job - specID := int64(*job.WorkflowSpecID) - if err := s.CancelSpec(ctx, proposal.ID); err != nil { - logger.Errorw("Failed to auto-cancel workflow spec", "id", specID, "err", err, "name", job.Name) - return 0, fmt.Errorf("failed to auto-cancel workflow spec %d: %w", specID, err) + jobSpecID := int64(*job.WorkflowSpecID) + jpSpec, err2 := s.orm.GetApprovedSpec(ctx, proposal.ID) + if err2 != nil { + logger.Errorw("GetApprovedSpec failed - no approved specs to cancel?", "id", proposal.ID, "err", err2, "name", job.Name) + // return success if there are no approved specs to cancel + return proposal.ID, nil } - logger.Infow("Successfully auto-cancelled a workflow spec", "id", specID) + if err := s.CancelSpec(ctx, jpSpec.ID); err != nil { + logger.Errorw("Failed to auto-cancel workflow spec", "jobProposalID", proposal.ID, "jobProposalSpecID", jpSpec.ID, "jobSpecID", jobSpecID, "err", err, "name", job.Name) + return 0, fmt.Errorf("failed to auto-cancel workflow spec (job proposal spec ID: %d): %w", jpSpec.ID, err) + } + logger.Infow("Successfully auto-cancelled a workflow spec", "jobProposalID", proposal.ID, "jobProposalSpecID", jpSpec.ID, "jobSpecID", jobSpecID, "name", job.Name) } return proposal.ID, nil diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index c513c05562d..d449d585401 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -1341,7 +1341,7 @@ func Test_Service_DeleteJob(t *testing.T) { ID: 1, WorkflowSpecID: &wfSpecID, } - spec = &feeds.JobProposalSpec{ + jobProposalSpec = &feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusApproved, JobProposalID: approved.ID, @@ -1415,13 +1415,14 @@ func Test_Service_DeleteJob(t *testing.T) { svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(nil) svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(workflowJob, nil) + svc.orm.On("GetApprovedSpec", mock.Anything, approved.ID).Return(jobProposalSpec, nil) // mocks for CancelSpec() - svc.orm.On("GetSpec", mock.Anything, approved.ID).Return(spec, nil) + svc.orm.On("GetSpec", mock.Anything, jobProposalSpec.ID).Return(jobProposalSpec, nil) svc.orm.On("GetJobProposal", mock.Anything, approved.ID).Return(&approved, nil) svc.connMgr.On("GetClient", mock.Anything).Return(svc.fmsClient, nil) - svc.orm.On("CancelSpec", mock.Anything, approved.ID).Return(nil) + svc.orm.On("CancelSpec", mock.Anything, jobProposalSpec.ID).Return(nil) svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(workflowJob, nil) svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, workflowJob.ID).Return(nil) @@ -1429,7 +1430,7 @@ func Test_Service_DeleteJob(t *testing.T) { mock.MatchedBy(func(ctx context.Context) bool { return true }), &proto.CancelledJobRequest{ Uuid: approved.RemoteUUID.String(), - Version: int64(spec.Version), + Version: int64(jobProposalSpec.Version), }, ).Return(&proto.CancelledJobResponse{}, nil) svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) From 22c6cf7320d6bfb16e8132729ddd2efa3cbd2bb7 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 4 Dec 2024 15:34:52 +0000 Subject: [PATCH 03/55] [CAPPL-324] Fix panic when fetching binary (#15490) * Fix panic when fetching the binary * [CAPPL-324] Fix panic when fetching the binary * [fix] Various Gateway bugs - Stop logging out the request/response body - Add a timeout when fetching the request - Add the method in various places where it was missing * Fix test * Linting * Review comments --- .../webapi/outgoing_connector_handler.go | 22 ++- core/services/chainlink/application.go | 28 +--- core/services/gateway/connector/connector.go | 2 +- .../connector/mocks/gateway_connector.go | 137 ++++++++++++++++++ .../gateway/handlers/capabilities/handler.go | 5 +- core/services/gateway/network/httpclient.go | 2 +- .../workflows/syncer/workflow_syncer_test.go | 2 +- core/services/workflows/syncer/fetcher.go | 112 +++++++++++--- .../services/workflows/syncer/fetcher_test.go | 40 ++--- .../workflows/syncer/workflow_registry.go | 4 + .../syncer/workflow_registry_test.go | 2 +- 11 files changed, 283 insertions(+), 73 deletions(-) diff --git a/core/capabilities/webapi/outgoing_connector_handler.go b/core/capabilities/webapi/outgoing_connector_handler.go index b00b82b2bd0..d18ee971d1a 100644 --- a/core/capabilities/webapi/outgoing_connector_handler.go +++ b/core/capabilities/webapi/outgoing_connector_handler.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" @@ -19,6 +20,7 @@ import ( var _ connector.GatewayConnectorHandler = &OutgoingConnectorHandler{} type OutgoingConnectorHandler struct { + services.StateMachine gc connector.GatewayConnector method string lggr logger.Logger @@ -98,7 +100,7 @@ func (c *OutgoingConnectorHandler) HandleGatewayMessage(ctx context.Context, gat } l.Debugw("handling gateway request") switch body.Method { - case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction, capabilities.MethodWorkflowSyncer: body := &msg.Body var payload capabilities.Response err := json.Unmarshal(body.Payload, &payload) @@ -125,16 +127,28 @@ func (c *OutgoingConnectorHandler) HandleGatewayMessage(ctx context.Context, gat } func (c *OutgoingConnectorHandler) Start(ctx context.Context) error { - return c.gc.AddHandler([]string{c.method}, c) + return c.StartOnce("OutgoingConnectorHandler", func() error { + return c.gc.AddHandler([]string{c.method}, c) + }) } func (c *OutgoingConnectorHandler) Close() error { - return nil + return c.StopOnce("OutgoingConnectorHandler", func() error { + return nil + }) +} + +func (c *OutgoingConnectorHandler) HealthReport() map[string]error { + return map[string]error{c.Name(): c.Healthy()} +} + +func (c *OutgoingConnectorHandler) Name() string { + return c.lggr.Name() } func validMethod(method string) bool { switch method { - case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction, capabilities.MethodWorkflowSyncer: return true default: return false diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index ac0d28760eb..863c5d915e9 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -34,7 +34,6 @@ import ( gatewayconnector "github.com/smartcontractkit/chainlink/v2/core/capabilities/gateway_connector" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" "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" @@ -50,8 +49,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/feeds" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/gateway" - capabilities2 "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - common2 "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" "github.com/smartcontractkit/chainlink/v2/core/services/headreporter" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" @@ -303,30 +300,13 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("expected 1 key, got %d", len(keys)) } - connector := gatewayConnectorWrapper.GetGatewayConnector() - webAPILggr := globalLogger.Named("WebAPITarget") - - webAPIConfig := webapi.ServiceConfig{ - RateLimiter: common2.RateLimiterConfig{ - GlobalRPS: 100.0, - GlobalBurst: 100, - PerSenderRPS: 100.0, - PerSenderBurst: 100, - }, - } - - outgoingConnectorHandler, err := webapi.NewOutgoingConnectorHandler(connector, - webAPIConfig, - capabilities2.MethodWebAPITarget, webAPILggr) - if err != nil { - return nil, fmt.Errorf("could not create outgoing connector handler: %w", err) - } + fetcher := syncer.NewFetcherService(globalLogger, gatewayConnectorWrapper) eventHandler := syncer.NewEventHandler(globalLogger, syncer.NewWorkflowRegistryDS(opts.DS, globalLogger), - syncer.NewFetcherFunc(globalLogger, outgoingConnectorHandler), workflowstore.NewDBStore(opts.DS, globalLogger, clockwork.NewRealClock()), opts.CapabilitiesRegistry, + fetcher.Fetch, workflowstore.NewDBStore(opts.DS, globalLogger, clockwork.NewRealClock()), opts.CapabilitiesRegistry, custmsg.NewLabeler(), clockwork.NewRealClock(), keys[0]) - loader := syncer.NewWorkflowRegistryContractLoader(cfg.Capabilities().WorkflowRegistry().Address(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + loader := syncer.NewWorkflowRegistryContractLoader(globalLogger, cfg.Capabilities().WorkflowRegistry().Address(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { return relayer.NewContractReader(ctx, bytes) }, eventHandler) @@ -338,7 +318,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { QueryCount: 100, }, eventHandler, loader, workflowDonNotifier) - srvcs = append(srvcs, wfSyncer) + srvcs = append(srvcs, fetcher, wfSyncer) } } } else { diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go index 18d34007c56..a8d356478e9 100644 --- a/core/services/gateway/connector/connector.go +++ b/core/services/gateway/connector/connector.go @@ -23,7 +23,7 @@ import ( // GatewayConnector is a component run by Nodes to connect to a set of Gateways. type GatewayConnector interface { - job.ServiceCtx + services.Service network.ConnectionInitiator AddHandler(methods []string, handler GatewayConnectorHandler) error diff --git a/core/services/gateway/connector/mocks/gateway_connector.go b/core/services/gateway/connector/mocks/gateway_connector.go index f9951af98e9..183fc949cd5 100644 --- a/core/services/gateway/connector/mocks/gateway_connector.go +++ b/core/services/gateway/connector/mocks/gateway_connector.go @@ -269,6 +269,98 @@ func (_c *GatewayConnector_GatewayIDs_Call) RunAndReturn(run func() []string) *G return _c } +// HealthReport provides a mock function with given fields: +func (_m *GatewayConnector) HealthReport() map[string]error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HealthReport") + } + + var r0 map[string]error + if rf, ok := ret.Get(0).(func() map[string]error); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]error) + } + } + + return r0 +} + +// GatewayConnector_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' +type GatewayConnector_HealthReport_Call struct { + *mock.Call +} + +// HealthReport is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) HealthReport() *GatewayConnector_HealthReport_Call { + return &GatewayConnector_HealthReport_Call{Call: _e.mock.On("HealthReport")} +} + +func (_c *GatewayConnector_HealthReport_Call) Run(run func()) *GatewayConnector_HealthReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_HealthReport_Call) Return(_a0 map[string]error) *GatewayConnector_HealthReport_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_HealthReport_Call) RunAndReturn(run func() map[string]error) *GatewayConnector_HealthReport_Call { + _c.Call.Return(run) + return _c +} + +// Name provides a mock function with given fields: +func (_m *GatewayConnector) Name() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Name") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GatewayConnector_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' +type GatewayConnector_Name_Call struct { + *mock.Call +} + +// Name is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) Name() *GatewayConnector_Name_Call { + return &GatewayConnector_Name_Call{Call: _e.mock.On("Name")} +} + +func (_c *GatewayConnector_Name_Call) Run(run func()) *GatewayConnector_Name_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_Name_Call) Return(_a0 string) *GatewayConnector_Name_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_Name_Call) RunAndReturn(run func() string) *GatewayConnector_Name_Call { + _c.Call.Return(run) + return _c +} + // NewAuthHeader provides a mock function with given fields: _a0 func (_m *GatewayConnector) NewAuthHeader(_a0 *url.URL) ([]byte, error) { ret := _m.Called(_a0) @@ -327,6 +419,51 @@ func (_c *GatewayConnector_NewAuthHeader_Call) RunAndReturn(run func(*url.URL) ( return _c } +// Ready provides a mock function with given fields: +func (_m *GatewayConnector) Ready() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Ready") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GatewayConnector_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' +type GatewayConnector_Ready_Call struct { + *mock.Call +} + +// Ready is a helper method to define mock.On call +func (_e *GatewayConnector_Expecter) Ready() *GatewayConnector_Ready_Call { + return &GatewayConnector_Ready_Call{Call: _e.mock.On("Ready")} +} + +func (_c *GatewayConnector_Ready_Call) Run(run func()) *GatewayConnector_Ready_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GatewayConnector_Ready_Call) Return(_a0 error) *GatewayConnector_Ready_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GatewayConnector_Ready_Call) RunAndReturn(run func() error) *GatewayConnector_Ready_Call { + _c.Call.Return(run) + return _c +} + // SendToGateway provides a mock function with given fields: ctx, gatewayId, msg func (_m *GatewayConnector) SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error { ret := _m.Called(ctx, gatewayId, msg) diff --git a/core/services/gateway/handlers/capabilities/handler.go b/core/services/gateway/handlers/capabilities/handler.go index 90bc2065edd..e1bdfdf8441 100644 --- a/core/services/gateway/handlers/capabilities/handler.go +++ b/core/services/gateway/handlers/capabilities/handler.go @@ -146,7 +146,8 @@ func (h *handler) handleWebAPIOutgoingMessage(ctx context.Context, msg *api.Mess newCtx := context.WithoutCancel(ctx) newCtx, cancel := context.WithTimeout(newCtx, timeout) defer cancel() - l := h.lggr.With("url", payload.URL, "messageId", msg.Body.MessageId, "method", payload.Method) + l := h.lggr.With("url", payload.URL, "messageId", msg.Body.MessageId, "method", payload.Method, "timeout", payload.TimeoutMs) + l.Debug("Sending request to client") respMsg, err := h.sendHTTPMessageToClient(newCtx, req, msg) if err != nil { l.Errorw("error while sending HTTP request to external endpoint", "err", err) @@ -187,7 +188,7 @@ func (h *handler) HandleNodeMessage(ctx context.Context, msg *api.Message, nodeA switch msg.Body.Method { case MethodWebAPITrigger: return h.handleWebAPITriggerMessage(ctx, msg, nodeAddr) - case MethodWebAPITarget, MethodComputeAction: + case MethodWebAPITarget, MethodComputeAction, MethodWorkflowSyncer: return h.handleWebAPIOutgoingMessage(ctx, msg, nodeAddr) default: return fmt.Errorf("unsupported method: %s", msg.Body.Method) diff --git a/core/services/gateway/network/httpclient.go b/core/services/gateway/network/httpclient.go index 4aecaaed3cd..52130c8d069 100644 --- a/core/services/gateway/network/httpclient.go +++ b/core/services/gateway/network/httpclient.go @@ -78,7 +78,7 @@ func (c *httpClient) Send(ctx context.Context, req HTTPRequest) (*HTTPResponse, // joining them to a single string in case array size is greater than 1 headers[k] = strings.Join(v, ",") } - c.lggr.Debugw("received HTTP response", "statusCode", resp.StatusCode, "body", string(body), "url", req.URL, "headers", headers) + c.lggr.Debugw("received HTTP response", "statusCode", resp.StatusCode, "url", req.URL, "headers", headers) return &HTTPResponse{ Headers: headers, diff --git a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go index cf2fb59a93b..28c5a28b303 100644 --- a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go +++ b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go @@ -98,7 +98,7 @@ func Test_InitialStateSync(t *testing.T) { } testEventHandler := newTestEvtHandler() - loader := syncer.NewWorkflowRegistryContractLoader(wfRegistryAddr.Hex(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + loader := syncer.NewWorkflowRegistryContractLoader(lggr, wfRegistryAddr.Hex(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { return backendTH.NewContractReader(ctx, t, bytes) }, testEventHandler) diff --git a/core/services/workflows/syncer/fetcher.go b/core/services/workflows/syncer/fetcher.go index bebdfb0519e..357f7518635 100644 --- a/core/services/workflows/syncer/fetcher.go +++ b/core/services/workflows/syncer/fetcher.go @@ -2,41 +2,113 @@ package syncer import ( "context" + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" "net/http" "strings" + "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" ) -func NewFetcherFunc( - lggr logger.Logger, - och *webapi.OutgoingConnectorHandler) FetcherFunc { - return func(ctx context.Context, url string) ([]byte, error) { - payloadBytes, err := json.Marshal(ghcapabilities.Request{ - URL: url, - Method: http.MethodGet, - }) - if err != nil { - return nil, fmt.Errorf("failed to marshal fetch request: %w", err) - } +const ( + defaultFetchTimeoutMs = 20_000 +) - messageID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, url}, "/") - resp, err := och.HandleSingleNodeRequest(ctx, messageID, payloadBytes) - if err != nil { - return nil, err +type FetcherService struct { + services.StateMachine + lggr logger.Logger + och *webapi.OutgoingConnectorHandler + wrapper gatewayConnector +} + +type gatewayConnector interface { + GetGatewayConnector() connector.GatewayConnector +} + +func NewFetcherService(lggr logger.Logger, wrapper gatewayConnector) *FetcherService { + return &FetcherService{ + lggr: lggr.Named("FetcherService"), + wrapper: wrapper, + } +} + +func (s *FetcherService) Start(ctx context.Context) error { + return s.StartOnce("FetcherService", func() error { + connector := s.wrapper.GetGatewayConnector() + + outgoingConnectorLggr := s.lggr.Named("WorkflowSyncer") + + webAPIConfig := webapi.ServiceConfig{ + RateLimiter: common.RateLimiterConfig{ + GlobalRPS: 100.0, + GlobalBurst: 100, + PerSenderRPS: 100.0, + PerSenderBurst: 100, + }, } - lggr.Debugw("received gateway response", "resp", resp) - var payload ghcapabilities.Response - err = json.Unmarshal(resp.Body.Payload, &payload) + och, err := webapi.NewOutgoingConnectorHandler(connector, + webAPIConfig, + capabilities.MethodWorkflowSyncer, outgoingConnectorLggr) if err != nil { - return nil, err + return fmt.Errorf("could not create outgoing connector handler: %w", err) } - return payload.Body, nil + s.och = och + return och.Start(ctx) + }) +} + +func (s *FetcherService) Close() error { + return s.StopOnce("FetcherService", func() error { + return s.och.Close() + }) +} + +func (s *FetcherService) HealthReport() map[string]error { + return map[string]error{s.Name(): s.Healthy()} +} + +func (s *FetcherService) Name() string { + return s.lggr.Name() +} + +func hash(url string) string { + h := sha256.New() + h.Write([]byte(url)) + return hex.EncodeToString(h.Sum(nil)) +} + +func (s *FetcherService) Fetch(ctx context.Context, url string) ([]byte, error) { + payloadBytes, err := json.Marshal(ghcapabilities.Request{ + URL: url, + Method: http.MethodGet, + TimeoutMs: defaultFetchTimeoutMs, + }) + if err != nil { + return nil, fmt.Errorf("failed to marshal fetch request: %w", err) + } + + messageID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") + resp, err := s.och.HandleSingleNodeRequest(ctx, messageID, payloadBytes) + if err != nil { + return nil, err } + + s.lggr.Debugw("received gateway response") + var payload ghcapabilities.Response + err = json.Unmarshal(resp.Body.Payload, &payload) + if err != nil { + return nil, err + } + + return payload.Body, nil } diff --git a/core/services/workflows/syncer/fetcher_test.go b/core/services/workflows/syncer/fetcher_test.go index 4ed228c6a51..8e3e58fba0d 100644 --- a/core/services/workflows/syncer/fetcher_test.go +++ b/core/services/workflows/syncer/fetcher_test.go @@ -9,46 +9,48 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" ) -func TestNewFetcherFunc(t *testing.T) { +type wrapper struct { + c connector.GatewayConnector +} + +func (w *wrapper) GetGatewayConnector() connector.GatewayConnector { + return w.c +} + +func TestNewFetcherService(t *testing.T) { ctx := context.Background() lggr := logger.TestLogger(t) - config := webapi.ServiceConfig{ - RateLimiter: common.RateLimiterConfig{ - GlobalRPS: 100.0, - GlobalBurst: 100, - PerSenderRPS: 100.0, - PerSenderBurst: 100, - }, - } - connector := gcmocks.NewGatewayConnector(t) - och, err := webapi.NewOutgoingConnectorHandler(connector, config, ghcapabilities.MethodComputeAction, lggr) - require.NoError(t, err) + wrapper := &wrapper{c: connector} url := "http://example.com" - msgID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, url}, "/") + msgID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") t.Run("OK-valid_request", func(t *testing.T) { + connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) + + fetcher := NewFetcherService(lggr, wrapper) + require.NoError(t, fetcher.Start(ctx)) + defer fetcher.Close() + gatewayResp := gatewayResponse(t, msgID) connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { - och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) + fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) }).Return(nil).Times(1) connector.EXPECT().DonID().Return("don-id") connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) - fetcher := NewFetcherFunc(lggr, och) - - payload, err := fetcher(ctx, url) + payload, err := fetcher.Fetch(ctx, url) require.NoError(t, err) expectedPayload := []byte("response body") diff --git a/core/services/workflows/syncer/workflow_registry.go b/core/services/workflows/syncer/workflow_registry.go index b33645cdb9e..6fc319da76b 100644 --- a/core/services/workflows/syncer/workflow_registry.go +++ b/core/services/workflows/syncer/workflow_registry.go @@ -556,17 +556,20 @@ func (r workflowAsEvent) GetData() any { } type workflowRegistryContractLoader struct { + lggr logger.Logger workflowRegistryAddress string newContractReaderFn newContractReaderFn handler evtHandler } func NewWorkflowRegistryContractLoader( + lggr logger.Logger, workflowRegistryAddress string, newContractReaderFn newContractReaderFn, handler evtHandler, ) *workflowRegistryContractLoader { return &workflowRegistryContractLoader{ + lggr: lggr.Named("WorkflowRegistryContractLoader"), workflowRegistryAddress: workflowRegistryAddress, newContractReaderFn: newContractReaderFn, handler: handler, @@ -624,6 +627,7 @@ func (l *workflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don return nil, fmt.Errorf("failed to get workflow metadata for don %w", err) } + l.lggr.Debugw("Rehydrating existing workflows", "len", len(workflows.WorkflowMetadataList)) for _, workflow := range workflows.WorkflowMetadataList { if err = l.handler.Handle(ctx, workflowAsEvent{ Data: workflow, diff --git a/core/services/workflows/syncer/workflow_registry_test.go b/core/services/workflows/syncer/workflow_registry_test.go index 0cccb405710..8a7c3bb0a7c 100644 --- a/core/services/workflows/syncer/workflow_registry_test.go +++ b/core/services/workflows/syncer/workflow_registry_test.go @@ -72,7 +72,7 @@ func Test_Workflow_Registry_Syncer(t *testing.T) { handler = NewEventHandler(lggr, orm, gateway, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) - loader = NewWorkflowRegistryContractLoader(contractAddress, func(ctx context.Context, bytes []byte) (ContractReader, error) { + loader = NewWorkflowRegistryContractLoader(lggr, contractAddress, func(ctx context.Context, bytes []byte) (ContractReader, error) { return reader, nil }, handler) From c1ee7ab715b524df6b580593e18f51637bd1500d Mon Sep 17 00:00:00 2001 From: Suryansh <39276431+0xsuryansh@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:21:59 +0530 Subject: [PATCH 04/55] CCIP-4359 fee quoter supports interface for keystone (#15448) * fix: enforce supports interface from IReceiver.sol and impliment in FeeQuoter.sol * fix: enforce supports interface from IReceiver.sol and impliment in FeeQuoter.sol * Update gethwrappers * CCIP-4359 changeset + minor fixes and wrappers * snapshot update * [Bot] Update changeset file with jira issues * lint fix * chore: import arrangement and additional comments * fix : comment in IReceiver * fix : comment in KeystoneFeedsPermissionHandler * fmt * add fee_quoter_interface * add fee_quoter_interface * remove incorrectly added mock interface * add mock interface * add fee_quoter_interface.go * added test with Keystone Forwarder * update cod cov ignore for ccip * cleanup: removed newline * update coverage * Revert "update cod cov ignore for ccip" This reverts commit 4a626109030230481f7e6f74d0ac45847110a0a4. * update lcov_prine to exclude keystone contract in coverage for CCIP * Revert "update lcov_prine to exclude keystone contract in coverage for CCIP" This reverts commit 5a0d65029b71a8d4ee5dc19e44a134ac963078fe. * remove keystone test setup dependency * chore: update test name according to style guide * update snapshot * Revert "Revert "update lcov_prine to exclude keystone contract in coverage for CCIP"" This reverts commit 2c8646184da37dcaae0c1143237f10e698269a26. --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/.changeset/tender-lemons-punch.md | 9 + contracts/gas-snapshots/ccip.gas-snapshot | 317 +++++++++--------- contracts/scripts/lcov_prune | 1 + contracts/src/v0.8/ccip/FeeQuoter.sol | 9 + .../test/feeQuoter/FeeQuoter.onReport.t.sol | 84 +++-- .../FeeQuoter.supportsInterface.t.sol | 18 + .../v0.8/keystone/KeystoneFeedsConsumer.sol | 4 +- .../KeystoneFeedsPermissionHandler.sol | 10 +- .../v0.8/keystone/interfaces/IReceiver.sol | 5 +- .../test/mocks/MaliciousReportReceiver.sol | 2 +- .../test/mocks/MaliciousRevertingReceiver.sol | 2 +- .../src/v0.8/keystone/test/mocks/Receiver.sol | 4 +- .../ccip/generated/fee_quoter/fee_quoter.go | 28 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- .../ccip/mocks/fee_quoter_interface.go | 57 ++++ 15 files changed, 344 insertions(+), 208 deletions(-) create mode 100644 contracts/.changeset/tender-lemons-punch.md create mode 100644 contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol diff --git a/contracts/.changeset/tender-lemons-punch.md b/contracts/.changeset/tender-lemons-punch.md new file mode 100644 index 00000000000..cac2e7ea0cf --- /dev/null +++ b/contracts/.changeset/tender-lemons-punch.md @@ -0,0 +1,9 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Add supportsInterface to FeeQuoter for Keystone + +PR issue: CCIP-4359 + +Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index cfa764656a4..ab4adc29a08 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -20,7 +20,7 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27346) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54878) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244496) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24223) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2077691) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2077779) CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners_Success() (gas: 332619) CCIPHome__validateConfig:test__validateConfigSmallerFChain_Success() (gas: 458568) CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 289191) @@ -68,7 +68,7 @@ CCIPHome_setCandidate:test_setCandidate_success() (gas: 1365439) CCIPHome_supportsInterface:test_supportsInterface_success() (gas: 9885) DefensiveExampleTest:test_HappyPath_Success() (gas: 200540) DefensiveExampleTest:test_Recovery() (gas: 425013) -E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512323) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512389) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96980) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49812) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17479) @@ -119,114 +119,113 @@ FactoryBurnMintERC20_mint:test_SenderNotMinter_Reverts() (gas: 11405) FactoryBurnMintERC20_supportsInterface:test_SupportsInterface_Success() (gas: 11538) FactoryBurnMintERC20_transfer:test_InvalidAddress_Reverts() (gas: 10701) FactoryBurnMintERC20_transfer:test_Transfer_Success() (gas: 42482) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16824) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16737) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16791) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 41195) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput_Success() (gas: 12541) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 140643) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 162508) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12241) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11564) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54904) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45323) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12456) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 88930) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13324) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17413) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12327) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106573) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110923) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110998) -FeeQuoter_constructor:test_Setup_Success() (gas: 4974931) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16846) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16759) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16813) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 41239) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput_Success() (gas: 12563) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 140709) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 162719) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12263) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11476) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54860) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45257) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12368) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 89062) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13346) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17435) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12349) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106632) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110982) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111057) +FeeQuoter_constructor:test_Setup_Success() (gas: 5011219) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68416) FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29300) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 96323) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14835) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20944) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 96433) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14857) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20988) FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 73071) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 26476) -FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled_Success() (gas: 112021) +FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled_Success() (gas: 112065) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16184) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 109131) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 68015) -FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent_Success() (gas: 33463) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78498) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 37372) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35151) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28241) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96218) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20702) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28049) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28094) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40887) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29801) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 109175) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 68059) +FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent_Success() (gas: 33529) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78516) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 37307) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35086) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28176) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96089) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20615) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27984) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28029) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40822) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29736) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18465) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 83208) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53548) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239604) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 83340) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53570) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239736) FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22668) FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29966) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100417) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143112) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143246) FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21280) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 114464) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 114510) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 23495) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63843) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1897830) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1897788) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1877907) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1897562) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1897766) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1897578) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 65210) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 65090) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58872) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1897204) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61821) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116926) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14160) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1895881) -FeeQuoter_onReport:test_OnReport_StaleUpdate_SkipPriceUpdate_Success() (gas: 43936) -FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23657) -FeeQuoter_onReport:test_onReport_Success() (gas: 80700) -FeeQuoter_onReport:test_onReport_TokenNotSupported_Revert() (gas: 23024) -FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 27202) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17448) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21620) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18680) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18220) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18534) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18657) -FeeQuoter_processMessageArgs:test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() (gas: 21454) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44930) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19986) -FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20383) -FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17954) -FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 123251) -FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42192) -FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28658) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29999) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76449) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28256) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26115) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19573) -FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12176) -FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23917) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28604) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74711) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145804) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52421) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 66335) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63909) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1897852) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1897810) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1877929) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1897584) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1897788) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1897600) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 65232) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 65112) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58894) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1897226) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61843) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116970) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14182) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1895903) +FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52614) +FeeQuoter_onReport:test_onReport() (gas: 89071) +FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122700) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17381) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21553) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18613) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18153) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18467) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18590) +FeeQuoter_processMessageArgs:test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() (gas: 21476) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44974) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 20008) +FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20405) +FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17976) +FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 123405) +FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42236) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28702) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 30021) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76515) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28300) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26159) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19595) +FeeQuoter_supportsInterface:test_SupportsInterface_Success() (gas: 13263) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12198) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23872) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28648) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74816) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145691) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52443) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 66423) FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 20124) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 93475) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 53098) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 93563) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 53142) FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12431) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10688) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4035395) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10884) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6819) -FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6545) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10710) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4057945) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10906) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6841) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6567) HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 176837) HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity_Success() (gas: 166986) HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism_Success() (gas: 135860) @@ -283,27 +282,27 @@ MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2093583) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30794) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 48169) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15907) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17602) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21630) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17624) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21652) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14636) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210571) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58451) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210637) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58473) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17791) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45202) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46470) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76911) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308951) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50636) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 51287) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46514) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76999) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 309039) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50680) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 51331) MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19375) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15914) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210291) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60244) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210357) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60266) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 47025) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48261) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77918) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308897) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52406) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48305) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 78006) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308985) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52450) MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 10967) MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19190) MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10642) @@ -358,10 +357,10 @@ NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 25 NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 220615) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 60497) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152941) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 166101) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 195828) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 139098) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 105168) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 166167) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 195938) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 139164) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 105212) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates_success() (gas: 123604) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43403) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64752) @@ -389,26 +388,26 @@ OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187974) OffRamp_batchExecute:test_SingleReport_Success() (gas: 156406) OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545037) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10600) -OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92744) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92766) OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63432) OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 69993) OffRamp_commit:test_InvalidInterval_Revert() (gas: 66119) OffRamp_commit:test_InvalidRootRevert() (gas: 65214) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6648767) -OffRamp_commit:test_NoConfig_Revert() (gas: 6232185) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112985) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121175) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112917) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355254) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164263) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6648811) +OffRamp_commit:test_NoConfig_Revert() (gas: 6232229) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113007) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121197) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112939) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355298) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164285) OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141269) OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 148268) OffRamp_commit:test_RootWithRMNDisabled_success() (gas: 153986) OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 61681) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232354) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125230) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232398) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125252) OffRamp_commit:test_Unhealthy_Revert() (gas: 60482) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206800) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206844) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 53621) OffRamp_constructor:test_Constructor_Success() (gas: 6194282) OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136585) @@ -421,12 +420,12 @@ OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) OffRamp_execute:test_LargeBatch_Success() (gas: 3376243) OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 371146) OffRamp_execute:test_MultipleReports_Success() (gas: 298685) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7056935) -OffRamp_execute:test_NoConfig_Revert() (gas: 6281405) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7056957) +OffRamp_execute:test_NoConfig_Revert() (gas: 6281427) OffRamp_execute:test_NonArray_Revert() (gas: 27680) OffRamp_execute:test_SingleReport_Success() (gas: 175664) OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147820) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6948577) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6948599) OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 56135) OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20463) @@ -508,32 +507,32 @@ OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Rever OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98066) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93146) OnRamp_constructor:test_Constructor_Success() (gas: 2647459) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115388) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146256) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145831) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144036) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146028) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145426) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140709) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38504) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115432) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146300) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145875) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144080) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146072) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145470) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140731) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38526) OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143112) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36589) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36611) OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36493) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18290) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38412) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23629) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186583) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 213012) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147026) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161215) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3963660) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186715) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 213144) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147070) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161303) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3963792) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24015) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75832) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75854) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38588) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281463) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281529) OnRamp_getFee:test_EmptyMessage_Success() (gas: 98692) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65453) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87185) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65475) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87119) OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35166) OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113865) OnRamp_getFee:test_Unhealthy_Revert() (gas: 17040) @@ -546,11 +545,11 @@ OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (g OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13264) OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56440) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 125901) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 172858) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 172880) PingPong_setOutOfOrderExecution:test_OutOfOrderExecution_Success() (gas: 20283) PingPong_setPaused:test_Pausing_Success() (gas: 17738) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 151971) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 177586) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 151993) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 177608) RMNHome_getConfigDigests:test_getConfigDigests_success() (gas: 1079685) RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23879) RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 10597) @@ -619,20 +618,20 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89591) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10750087) Router_applyRampUpdates:test_OnRampDisable() (gas: 56445) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12414) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 131425) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 221688) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 131447) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 221710) Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 71858) Router_ccipSend:test_InvalidMsgValue() (gas: 32411) Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 69524) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 193296) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 193318) Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 61550) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 191900) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 226539) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 191922) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 226583) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 25056) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 45056) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 194209) -Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 140674) -Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 230872) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 194231) +Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 140696) +Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 230894) Router_constructor:test_Constructor_Success() (gas: 13222) Router_getArmProxy:test_getArmProxy() (gas: 10573) Router_getFee:test_GetFeeSupportedChain_Success() (gas: 51934) diff --git a/contracts/scripts/lcov_prune b/contracts/scripts/lcov_prune index cce524185ae..9d5d592c646 100755 --- a/contracts/scripts/lcov_prune +++ b/contracts/scripts/lcov_prune @@ -30,6 +30,7 @@ exclusion_list_ccip=( "src/v0.8/ConfirmedOwnerWithProposal.sol" "src/v0.8/tests/MockV3Aggregator.sol" "src/v0.8/ccip/applications/CCIPClientExample.sol" + "src/v0.8/keystone/*" ) exclusion_list_shared=( diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index d8a04e359b1..58261eff499 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -15,6 +15,7 @@ import {Internal} from "./libraries/Internal.sol"; import {Pool} from "./libraries/Pool.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; +import {IERC165} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice The FeeQuoter contract responsibility is to: @@ -493,6 +494,14 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } } + /// @notice Signals which version of the pool interface is supported + function supportsInterface( + bytes4 interfaceId + ) public pure override returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IFeeQuoter).interfaceId + || interfaceId == type(ITypeAndVersion).interfaceId || interfaceId == type(IERC165).interfaceId; + } + /// @inheritdoc IReceiver /// @notice Handles the report containing price feeds and updates the internal price storage. /// @dev This function is called to process incoming price feed data. diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol index aba4e178865..ebd800b7d48 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol @@ -2,30 +2,42 @@ pragma solidity 0.8.24; import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; + +import {KeystoneForwarder} from "../../../keystone/KeystoneForwarder.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_onReport is FeeQuoterSetup { - address internal constant FORWARDER_1 = address(0x1); - address internal constant WORKFLOW_OWNER_1 = address(0x3); - bytes10 internal constant WORKFLOW_NAME_1 = "workflow1"; - bytes2 internal constant REPORT_NAME_1 = "01"; + bytes32 internal constant EXECUTION_ID = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; + address internal constant TRANSMITTER = address(50); + bytes32 internal constant WORKFLOW_ID_1 = hex"6d795f6964000000000000000000000000000000000000000000000000000000"; + address internal constant WORKFLOW_OWNER_1 = address(51); + bytes10 internal constant WORKFLOW_NAME_1 = hex"000000000000DEADBEEF"; + bytes2 internal constant REPORT_NAME_1 = hex"0001"; address internal s_onReportTestToken1; address internal s_onReportTestToken2; + bytes public encodedPermissionsMetadata; + KeystoneForwarder internal s_forwarder; function setUp() public virtual override { super.setUp(); + + s_forwarder = new KeystoneForwarder(); + s_onReportTestToken1 = s_sourceTokens[0]; s_onReportTestToken2 = _deploySourceToken("onReportTestToken2", 0, 20); KeystoneFeedsPermissionHandler.Permission[] memory permissions = new KeystoneFeedsPermissionHandler.Permission[](1); permissions[0] = KeystoneFeedsPermissionHandler.Permission({ - forwarder: FORWARDER_1, + forwarder: address(s_forwarder), workflowOwner: WORKFLOW_OWNER_1, workflowName: WORKFLOW_NAME_1, reportName: REPORT_NAME_1, isAllowed: true }); + + encodedPermissionsMetadata = abi.encodePacked(WORKFLOW_ID_1, WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ sourceToken: s_onReportTestToken1, @@ -39,10 +51,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); } - function test_onReport_Success() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - + function test_onReport() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](2); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); @@ -56,7 +65,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken2, expectedStoredToken2Price, block.timestamp); - changePrank(FORWARDER_1); + changePrank(address(s_forwarder)); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).value, expectedStoredToken1Price); @@ -66,11 +75,34 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).timestamp, report[1].timestamp); } - function test_OnReport_StaleUpdate_SkipPriceUpdate_Success() public { - //Creating a correct report - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + function test_onReport_withKeystoneForwarderContract() public { + FeeQuoter.ReceivedCCIPFeedReport[] memory priceReportRaw = new FeeQuoter.ReceivedCCIPFeedReport[](2); + priceReportRaw[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + priceReportRaw[1] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); + + uint224 expectedStoredToken1Price = s_feeQuoter.calculateRebasedValue(18, 18, priceReportRaw[0].price); + uint224 expectedStoredToken2Price = s_feeQuoter.calculateRebasedValue(18, 20, priceReportRaw[1].price); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken1, expectedStoredToken1Price, block.timestamp); + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken2, expectedStoredToken2Price, block.timestamp); + changePrank(address(s_forwarder)); + s_forwarder.route( + EXECUTION_ID, TRANSMITTER, address(s_feeQuoter), encodedPermissionsMetadata, abi.encode(priceReportRaw) + ); + + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[0].token).value, expectedStoredToken1Price); + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[0].token).timestamp, priceReportRaw[0].timestamp); + + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[1].token).value, expectedStoredToken2Price); + vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[1].token).timestamp, priceReportRaw[1].timestamp); + } + + function test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); @@ -80,7 +112,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken1, expectedStoredTokenPrice, block.timestamp); - changePrank(FORWARDER_1); + changePrank(address(s_forwarder)); //setting the correct price and time with the correct report s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); @@ -100,22 +132,18 @@ contract FeeQuoter_onReport is FeeQuoterSetup { assertEq(vm.getRecordedLogs().length, 0); } - function test_onReport_TokenNotSupported_Revert() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + function test_onReport_RevertWhen_TokenNotSupported() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); // Revert due to token config not being set with the isEnabled flag vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); - vm.startPrank(FORWARDER_1); + changePrank(address(s_forwarder)); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } - function test_onReport_InvalidForwarder_Reverts() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + function test_onReport_RevertWhen_InvalidForwarder() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); @@ -132,16 +160,4 @@ contract FeeQuoter_onReport is FeeQuoterSetup { changePrank(STRANGER); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } - - function test_onReport_UnsupportedToken_Reverts() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); - report[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); - changePrank(FORWARDER_1); - s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol new file mode 100644 index 00000000000..a9352392301 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IReceiver} from "../../../keystone/interfaces/IReceiver.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; +import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; + +contract FeeQuoter_supportsInterface is FeeQuoterSetup { + function test_SupportsInterface_Success() public view { + assertTrue(s_feeQuoter.supportsInterface(type(IReceiver).interfaceId)); + assertTrue(s_feeQuoter.supportsInterface(type(ITypeAndVersion).interfaceId)); + assertTrue(s_feeQuoter.supportsInterface(type(IFeeQuoter).interfaceId)); + assertTrue(s_feeQuoter.supportsInterface(type(IERC165).interfaceId)); + } +} diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol index 447c979d405..2f57a00bf04 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -7,7 +7,7 @@ import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { +contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator { event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); error UnauthorizedSender(address sender); @@ -101,7 +101,7 @@ contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { return (report.Price, report.Timestamp); } - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol index 708fdc8e692..809081b92e0 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol @@ -10,11 +10,11 @@ abstract contract KeystoneFeedsPermissionHandler is Ownable2StepMsgSender { /// @notice Holds the details for permissions of a report /// @dev Workflow names and report names are stored as bytes to optimize for gas efficiency. struct Permission { - address forwarder; // ──────╮ The address of the forwarder (20 bytes) - bytes10 workflowName; // │ The name of the workflow in bytes10 - bytes2 reportName; // ──────╯ The name of the report in bytes2 - address workflowOwner; // ──╮ The address of the workflow owner (20 bytes) - bool isAllowed; // ─────────╯ Whether the report is allowed or not (1 byte) + address forwarder; // ─────╮ The address of the forwarder (20 bytes) + bytes10 workflowName; // │ The name of the workflow in bytes10 + bytes2 reportName; // ─────╯ The name of the report in bytes2 + address workflowOwner; // ─╮ The address of the workflow owner (20 bytes) + bool isAllowed; // ────────╯ Whether the report is allowed or not (1 byte) } /// @notice Event emitted when report permissions are set diff --git a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol index 9afa1d340a3..b18e35d6b5f 100644 --- a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol +++ b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + /// @title IReceiver - receives keystone reports -interface IReceiver { +/// @notice Implementations must support the IReceiver interface through ERC165. +interface IReceiver is IERC165 { /// @notice Handles incoming keystone reports. /// @dev If this function call reverts, it can be retried with a higher gas /// limit. The receiver is responsible for discarding stale reports. diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol index 8f039b5f0ce..71fb731d0ad 100644 --- a/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IReceiver} from "../../interfaces/IReceiver.sol"; -contract MaliciousReportReceiver is IReceiver, IERC165 { +contract MaliciousReportReceiver is IReceiver { event MessageReceived(bytes metadata, bytes[] mercuryReports); bytes public latestReport; diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol index f45e95afb2c..c749b50dafe 100644 --- a/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol @@ -6,7 +6,7 @@ import {IReceiver} from "../../interfaces/IReceiver.sol"; /// A malicious receiver that uses max allowed for ERC165 checks and consumes all gas in `onReport()` /// Causes parent Forwarder contract to revert if it doesn't handle gas tracking accurately -contract MaliciousRevertingReceiver is IReceiver, IERC165 { +contract MaliciousRevertingReceiver is IReceiver { function onReport(bytes calldata, bytes calldata) external view override { // consumes about 63/64 of all gas available uint256 targetGasRemaining = 200; diff --git a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol index d4005950ade..0604a145c6b 100644 --- a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IReceiver} from "../../interfaces/IReceiver.sol"; -contract Receiver is IReceiver, IERC165 { +contract Receiver is IReceiver { event MessageReceived(bytes metadata, bytes[] mercuryReports); bytes public latestReport; @@ -18,7 +18,7 @@ contract Receiver is IReceiver, IERC165 { emit MessageReceived(metadata, mercuryReports); } - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index 1d28c85f997..1f64166ac74 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -156,8 +156,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minFeeUSDCents\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\"}],\"name\":\"InvalidFeeRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620078f0380380620078f083398101604081905262000034916200189c565b85336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001d0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200024a565b5060208701516001600160a01b03161580620000dc575086516001600160601b0316155b80620000f05750604087015163ffffffff16155b156200010f5760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c052805160008152918201905262000155908662000399565b6200016084620004e1565b6200016b81620005d9565b620001768262000a45565b60408051600080825260208201909252620001c391859190620001bc565b6040805180820190915260008082526020820152815260200190600190039081620001945790505b5062000b11565b5050505050505062001b5a565b336001600160a01b03821603620001fa57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620002da576000828281518110620002735762000273620019bb565b602090810291909101015190506200028d60028262000e97565b15620002d0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000252565b50815160005b815181101562000393576000828281518110620003015762000301620019bb565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200033f576040516342bcdf7f60e11b815260040160405180910390fd5b6200034c60028262000eb7565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620002e0565b50505050565b60005b82518110156200043a57620003d8838281518110620003bf57620003bf620019bb565b6020026020010151600b62000ece60201b90919060201c565b156200043157828181518110620003f357620003f3620019bb565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016200039c565b5060005b8151811015620004dc576200047a828281518110620004615762000461620019bb565b6020026020010151600b62000eb760201b90919060201c565b15620004d357818181518110620004955762000495620019bb565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016200043e565b505050565b60005b8151811015620005d5576000828281518110620005055762000505620019bb565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a0180518589018051949098166001600160a81b03199093168317600160a01b60ff928316021760ff60a81b1916600160a81b9415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050620004e4565b5050565b60005b8151811015620005d5576000828281518110620005fd57620005fd620019bb565b6020026020010151905060008383815181106200061e576200061e620019bb565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000657575061016081015163ffffffff16155b806200067957506102008101516001600160e01b031916630a04b54b60e21b14155b80620006995750806060015163ffffffff1681610160015163ffffffff16115b15620006c85760405163c35aa79d60e01b81526001600160401b03831660048201526024015b60405180910390fd5b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b03191690036200074857816001600160401b03167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516200073a9190620019d1565b60405180910390a26200078c565b816001600160401b03167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051620007839190620019d1565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050620005dc565b60005b8151811015620005d557600082828151811062000a695762000a69620019bb565b6020026020010151600001519050600083838151811062000a8e5762000a8e620019bb565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a48565b60005b825181101562000dd157600083828151811062000b355762000b35620019bb565b6020026020010151905060008160000151905060005b82602001515181101562000dc25760008360200151828151811062000b745762000b74620019bb565b602002602001015160200151905060008460200151838151811062000b9d5762000b9d620019bb565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff161062000bf857815160208301516040516305a7b3d160e11b815263ffffffff928316600482015291166024820152604401620006bf565b602063ffffffff16826080015163ffffffff16101562000c495760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff9091166024820152604401620006bf565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000daf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b4b565b50505080600101905062000b14565b5060005b8151811015620004dc57600082828151811062000df65762000df6620019bb565b6020026020010151600001519050600083838151811062000e1b5762000e1b620019bb565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd5565b600062000eae836001600160a01b03841662000ee5565b90505b92915050565b600062000eae836001600160a01b03841662000fe9565b600062000eae836001600160a01b0384166200103b565b6000818152600183016020526040812054801562000fde57600062000f0c60018362001b22565b855490915060009062000f229060019062001b22565b905081811462000f8e57600086600001828154811062000f465762000f46620019bb565b906000526020600020015490508087600001848154811062000f6c5762000f6c620019bb565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000fa25762000fa262001b44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb1565b600091505062000eb1565b6000818152600183016020526040812054620010325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb1565b50600062000eb1565b6000818152600183016020526040812054801562000fde5760006200106260018362001b22565b8554909150600090620010789060019062001b22565b905080821462000f8e57600086600001828154811062000f465762000f46620019bb565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620010d757620010d76200109c565b60405290565b604080519081016001600160401b0381118282101715620010d757620010d76200109c565b60405160c081016001600160401b0381118282101715620010d757620010d76200109c565b60405161022081016001600160401b0381118282101715620010d757620010d76200109c565b604051601f8201601f191681016001600160401b03811182821017156200117857620011786200109c565b604052919050565b80516001600160a01b03811681146200119857600080fd5b919050565b805163ffffffff811681146200119857600080fd5b600060608284031215620011c557600080fd5b620011cf620010b2565b82519091506001600160601b0381168114620011ea57600080fd5b8152620011fa6020830162001180565b60208201526200120d604083016200119d565b604082015292915050565b60006001600160401b038211156200123457620012346200109c565b5060051b60200190565b600082601f8301126200125057600080fd5b8151602062001269620012638362001218565b6200114d565b8083825260208201915060208460051b8701019350868411156200128c57600080fd5b602086015b84811015620012b357620012a58162001180565b835291830191830162001291565b509695505050505050565b805180151581146200119857600080fd5b600082601f830112620012e157600080fd5b81516020620012f4620012638362001218565b82815260079290921b840181019181810190868411156200131457600080fd5b8286015b84811015620012b3578088036080811215620013345760008081fd5b6200133e620010dd565b620013498362001180565b8152606080601f1984011215620013605760008081fd5b6200136a620010b2565b92506200137987850162001180565b835260408085015160ff81168114620013925760008081fd5b84890152620013a3858301620012be565b90840152508086019190915283529183019160800162001318565b80516001600160401b03811681146200119857600080fd5b805161ffff811681146200119857600080fd5b600082601f830112620013fb57600080fd5b815160206200140e620012638362001218565b82815260059290921b840181019181810190868411156200142e57600080fd5b8286015b84811015620012b35780516001600160401b03808211156200145357600080fd5b908801906040601f19838c0381018213156200146e57600080fd5b62001478620010dd565b62001485898601620013be565b815282850151848111156200149957600080fd5b8086019550508c603f860112620014af57600080fd5b888501519350620014c4620012638562001218565b84815260e09094028501830193898101908e861115620014e357600080fd5b958401955b85871015620015bc57868f0360e08112156200150357600080fd5b6200150d620010dd565b620015188962001180565b815260c086830112156200152b57600080fd5b6200153562001102565b9150620015448d8a016200119d565b825262001553878a016200119d565b8d8301526200156560608a01620013d6565b878301526200157760808a016200119d565b60608301526200158a60a08a016200119d565b60808301526200159d60c08a01620012be565b60a0830152808d0191909152825260e09690960195908a0190620014e8565b828b01525087525050509284019250830162001432565b600082601f830112620015e557600080fd5b81516020620015f8620012638362001218565b82815260069290921b840181019181810190868411156200161857600080fd5b8286015b84811015620012b35760408189031215620016375760008081fd5b62001641620010dd565b6200164c8262001180565b81526200165b858301620013be565b818601528352918301916040016200161c565b80516001600160e01b0319811681146200119857600080fd5b600082601f8301126200169957600080fd5b81516020620016ac620012638362001218565b8281526102409283028501820192828201919087851115620016cd57600080fd5b8387015b858110156200188f5780890382811215620016ec5760008081fd5b620016f6620010dd565b6200170183620013be565b815261022080601f1984011215620017195760008081fd5b6200172362001127565b925062001732888501620012be565b8352604062001743818601620013d6565b898501526060620017568187016200119d565b82860152608091506200176b8287016200119d565b9085015260a06200177e8682016200119d565b8286015260c0915062001793828701620013d6565b9085015260e0620017a68682016200119d565b828601526101009150620017bc828701620013d6565b90850152610120620017d0868201620013d6565b828601526101409150620017e6828701620013d6565b90850152610160620017fa8682016200119d565b828601526101809150620018108287016200119d565b908501526101a062001824868201620013be565b828601526101c091506200183a8287016200119d565b908501526101e06200184e8682016200119d565b82860152610200915062001864828701620012be565b90850152620018758583016200166e565b9084015250808701919091528452928401928101620016d1565b5090979650505050505050565b6000806000806000806000610120888a031215620018b957600080fd5b620018c58989620011b2565b60608901519097506001600160401b0380821115620018e357600080fd5b620018f18b838c016200123e565b975060808a01519150808211156200190857600080fd5b620019168b838c016200123e565b965060a08a01519150808211156200192d57600080fd5b6200193b8b838c01620012cf565b955060c08a01519150808211156200195257600080fd5b620019608b838c01620013e9565b945060e08a01519150808211156200197757600080fd5b620019858b838c01620015d3565b93506101008a01519150808211156200199d57600080fd5b50620019ac8a828b0162001687565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019f2602084018261ffff169052565b50604083015162001a0b604084018263ffffffff169052565b50606083015162001a24606084018263ffffffff169052565b50608083015162001a3d608084018263ffffffff169052565b5060a083015162001a5460a084018261ffff169052565b5060c083015162001a6d60c084018263ffffffff169052565b5060e083015162001a8460e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb157634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615d4362001bad600039600081816102fa01526117ba0152600081816102be01528181610ed50152610f3501526000818161028a01528181610f5e0152610fce0152615d436000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c806379ba509711610104578063bf78e03f116100a2578063d8694ccd11610071578063d8694ccd14610ad6578063f2fde38b14610ae9578063fbe3f77814610afc578063ffdb4b3714610b0f57600080fd5b8063bf78e03f146109d5578063cdc73d5114610ab3578063d02641a014610abb578063d63d3af214610ace57600080fd5b806382b49eb0116100de57806382b49eb0146108175780638da5cb5b1461098757806391a2749a146109af578063a69c64c0146109c257600080fd5b806379ba5097146107e95780637afac322146107f1578063805f21321461080457600080fd5b806341ed29e71161017c578063514e8cff1161014b578063514e8cff146104845780636cb5f3dd146105275780636def4ce71461053a578063770e2dc4146107d657600080fd5b806341ed29e7146103ee578063430d138c1461040157806345ac924d146104245780634ab35b0b1461044457600080fd5b8063181f5a77116101b8578063181f5a77146103735780632451a627146103bc578063325c868e146103d15780633937306f146103d957600080fd5b806241e5be146101de578063061877e31461020457806306285c691461025d575b600080fd5b6101f16101ec36600461440b565b610b57565b6040519081526020015b60405180910390f35b610244610212366004614447565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101fb565b610327604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101fb565b6103af6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101fb91906144c6565b6103c4610bc5565b6040516101fb91906144d9565b6101f1602481565b6103ec6103e7366004614533565b610bd6565b005b6103ec6103fc3660046146df565b610e8b565b61041461040f3660046148ca565b610ecd565b6040516101fb94939291906149be565b610437610432366004614a5d565b6110dd565b6040516101fb9190614a9f565b610457610452366004614447565b6111a8565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b61051a610492366004614b1a565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101fb9190614b35565b6103ec610535366004614bc6565b6111b3565b6107c9610548366004614b1a565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c01000000000000000000000000860485166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516101fb9190614de6565b6103ec6107e4366004614fe4565b6111c7565b6103ec6111d9565b6103ec6107ff3660046152fe565b6112a7565b6103ec610812366004615362565b6112b9565b6109276108253660046153ce565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101fb9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60015460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b6103ec6109bd3660046153f8565b6116f5565b6103ec6109d0366004615489565b611706565b610a766109e3366004614447565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff9485168152600783528390208351918201845254938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615159082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260208084015160ff1690820152918101511515908201526060016101fb565b6103c4611717565b61051a610ac9366004614447565b611723565b6101f1601281565b6101f1610ae436600461554e565b6118d8565b6103ec610af7366004614447565b611e10565b6103ec610b0a3660046155b2565b611e21565b610b22610b1d3660046156d2565b611e32565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101fb565b6000610b6282611eea565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b8985611eea565b610bb1907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168561572b565b610bbb9190615742565b90505b9392505050565b6060610bd16002611f84565b905090565b610bde611f91565b6000610bea828061577d565b9050905060005b81811015610d34576000610c05848061577d565b83818110610c1557610c156157e5565b905060400201803603810190610c2b9190615840565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610d239290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610bf1565b506000610d44602084018461577d565b9050905060005b81811015610e85576000610d62602086018661577d565b83818110610d7257610d726157e5565b905060400201803603810190610d88919061587d565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e749290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d4b565b50505050565b610e93611fd6565b60005b8151811015610ec957610ec1828281518110610eb457610eb46157e5565b6020026020010151612027565b600101610e96565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1603610f2e578a9350610f5c565b610f598c8c7f0000000000000000000000000000000000000000000000000000000000000000610b57565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16841115611000576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff169061102f8c8c846121f9565b9050806020015194506110458f8b8b8b8b6123a2565b925085856110c5836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff8111156110fb576110fb61456e565b60405190808252806020026020018201604052801561114057816020015b60408051808201909152600080825260208201528152602001906001900390816111195790505b50905060005b8281101561119d57611178868683818110611163576111636157e5565b9050602002016020810190610ac99190614447565b82828151811061118a5761118a6157e5565b6020908102919091010152600101611146565b509150505b92915050565b60006111a282611eea565b6111bb611fd6565b6111c481612725565b50565b6111cf611fd6565b610ec98282612bf7565b60005473ffffffffffffffffffffffffffffffffffffffff16331461122a576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6112af611fd6565b610ec9828261306d565b60008060006112fd87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506131b492505050565b92509250925061130f338385846131cf565b600061131d858701876158a0565b905060005b81518110156116ea57600060076000848481518110611343576113436157e5565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff908116835282820193909352604091820160002082516060810184529054938416815260ff740100000000000000000000000000000000000000008504811692820192909252750100000000000000000000000000000000000000000090930416151590820181905290915061143e578282815181106113e7576113e76157e5565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610ff7565b600061148b6012836020015186868151811061145c5761145c6157e5565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613327565b9050600660008585815181106114a3576114a36157e5565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff16848481518110611515576115156157e5565b60200260200101516040015163ffffffff1610156115345750506116e2565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001858581518110611575576115756157e5565b60200260200101516040015163ffffffff16815250600660008686815181106115a0576115a06157e5565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790558351849084908110611638576116386157e5565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061168e5761168e6157e5565b6020026020010151604001516040516116d79291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250505b600101611322565b505050505050505050565b6116fd611fd6565b6111c4816133ea565b61170e611fd6565b6111c481613576565b6060610bd1600b611f84565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f000000000000000000000000000000000000000000000000000000000000000016906117e59042615967565b10156117f15792915050565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526007602090815260409182902082516060810184529054938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615801591830191909152806118925750805173ffffffffffffffffffffffffffffffffffffffff16155b1561189e575092915050565b60006118a982613660565b9050826020015163ffffffff16816020015163ffffffff1610156118cd57826118cf565b805b95945050505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c01000000000000000000000000880485166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611b12576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610ff7565b611b2d611b256080850160608601614447565b600b906137f2565b611b8c57611b416080840160608501614447565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610ff7565b6000611b9b604085018561577d565b9150611bf7905082611bb0602087018761597a565b905083611bbd888061597a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061382192505050565b6000611c11611c0c6080870160608801614447565b611eea565b90506000611c2487856101c001516138de565b9050600080808515611c6457611c58878b611c4560808d0160608e01614447565b88611c5360408f018f61577d565b6139de565b91945092509050611c84565b6101a0870151611c819063ffffffff16662386f26fc1000061572b565b92505b61010087015160009061ffff1615611cc857611cc5886dffffffffffffffffffffffffffff607088901c16611cbc60208e018e61597a565b90508a86613cb6565b90505b61018088015160009067ffffffffffffffff16611cf1611ceb60808e018e61597a565b8c613d66565b600001518563ffffffff168b60a0015161ffff168e8060200190611d15919061597a565b611d2092915061572b565b8c6080015163ffffffff16611d3591906159df565b611d3f91906159df565b611d4991906159df565b611d63906dffffffffffffffffffffffffffff891661572b565b611d6d919061572b565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611da79190614447565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611de29067ffffffffffffffff168961572b565b611dec91906159df565b611df691906159df565b611e009190615742565b9c9b505050505050505050505050565b611e18611fd6565b6111c481613e27565b611e29611fd6565b6111c481613eeb565b67ffffffffffffffff8116600090815260096020526040812054819060ff16611e93576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610ff7565b611e9c84611eea565b67ffffffffffffffff8416600090815260096020526040902060010154611ede908590700100000000000000000000000000000000900463ffffffff166138de565b915091505b9250929050565b600080611ef683611723565b9050806020015163ffffffff1660001480611f2e575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15611f7d576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610ff7565b5192915050565b60606000610bbe8361403d565b611f9c6002336137f2565b611fd4576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610ff7565b565b60015473ffffffffffffffffffffffffffffffffffffffff163314611fd4576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006120e082600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906121ed908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b6040805180820190915260008082526020820152600083900361223a57506040805180820190915267ffffffffffffffff8216815260006020820152610bbe565b600061224684866159f2565b905060006122578560048189615a38565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016122f457808060200190518101906122eb9190615a62565b92505050610bbe565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016123705760405180604001604052808280602001905181019061235c9190615a8e565b815260006020909101529250610bbe915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808616600090815260096020526040902060010154606091750100000000000000000000000000000000000000000090910460e01b9085908111156123f2576123f261456e565b60405190808252806020026020018201604052801561242557816020015b60608152602001906001900390816124105790505b50915060005b8581101561271a576000858583818110612447576124476157e5565b61245d9260206040909202019081019150614447565b90506000888884818110612473576124736157e5565b90506020028101906124859190615aa7565b61249390604081019061597a565b91505060208111156125435767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115612543576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610ff7565b6125b3848a8a86818110612559576125596157e5565b905060200281019061256b9190615aa7565b61257990602081019061597a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061409992505050565b67ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684528252808320815160c081018352905463ffffffff8082168352640100000000820481169483019490945268010000000000000000810461ffff16928201929092526a01000000000000000000008204831660608201526e010000000000000000000000000000820490921660808301527201000000000000000000000000000000000000900460ff16151560a082018190529091906126c55767ffffffffffffffff8c166000908152600960205260409020547b01000000000000000000000000000000000000000000000000000000900463ffffffff166126cb565b81606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052878681518110612700576127006157e5565b60200260200101819052505050505080600101905061242b565b505095945050505050565b60005b8151811015610ec9576000828281518110612745576127456157e5565b602002602001015190506000838381518110612763576127636157e5565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061279c575061016081015163ffffffff16155b806127ee57506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061280d5750806060015163ffffffff1681610160015163ffffffff16115b15612850576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610ff7565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036128f8578167ffffffffffffffff167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516128eb9190614de6565b60405180910390a261293b565b8167ffffffffffffffff167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a835826040516129329190614de6565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612728565b60005b8251811015612f84576000838281518110612c1757612c176157e5565b6020026020010151905060008160000151905060005b826020015151811015612f7657600083602001518281518110612c5257612c526157e5565b6020026020010151602001519050600084602001518381518110612c7857612c786157e5565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff1610612cea57815160208301516040517f0b4f67a200000000000000000000000000000000000000000000000000000000815263ffffffff928316600482015291166024820152604401610ff7565b602063ffffffff16826080015163ffffffff161015612d5f5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610ff7565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612f64908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612c2d565b505050806001019050612bfa565b5060005b8151811015613068576000828281518110612fa557612fa56157e5565b60200260200101516000015190506000838381518110612fc757612fc76157e5565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612f88565b505050565b60005b8251811015613110576130a683828151811061308e5761308e6157e5565b6020026020010151600b6140eb90919063ffffffff16565b15613108578281815181106130bd576130bd6157e5565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101613070565b5060005b81518110156130685761314a828281518110613132576131326157e5565b6020026020010151600b61410d90919063ffffffff16565b156131ac57818181518110613161576131616157e5565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101613114565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16613320576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610ff7565b5050505050565b6000806133348486615ae5565b9050600060248260ff16111561336e57613352602460ff8416615967565b61335d90600a615c1e565b6133679085615742565b9050613394565b61337c60ff83166024615967565b61338790600a615c1e565b613391908561572b565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156118cf576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160005b815181101561348557600082828151811061340f5761340f6157e5565b6020026020010151905061342d81600261412f90919063ffffffff16565b1561347c5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016133f2565b50815160005b8151811015610e855760008282815181106134a8576134a86157e5565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613518576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61352360028261410d565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010161348b565b60005b8151811015610ec9576000828281518110613596576135966157e5565b602002602001015160000151905060008383815181106135b8576135b86157e5565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613579565b60408051808201909152600080825260208201526000826000015190506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156136cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ef9190615c44565b509350509250506000821215613731576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006137b08473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613781573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a59190615c94565b876020015185613327565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff909216602083015250949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bbe565b836040015163ffffffff1683111561387a5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610ff7565b836020015161ffff168211156138cf5760208401516040517fd88dddd60000000000000000000000000000000000000000000000000000000081526004810184905261ffff9091166024820152604401610ff7565b610e8584610200015182614099565b67ffffffffffffffff821660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825263ffffffff7c0100000000000000000000000000000000000000000000000000000000909104811692820192909252908316156139d6576000816020015163ffffffff16426139739190615967565b90508363ffffffff168111156139d4576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff8516602482015260448101829052606401610ff7565b505b519392505050565b6000808083815b81811015613ca8576000878783818110613a0157613a016157e5565b905060400201803603810190613a179190615cb1565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b37576101208d0151613b049061ffff16662386f26fc1000061572b565b613b0e90886159df565b96508c610140015186613b219190615cea565b9550613b2e602086615cea565b94505050613ca0565b604081015160009061ffff1615613bf05760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613b93578351613b8c90611eea565b9050613b96565b508a5b620186a0836040015161ffff16613bd88660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661415190919063ffffffff16565b613be2919061572b565b613bec9190615742565b9150505b6060820151613bff9088615cea565b9650816080015186613c119190615cea565b8251909650600090613c309063ffffffff16662386f26fc1000061572b565b905080821015613c4f57613c44818a6159df565b985050505050613ca0565b6000836020015163ffffffff16662386f26fc10000613c6e919061572b565b905080831115613c8e57613c82818b6159df565b99505050505050613ca0565b613c98838b6159df565b995050505050505b6001016139e5565b505096509650969350505050565b60008063ffffffff8316613ccc6101208661572b565b613cd8876101e06159df565b613ce291906159df565b613cec91906159df565b905060008760c0015163ffffffff168860e0015161ffff1683613d0f919061572b565b613d1991906159df565b61010089015190915061ffff16613d406dffffffffffffffffffffffffffff89168361572b565b613d4a919061572b565b613d5a90655af3107a400061572b565b98975050505050505050565b60408051808201909152600080825260208201526000613d92858585610160015163ffffffff166121f9565b9050826060015163ffffffff1681600001511115613ddc576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015613df057508060200151155b15610bbb576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613e76576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015610ec9576000828281518110613f0b57613f0b6157e5565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a0180518589018051949098167fffffffffffffffffffffff00000000000000000000000000000000000000000090931683177401000000000000000000000000000000000000000060ff92831602177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000009415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050613eee565b60608160000180548060200260200160405190810160405280929190818152602001828054801561408d57602002820191906000526020600020905b815481526020019060010190808311614079575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610ec9576130688161418e565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff8416614241565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff841661433b565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff841661438a565b6000670de0b6b3a7640000614184837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff861661572b565b610bbe9190615742565b600081516020146141cd57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ff791906144c6565b6000828060200190518101906141e39190615a8e565b905073ffffffffffffffffffffffffffffffffffffffff811180614208575061040081105b156111a257826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ff791906144c6565b6000818152600183016020526040812054801561432a576000614265600183615967565b855490915060009061427990600190615967565b90508082146142de576000866000018281548110614299576142996157e5565b90600052602060002001549050808760000184815481106142bc576142bc6157e5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806142ef576142ef615d07565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506111a2565b60009150506111a2565b5092915050565b6000818152600183016020526040812054614382575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556111a2565b5060006111a2565b6000818152600183016020526040812054801561432a5760006143ae600183615967565b85549091506000906143c290600190615967565b90508181146142de576000866000018281548110614299576142996157e5565b803573ffffffffffffffffffffffffffffffffffffffff8116811461440657600080fd5b919050565b60008060006060848603121561442057600080fd5b614429846143e2565b92506020840135915061443e604085016143e2565b90509250925092565b60006020828403121561445957600080fd5b610bbe826143e2565b6000815180845260005b818110156144885760208185018101518683018201520161446c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610bbe6020830184614462565b6020808252825182820181905260009190848201906040850190845b8181101561452757835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144f5565b50909695505050505050565b60006020828403121561454557600080fd5b813567ffffffffffffffff81111561455c57600080fd5b820160408185031215610bbe57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156145c0576145c061456e565b60405290565b6040805190810167ffffffffffffffff811182821017156145c0576145c061456e565b604051610220810167ffffffffffffffff811182821017156145c0576145c061456e565b60405160c0810167ffffffffffffffff811182821017156145c0576145c061456e565b6040516060810167ffffffffffffffff811182821017156145c0576145c061456e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561469a5761469a61456e565b604052919050565b600067ffffffffffffffff8211156146bc576146bc61456e565b5060051b60200190565b80151581146111c457600080fd5b8035614406816146c6565b600060208083850312156146f257600080fd5b823567ffffffffffffffff81111561470957600080fd5b8301601f8101851361471a57600080fd5b803561472d614728826146a2565b614653565b81815260a0918202830184019184820191908884111561474c57600080fd5b938501935b8385101561481f5780858a0312156147695760008081fd5b61477161459d565b61477a866143e2565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146147af5760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146147e85760008081fd5b9082015260606147f98782016143e2565b9082015260808681013561480c816146c6565b9082015283529384019391850191614751565b50979650505050505050565b803567ffffffffffffffff8116811461440657600080fd5b60008083601f84011261485557600080fd5b50813567ffffffffffffffff81111561486d57600080fd5b602083019150836020828501011115611ee357600080fd5b60008083601f84011261489757600080fd5b50813567ffffffffffffffff8111156148af57600080fd5b6020830191508360208260051b8501011115611ee357600080fd5b600080600080600080600080600060c08a8c0312156148e857600080fd5b6148f18a61482b565b98506148ff60208b016143e2565b975060408a0135965060608a013567ffffffffffffffff8082111561492357600080fd5b61492f8d838e01614843565b909850965060808c013591508082111561494857600080fd5b6149548d838e01614885565b909650945060a08c013591508082111561496d57600080fd5b818c0191508c601f83011261498157600080fd5b81358181111561499057600080fd5b8d60208260061b85010111156149a557600080fd5b6020830194508093505050509295985092959850929598565b8481526000602085151581840152608060408401526149e06080840186614462565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614a4c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614a3a838351614462565b94870194925090860190600101614a00565b50909b9a5050505050505050505050565b60008060208385031215614a7057600080fd5b823567ffffffffffffffff811115614a8757600080fd5b614a9385828601614885565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614b0d57614afd84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614abc565b5091979650505050505050565b600060208284031215614b2c57600080fd5b610bbe8261482b565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016111a2565b803561ffff8116811461440657600080fd5b803563ffffffff8116811461440657600080fd5b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461440657600080fd5b60006020808385031215614bd957600080fd5b823567ffffffffffffffff811115614bf057600080fd5b8301601f81018513614c0157600080fd5b8035614c0f614728826146a2565b8181526102409182028301840191848201919088841115614c2f57600080fd5b938501935b8385101561481f5784890381811215614c4d5760008081fd5b614c556145c6565b614c5e8761482b565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215614c935760008081fd5b614c9b6145e9565b9250614ca88989016146d4565b83526040614cb7818a01614b70565b8a8501526060614cc8818b01614b82565b8286015260809150614cdb828b01614b82565b9085015260a0614cec8a8201614b82565b8286015260c09150614cff828b01614b70565b9085015260e0614d108a8201614b82565b828601526101009150614d24828b01614b70565b90850152610120614d368a8201614b70565b828601526101409150614d4a828b01614b70565b90850152610160614d5c8a8201614b82565b828601526101809150614d70828b01614b82565b908501526101a0614d828a820161482b565b828601526101c09150614d96828b01614b82565b908501526101e0614da88a8201614b82565b828601526102009150614dbc828b016146d4565b90850152614dcb898301614b96565b90840152508088019190915283529384019391850191614c34565b81511515815261022081016020830151614e06602084018261ffff169052565b506040830151614e1e604084018263ffffffff169052565b506060830151614e36606084018263ffffffff169052565b506080830151614e4e608084018263ffffffff169052565b5060a0830151614e6460a084018261ffff169052565b5060c0830151614e7c60c084018263ffffffff169052565b5060e0830151614e9260e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b600082601f830112614f5d57600080fd5b81356020614f6d614728836146a2565b82815260069290921b84018101918181019086841115614f8c57600080fd5b8286015b84811015614fd95760408189031215614fa95760008081fd5b614fb16145c6565b614fba8261482b565b8152614fc78583016143e2565b81860152835291830191604001614f90565b509695505050505050565b60008060408385031215614ff757600080fd5b67ffffffffffffffff8335111561500d57600080fd5b83601f84358501011261501f57600080fd5b61502f61472884358501356146a2565b8335840180358083526020808401939260059290921b9091010186101561505557600080fd5b602085358601015b85358601803560051b016020018110156152625767ffffffffffffffff8135111561508757600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a030112156150c057600080fd5b6150c86145c6565b6150d46020830161482b565b815267ffffffffffffffff604083013511156150ef57600080fd5b88603f60408401358401011261510457600080fd5b61511a61472860206040850135850101356146a2565b6020604084810135850182810135808552928401939260e00201018b101561514157600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156152435760e0818d03121561517457600080fd5b61517c6145c6565b615185826143e2565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f030112156151b957600080fd5b6151c161460d565b6151cd60208401614b82565b81526151db60408401614b82565b60208201526151ec60608401614b70565b60408201526151fd60808401614b82565b606082015261520e60a08401614b82565b608082015261522060c08401356146c6565b60c083013560a0820152602082810191909152908452929092019160e00161514b565b508060208401525050808552505060208301925060208101905061505d565b5092505067ffffffffffffffff6020840135111561527f57600080fd5b61528f8460208501358501614f4c565b90509250929050565b600082601f8301126152a957600080fd5b813560206152b9614728836146a2565b8083825260208201915060208460051b8701019350868411156152db57600080fd5b602086015b84811015614fd9576152f1816143e2565b83529183019183016152e0565b6000806040838503121561531157600080fd5b823567ffffffffffffffff8082111561532957600080fd5b61533586838701615298565b9350602085013591508082111561534b57600080fd5b5061535885828601615298565b9150509250929050565b6000806000806040858703121561537857600080fd5b843567ffffffffffffffff8082111561539057600080fd5b61539c88838901614843565b909650945060208701359150808211156153b557600080fd5b506153c287828801614843565b95989497509550505050565b600080604083850312156153e157600080fd5b6153ea8361482b565b915061528f602084016143e2565b60006020828403121561540a57600080fd5b813567ffffffffffffffff8082111561542257600080fd5b908301906040828603121561543657600080fd5b61543e6145c6565b82358281111561544d57600080fd5b61545987828601615298565b82525060208301358281111561546e57600080fd5b61547a87828601615298565b60208301525095945050505050565b6000602080838503121561549c57600080fd5b823567ffffffffffffffff8111156154b357600080fd5b8301601f810185136154c457600080fd5b80356154d2614728826146a2565b81815260069190911b820183019083810190878311156154f157600080fd5b928401925b82841015615543576040848903121561550f5760008081fd5b6155176145c6565b615520856143e2565b815261552d86860161482b565b81870152825260409390930192908401906154f6565b979650505050505050565b6000806040838503121561556157600080fd5b61556a8361482b565b9150602083013567ffffffffffffffff81111561558657600080fd5b830160a0818603121561559857600080fd5b809150509250929050565b60ff811681146111c457600080fd5b600060208083850312156155c557600080fd5b823567ffffffffffffffff8111156155dc57600080fd5b8301601f810185136155ed57600080fd5b80356155fb614728826146a2565b81815260079190911b8201830190838101908783111561561a57600080fd5b928401925b828410156155435783880360808112156156395760008081fd5b6156416145c6565b61564a866143e2565b81526060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561567e5760008081fd5b615686614630565b92506156938888016143e2565b83526040808801356156a4816155a3565b848a015290870135906156b6826146c6565b830152808701919091528252608093909301929084019061561f565b600080604083850312156156e557600080fd5b6156ee836143e2565b915061528f6020840161482b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176111a2576111a26156fc565b600082615778577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126157b257600080fd5b83018035915067ffffffffffffffff8211156157cd57600080fd5b6020019150600681901b3603821315611ee357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461440657600080fd5b60006040828403121561585257600080fd5b61585a6145c6565b615863836143e2565b815261587160208401615814565b60208201529392505050565b60006040828403121561588f57600080fd5b6158976145c6565b6158638361482b565b600060208083850312156158b357600080fd5b823567ffffffffffffffff8111156158ca57600080fd5b8301601f810185136158db57600080fd5b80356158e9614728826146a2565b8181526060918202830184019184820191908884111561590857600080fd5b938501935b8385101561481f5780858a0312156159255760008081fd5b61592d614630565b615936866143e2565b8152615943878701615814565b878201526040615954818801614b82565b908201528352938401939185019161590d565b818103818111156111a2576111a26156fc565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159af57600080fd5b83018035915067ffffffffffffffff8211156159ca57600080fd5b602001915036819003821315611ee357600080fd5b808201808211156111a2576111a26156fc565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614f445760049490940360031b84901b1690921692915050565b60008085851115615a4857600080fd5b83861115615a5557600080fd5b5050820193919092039150565b600060408284031215615a7457600080fd5b615a7c6145c6565b825181526020830151615871816146c6565b600060208284031215615aa057600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615adb57600080fd5b9190910192915050565b60ff81811683821601908111156111a2576111a26156fc565b600181815b80851115615b5757817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b3d57615b3d6156fc565b80851615615b4a57918102915b93841c9390800290615b03565b509250929050565b600082615b6e575060016111a2565b81615b7b575060006111a2565b8160018114615b915760028114615b9b57615bb7565b60019150506111a2565b60ff841115615bac57615bac6156fc565b50506001821b6111a2565b5060208310610133831016604e8410600b8410161715615bda575081810a6111a2565b615be48383615afe565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615c1657615c166156fc565b029392505050565b6000610bbe8383615b5f565b805169ffffffffffffffffffff8116811461440657600080fd5b600080600080600060a08688031215615c5c57600080fd5b615c6586615c2a565b9450602086015193506040860151925060608601519150615c8860808701615c2a565b90509295509295909350565b600060208284031215615ca657600080fd5b8151610bbe816155a3565b600060408284031215615cc357600080fd5b615ccb6145c6565b615cd4836143e2565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614334576143346156fc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minFeeUSDCents\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\"}],\"name\":\"InvalidFeeRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b5060405162007a6838038062007a6883398101604081905262000034916200189c565b85336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001d0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200024a565b5060208701516001600160a01b03161580620000dc575086516001600160601b0316155b80620000f05750604087015163ffffffff16155b156200010f5760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c052805160008152918201905262000155908662000399565b6200016084620004e1565b6200016b81620005d9565b620001768262000a45565b60408051600080825260208201909252620001c391859190620001bc565b6040805180820190915260008082526020820152815260200190600190039081620001945790505b5062000b11565b5050505050505062001b5a565b336001600160a01b03821603620001fa57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620002da576000828281518110620002735762000273620019bb565b602090810291909101015190506200028d60028262000e97565b15620002d0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000252565b50815160005b815181101562000393576000828281518110620003015762000301620019bb565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200033f576040516342bcdf7f60e11b815260040160405180910390fd5b6200034c60028262000eb7565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620002e0565b50505050565b60005b82518110156200043a57620003d8838281518110620003bf57620003bf620019bb565b6020026020010151600b62000ece60201b90919060201c565b156200043157828181518110620003f357620003f3620019bb565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016200039c565b5060005b8151811015620004dc576200047a828281518110620004615762000461620019bb565b6020026020010151600b62000eb760201b90919060201c565b15620004d357818181518110620004955762000495620019bb565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016200043e565b505050565b60005b8151811015620005d5576000828281518110620005055762000505620019bb565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a0180518589018051949098166001600160a81b03199093168317600160a01b60ff928316021760ff60a81b1916600160a81b9415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050620004e4565b5050565b60005b8151811015620005d5576000828281518110620005fd57620005fd620019bb565b6020026020010151905060008383815181106200061e576200061e620019bb565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000657575061016081015163ffffffff16155b806200067957506102008101516001600160e01b031916630a04b54b60e21b14155b80620006995750806060015163ffffffff1681610160015163ffffffff16115b15620006c85760405163c35aa79d60e01b81526001600160401b03831660048201526024015b60405180910390fd5b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b03191690036200074857816001600160401b03167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516200073a9190620019d1565b60405180910390a26200078c565b816001600160401b03167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051620007839190620019d1565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050620005dc565b60005b8151811015620005d557600082828151811062000a695762000a69620019bb565b6020026020010151600001519050600083838151811062000a8e5762000a8e620019bb565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a48565b60005b825181101562000dd157600083828151811062000b355762000b35620019bb565b6020026020010151905060008160000151905060005b82602001515181101562000dc25760008360200151828151811062000b745762000b74620019bb565b602002602001015160200151905060008460200151838151811062000b9d5762000b9d620019bb565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff161062000bf857815160208301516040516305a7b3d160e11b815263ffffffff928316600482015291166024820152604401620006bf565b602063ffffffff16826080015163ffffffff16101562000c495760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff9091166024820152604401620006bf565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000daf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b4b565b50505080600101905062000b14565b5060005b8151811015620004dc57600082828151811062000df65762000df6620019bb565b6020026020010151600001519050600083838151811062000e1b5762000e1b620019bb565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd5565b600062000eae836001600160a01b03841662000ee5565b90505b92915050565b600062000eae836001600160a01b03841662000fe9565b600062000eae836001600160a01b0384166200103b565b6000818152600183016020526040812054801562000fde57600062000f0c60018362001b22565b855490915060009062000f229060019062001b22565b905081811462000f8e57600086600001828154811062000f465762000f46620019bb565b906000526020600020015490508087600001848154811062000f6c5762000f6c620019bb565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000fa25762000fa262001b44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb1565b600091505062000eb1565b6000818152600183016020526040812054620010325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb1565b50600062000eb1565b6000818152600183016020526040812054801562000fde5760006200106260018362001b22565b8554909150600090620010789060019062001b22565b905080821462000f8e57600086600001828154811062000f465762000f46620019bb565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620010d757620010d76200109c565b60405290565b604080519081016001600160401b0381118282101715620010d757620010d76200109c565b60405160c081016001600160401b0381118282101715620010d757620010d76200109c565b60405161022081016001600160401b0381118282101715620010d757620010d76200109c565b604051601f8201601f191681016001600160401b03811182821017156200117857620011786200109c565b604052919050565b80516001600160a01b03811681146200119857600080fd5b919050565b805163ffffffff811681146200119857600080fd5b600060608284031215620011c557600080fd5b620011cf620010b2565b82519091506001600160601b0381168114620011ea57600080fd5b8152620011fa6020830162001180565b60208201526200120d604083016200119d565b604082015292915050565b60006001600160401b038211156200123457620012346200109c565b5060051b60200190565b600082601f8301126200125057600080fd5b8151602062001269620012638362001218565b6200114d565b8083825260208201915060208460051b8701019350868411156200128c57600080fd5b602086015b84811015620012b357620012a58162001180565b835291830191830162001291565b509695505050505050565b805180151581146200119857600080fd5b600082601f830112620012e157600080fd5b81516020620012f4620012638362001218565b82815260079290921b840181019181810190868411156200131457600080fd5b8286015b84811015620012b3578088036080811215620013345760008081fd5b6200133e620010dd565b620013498362001180565b8152606080601f1984011215620013605760008081fd5b6200136a620010b2565b92506200137987850162001180565b835260408085015160ff81168114620013925760008081fd5b84890152620013a3858301620012be565b90840152508086019190915283529183019160800162001318565b80516001600160401b03811681146200119857600080fd5b805161ffff811681146200119857600080fd5b600082601f830112620013fb57600080fd5b815160206200140e620012638362001218565b82815260059290921b840181019181810190868411156200142e57600080fd5b8286015b84811015620012b35780516001600160401b03808211156200145357600080fd5b908801906040601f19838c0381018213156200146e57600080fd5b62001478620010dd565b62001485898601620013be565b815282850151848111156200149957600080fd5b8086019550508c603f860112620014af57600080fd5b888501519350620014c4620012638562001218565b84815260e09094028501830193898101908e861115620014e357600080fd5b958401955b85871015620015bc57868f0360e08112156200150357600080fd5b6200150d620010dd565b620015188962001180565b815260c086830112156200152b57600080fd5b6200153562001102565b9150620015448d8a016200119d565b825262001553878a016200119d565b8d8301526200156560608a01620013d6565b878301526200157760808a016200119d565b60608301526200158a60a08a016200119d565b60808301526200159d60c08a01620012be565b60a0830152808d0191909152825260e09690960195908a0190620014e8565b828b01525087525050509284019250830162001432565b600082601f830112620015e557600080fd5b81516020620015f8620012638362001218565b82815260069290921b840181019181810190868411156200161857600080fd5b8286015b84811015620012b35760408189031215620016375760008081fd5b62001641620010dd565b6200164c8262001180565b81526200165b858301620013be565b818601528352918301916040016200161c565b80516001600160e01b0319811681146200119857600080fd5b600082601f8301126200169957600080fd5b81516020620016ac620012638362001218565b8281526102409283028501820192828201919087851115620016cd57600080fd5b8387015b858110156200188f5780890382811215620016ec5760008081fd5b620016f6620010dd565b6200170183620013be565b815261022080601f1984011215620017195760008081fd5b6200172362001127565b925062001732888501620012be565b8352604062001743818601620013d6565b898501526060620017568187016200119d565b82860152608091506200176b8287016200119d565b9085015260a06200177e8682016200119d565b8286015260c0915062001793828701620013d6565b9085015260e0620017a68682016200119d565b828601526101009150620017bc828701620013d6565b90850152610120620017d0868201620013d6565b828601526101409150620017e6828701620013d6565b90850152610160620017fa8682016200119d565b828601526101809150620018108287016200119d565b908501526101a062001824868201620013be565b828601526101c091506200183a8287016200119d565b908501526101e06200184e8682016200119d565b82860152610200915062001864828701620012be565b90850152620018758583016200166e565b9084015250808701919091528452928401928101620016d1565b5090979650505050505050565b6000806000806000806000610120888a031215620018b957600080fd5b620018c58989620011b2565b60608901519097506001600160401b0380821115620018e357600080fd5b620018f18b838c016200123e565b975060808a01519150808211156200190857600080fd5b620019168b838c016200123e565b965060a08a01519150808211156200192d57600080fd5b6200193b8b838c01620012cf565b955060c08a01519150808211156200195257600080fd5b620019608b838c01620013e9565b945060e08a01519150808211156200197757600080fd5b620019858b838c01620015d3565b93506101008a01519150808211156200199d57600080fd5b50620019ac8a828b0162001687565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019f2602084018261ffff169052565b50604083015162001a0b604084018263ffffffff169052565b50606083015162001a24606084018263ffffffff169052565b50608083015162001a3d608084018263ffffffff169052565b5060a083015162001a5460a084018261ffff169052565b5060c083015162001a6d60c084018263ffffffff169052565b5060e083015162001a8460e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb157634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615ebb62001bad6000396000818161032801526119170152600081816102ec0152818161103401526110940152600081816102b8015281816110bd015261112d0152615ebb6000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c8063770e2dc41161010f578063bf78e03f116100a2578063d8694ccd11610071578063d8694ccd14610b04578063f2fde38b14610b17578063fbe3f77814610b2a578063ffdb4b3714610b3d57600080fd5b8063bf78e03f14610a03578063cdc73d5114610ae1578063d02641a014610ae9578063d63d3af214610afc57600080fd5b806382b49eb0116100de57806382b49eb0146108455780638da5cb5b146109b557806391a2749a146109dd578063a69c64c0146109f057600080fd5b8063770e2dc41461080457806379ba5097146108175780637afac3221461081f578063805f21321461083257600080fd5b80633937306f116101875780634ab35b0b116101565780634ab35b0b14610472578063514e8cff146104b25780636cb5f3dd146105555780636def4ce71461056857600080fd5b80633937306f1461040757806341ed29e71461041c578063430d138c1461042f57806345ac924d1461045257600080fd5b806306285c69116101c357806306285c691461028b578063181f5a77146103a15780632451a627146103ea578063325c868e146103ff57600080fd5b806241e5be146101e957806301ffc9a71461020f578063061877e314610232575b600080fd5b6101fc6101f7366004614568565b610b85565b6040519081526020015b60405180910390f35b61022261021d3660046145d4565b610bf3565b6040519015158152602001610206565b6102726102403660046145ef565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610206565b610355604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff1690820152606001610206565b6103dd6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b604051610206919061466e565b6103f2610d24565b6040516102069190614681565b6101fc602481565b61041a6104153660046146db565b610d35565b005b61041a61042a366004614887565b610fea565b61044261043d366004614a72565b61102c565b6040516102069493929190614b66565b610465610460366004614c05565b61123c565b6040516102069190614c47565b6104856104803660046145ef565b611305565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b6105486104c0366004614cc2565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516102069190614cdd565b61041a610563366004614d3e565b611310565b6107f7610576366004614cc2565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c01000000000000000000000000860485166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516102069190614f5e565b61041a61081236600461515c565b611324565b61041a611336565b61041a61082d366004615476565b611404565b61041a6108403660046154da565b611416565b610955610853366004615546565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516102069190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b61041a6109eb366004615570565b611852565b61041a6109fe366004615601565b611863565b610aa4610a113660046145ef565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff9485168152600783528390208351918201845254938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615159082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260208084015160ff169082015291810151151590820152606001610206565b6103f2611874565b610548610af73660046145ef565b611880565b6101fc601281565b6101fc610b123660046156c6565b611a35565b61041a610b253660046145ef565b611f6d565b61041a610b3836600461572a565b611f7e565b610b50610b4b36600461584a565b611f8f565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610206565b6000610b9082612047565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610bb785612047565b610bdf907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856158a3565b610be991906158ba565b90505b9392505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f805f2132000000000000000000000000000000000000000000000000000000001480610c8657507fffffffff0000000000000000000000000000000000000000000000000000000082167f9b645f4100000000000000000000000000000000000000000000000000000000145b80610cd257507fffffffff0000000000000000000000000000000000000000000000000000000082167f181f5a7700000000000000000000000000000000000000000000000000000000145b80610d1e57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6060610d3060026120e1565b905090565b610d3d6120ee565b6000610d4982806158f5565b9050905060005b81811015610e93576000610d6484806158f5565b83818110610d7457610d7461595d565b905060400201803603810190610d8a91906159b8565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610e829290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d50565b506000610ea360208401846158f5565b9050905060005b81811015610fe4576000610ec160208601866158f5565b83818110610ed157610ed161595d565b905060400201803603810190610ee791906159f5565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610fd39290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610eaa565b50505050565b610ff2612133565b60005b8151811015611028576110208282815181106110135761101361595d565b6020026020010151612184565b600101610ff5565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff160361108d578a93506110bb565b6110b88c8c7f0000000000000000000000000000000000000000000000000000000000000000610b85565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1684111561115f576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff169061118e8c8c84612356565b9050806020015194506111a48f8b8b8b8b6124ff565b92508585611224836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff81111561125a5761125a614716565b60405190808252806020026020018201604052801561129f57816020015b60408051808201909152600080825260208201528152602001906001900390816112785790505b50905060005b828110156112fc576112d78686838181106112c2576112c261595d565b9050602002016020810190610af791906145ef565b8282815181106112e9576112e961595d565b60209081029190910101526001016112a5565b50949350505050565b6000610d1e82612047565b611318612133565b61132181612882565b50565b61132c612133565b6110288282612d54565b60005473ffffffffffffffffffffffffffffffffffffffff163314611387576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61140c612133565b61102882826131ca565b600080600061145a87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061331192505050565b92509250925061146c3383858461332c565b600061147a85870187615a18565b905060005b8151811015611847576000600760008484815181106114a0576114a061595d565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff908116835282820193909352604091820160002082516060810184529054938416815260ff740100000000000000000000000000000000000000008504811692820192909252750100000000000000000000000000000000000000000090930416151590820181905290915061159b578282815181106115445761154461595d565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401611156565b60006115e8601283602001518686815181106115b9576115b961595d565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613484565b9050600660008585815181106116005761160061595d565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106116725761167261595d565b60200260200101516040015163ffffffff16101561169157505061183f565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106116d2576116d261595d565b60200260200101516040015163ffffffff16815250600660008686815181106116fd576116fd61595d565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106117955761179561595d565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a828686815181106117eb576117eb61595d565b6020026020010151604001516040516118349291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250505b60010161147f565b505050505050505050565b61185a612133565b61132181613547565b61186b612133565b611321816136d3565b6060610d30600b6120e1565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f000000000000000000000000000000000000000000000000000000000000000016906119429042615adf565b101561194e5792915050565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526007602090815260409182902082516060810184529054938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615801591830191909152806119ef5750805173ffffffffffffffffffffffffffffffffffffffff16155b156119fb575092915050565b6000611a06826137bd565b9050826020015163ffffffff16816020015163ffffffff161015611a2a5782611a2c565b805b95945050505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c01000000000000000000000000880485166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611c6f576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401611156565b611c8a611c8260808501606086016145ef565b600b9061394f565b611ce957611c9e60808401606085016145ef565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401611156565b6000611cf860408501856158f5565b9150611d54905082611d0d6020870187615af2565b905083611d1a8880615af2565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397e92505050565b6000611d6e611d6960808701606088016145ef565b612047565b90506000611d8187856101c00151613a3b565b9050600080808515611dc157611db5878b611da260808d0160608e016145ef565b88611db060408f018f6158f5565b613b3b565b91945092509050611de1565b6101a0870151611dde9063ffffffff16662386f26fc100006158a3565b92505b61010087015160009061ffff1615611e2557611e22886dffffffffffffffffffffffffffff607088901c16611e1960208e018e615af2565b90508a86613e13565b90505b61018088015160009067ffffffffffffffff16611e4e611e4860808e018e615af2565b8c613ec3565b600001518563ffffffff168b60a0015161ffff168e8060200190611e729190615af2565b611e7d9291506158a3565b8c6080015163ffffffff16611e929190615b57565b611e9c9190615b57565b611ea69190615b57565b611ec0906dffffffffffffffffffffffffffff89166158a3565b611eca91906158a3565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611f0491906145ef565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611f3f9067ffffffffffffffff16896158a3565b611f499190615b57565b611f539190615b57565b611f5d91906158ba565b9c9b505050505050505050505050565b611f75612133565b61132181613f84565b611f86612133565b61132181614048565b67ffffffffffffffff8116600090815260096020526040812054819060ff16611ff0576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401611156565b611ff984612047565b67ffffffffffffffff841660009081526009602052604090206001015461203b908590700100000000000000000000000000000000900463ffffffff16613a3b565b915091505b9250929050565b60008061205383611880565b9050806020015163ffffffff166000148061208b575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156120da576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401611156565b5192915050565b60606000610bec8361419a565b6120f960023361394f565b612131576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401611156565b565b60015473ffffffffffffffffffffffffffffffffffffffff163314612131576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061223d82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061234a908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b6040805180820190915260008082526020820152600083900361239757506040805180820190915267ffffffffffffffff8216815260006020820152610bec565b60006123a38486615b6a565b905060006123b48560048189615bb0565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161245157808060200190518101906124489190615bda565b92505050610bec565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016124cd576040518060400160405280828060200190518101906124b99190615c06565b815260006020909101529250610bec915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808616600090815260096020526040902060010154606091750100000000000000000000000000000000000000000090910460e01b90859081111561254f5761254f614716565b60405190808252806020026020018201604052801561258257816020015b606081526020019060019003908161256d5790505b50915060005b858110156128775760008585838181106125a4576125a461595d565b6125ba92602060409092020190810191506145ef565b905060008888848181106125d0576125d061595d565b90506020028101906125e29190615c1f565b6125f0906040810190615af2565b91505060208111156126a05767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff168111156126a0576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401611156565b612710848a8a868181106126b6576126b661595d565b90506020028101906126c89190615c1f565b6126d6906020810190615af2565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141f692505050565b67ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684528252808320815160c081018352905463ffffffff8082168352640100000000820481169483019490945268010000000000000000810461ffff16928201929092526a01000000000000000000008204831660608201526e010000000000000000000000000000820490921660808301527201000000000000000000000000000000000000900460ff16151560a082018190529091906128225767ffffffffffffffff8c166000908152600960205260409020547b01000000000000000000000000000000000000000000000000000000900463ffffffff16612828565b81606001515b6040805163ffffffff831660208201529192500160405160208183030381529060405287868151811061285d5761285d61595d565b602002602001018190525050505050806001019050612588565b505095945050505050565b60005b81518110156110285760008282815181106128a2576128a261595d565b6020026020010151905060008383815181106128c0576128c061595d565b60200260200101516000015190506000826020015190508167ffffffffffffffff16600014806128f9575061016081015163ffffffff16155b8061294b57506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061296a5750806060015163ffffffff1681610160015163ffffffff16115b156129ad576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401611156565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff00000000000000000000000000000000000000000000000000000000169003612a55578167ffffffffffffffff167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda4626582604051612a489190614f5e565b60405180910390a2612a98565b8167ffffffffffffffff167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051612a8f9190614f5e565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612885565b60005b82518110156130e1576000838281518110612d7457612d7461595d565b6020026020010151905060008160000151905060005b8260200151518110156130d357600083602001518281518110612daf57612daf61595d565b6020026020010151602001519050600084602001518381518110612dd557612dd561595d565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff1610612e4757815160208301516040517f0b4f67a200000000000000000000000000000000000000000000000000000000815263ffffffff928316600482015291166024820152604401611156565b602063ffffffff16826080015163ffffffff161015612ebc5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401611156565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906130c1908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612d8a565b505050806001019050612d57565b5060005b81518110156131c55760008282815181106131025761310261595d565b602002602001015160000151905060008383815181106131245761312461595d565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a350506001016130e5565b505050565b60005b825181101561326d576132038382815181106131eb576131eb61595d565b6020026020010151600b61424890919063ffffffff16565b156132655782818151811061321a5761321a61595d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016131cd565b5060005b81518110156131c5576132a782828151811061328f5761328f61595d565b6020026020010151600b61426a90919063ffffffff16565b15613309578181815181106132be576132be61595d565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101613271565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff1661347d576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401611156565b5050505050565b6000806134918486615c5d565b9050600060248260ff1611156134cb576134af602460ff8416615adf565b6134ba90600a615d96565b6134c490856158ba565b90506134f1565b6134d960ff83166024615adf565b6134e490600a615d96565b6134ee90856158a3565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115611a2c576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160005b81518110156135e257600082828151811061356c5761356c61595d565b6020026020010151905061358a81600261428c90919063ffffffff16565b156135d95760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010161354f565b50815160005b8151811015610fe45760008282815181106136055761360561595d565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613675576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61368060028261426a565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016135e8565b60005b81518110156110285760008282815181106136f3576136f361595d565b602002602001015160000151905060008383815181106137155761371561595d565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016136d6565b60408051808201909152600080825260208201526000826000015190506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384c9190615dbc565b50935050925050600082121561388e576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061390d8473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139029190615e0c565b876020015185613484565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff909216602083015250949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bec565b836040015163ffffffff168311156139d75760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401611156565b836020015161ffff16821115613a2c5760208401516040517fd88dddd60000000000000000000000000000000000000000000000000000000081526004810184905261ffff9091166024820152604401611156565b610fe4846102000151826141f6565b67ffffffffffffffff821660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169282019290925290831615613b33576000816020015163ffffffff1642613ad09190615adf565b90508363ffffffff16811115613b31576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff8516602482015260448101829052606401611156565b505b519392505050565b6000808083815b81811015613e05576000878783818110613b5e57613b5e61595d565b905060400201803603810190613b749190615e29565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613c94576101208d0151613c619061ffff16662386f26fc100006158a3565b613c6b9088615b57565b96508c610140015186613c7e9190615e62565b9550613c8b602086615e62565b94505050613dfd565b604081015160009061ffff1615613d4d5760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613cf0578351613ce990612047565b9050613cf3565b508a5b620186a0836040015161ffff16613d358660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166142ae90919063ffffffff16565b613d3f91906158a3565b613d4991906158ba565b9150505b6060820151613d5c9088615e62565b9650816080015186613d6e9190615e62565b8251909650600090613d8d9063ffffffff16662386f26fc100006158a3565b905080821015613dac57613da1818a615b57565b985050505050613dfd565b6000836020015163ffffffff16662386f26fc10000613dcb91906158a3565b905080831115613deb57613ddf818b615b57565b99505050505050613dfd565b613df5838b615b57565b995050505050505b600101613b42565b505096509650969350505050565b60008063ffffffff8316613e29610120866158a3565b613e35876101e0615b57565b613e3f9190615b57565b613e499190615b57565b905060008760c0015163ffffffff168860e0015161ffff1683613e6c91906158a3565b613e769190615b57565b61010089015190915061ffff16613e9d6dffffffffffffffffffffffffffff8916836158a3565b613ea791906158a3565b613eb790655af3107a40006158a3565b98975050505050505050565b60408051808201909152600080825260208201526000613eef858585610160015163ffffffff16612356565b9050826060015163ffffffff1681600001511115613f39576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015613f4d57508060200151155b15610be9576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613fd3576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156110285760008282815181106140685761406861595d565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a0180518589018051949098167fffffffffffffffffffffff00000000000000000000000000000000000000000090931683177401000000000000000000000000000000000000000060ff92831602177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000009415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a250505080600101905061404b565b6060816000018054806020026020016040519081016040528092919081815260200182805480156141ea57602002820191906000526020600020905b8154815260200190600101908083116141d6575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601611028576131c5816142eb565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff841661439e565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff8416614498565b6000610bec8373ffffffffffffffffffffffffffffffffffffffff84166144e7565b6000670de0b6b3a76400006142e1837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166158a3565b610bec91906158ba565b6000815160201461432a57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611156919061466e565b6000828060200190518101906143409190615c06565b905073ffffffffffffffffffffffffffffffffffffffff811180614365575061040081105b15610d1e57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611156919061466e565b600081815260018301602052604081205480156144875760006143c2600183615adf565b85549091506000906143d690600190615adf565b905080821461443b5760008660000182815481106143f6576143f661595d565b90600052602060002001549050808760000184815481106144195761441961595d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061444c5761444c615e7f565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d1e565b6000915050610d1e565b5092915050565b60008181526001830160205260408120546144df57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d1e565b506000610d1e565b6000818152600183016020526040812054801561448757600061450b600183615adf565b855490915060009061451f90600190615adf565b905081811461443b5760008660000182815481106143f6576143f661595d565b803573ffffffffffffffffffffffffffffffffffffffff8116811461456357600080fd5b919050565b60008060006060848603121561457d57600080fd5b6145868461453f565b92506020840135915061459b6040850161453f565b90509250925092565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461456357600080fd5b6000602082840312156145e657600080fd5b610bec826145a4565b60006020828403121561460157600080fd5b610bec8261453f565b6000815180845260005b8181101561463057602081850181015186830182015201614614565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610bec602083018461460a565b6020808252825182820181905260009190848201906040850190845b818110156146cf57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161469d565b50909695505050505050565b6000602082840312156146ed57600080fd5b813567ffffffffffffffff81111561470457600080fd5b820160408185031215610bec57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561476857614768614716565b60405290565b6040805190810167ffffffffffffffff8111828210171561476857614768614716565b604051610220810167ffffffffffffffff8111828210171561476857614768614716565b60405160c0810167ffffffffffffffff8111828210171561476857614768614716565b6040516060810167ffffffffffffffff8111828210171561476857614768614716565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561484257614842614716565b604052919050565b600067ffffffffffffffff82111561486457614864614716565b5060051b60200190565b801515811461132157600080fd5b80356145638161486e565b6000602080838503121561489a57600080fd5b823567ffffffffffffffff8111156148b157600080fd5b8301601f810185136148c257600080fd5b80356148d56148d08261484a565b6147fb565b81815260a091820283018401918482019190888411156148f457600080fd5b938501935b838510156149c75780858a0312156149115760008081fd5b614919614745565b6149228661453f565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146149575760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149905760008081fd5b9082015260606149a187820161453f565b908201526080868101356149b48161486e565b90820152835293840193918501916148f9565b50979650505050505050565b803567ffffffffffffffff8116811461456357600080fd5b60008083601f8401126149fd57600080fd5b50813567ffffffffffffffff811115614a1557600080fd5b60208301915083602082850101111561204057600080fd5b60008083601f840112614a3f57600080fd5b50813567ffffffffffffffff811115614a5757600080fd5b6020830191508360208260051b850101111561204057600080fd5b600080600080600080600080600060c08a8c031215614a9057600080fd5b614a998a6149d3565b9850614aa760208b0161453f565b975060408a0135965060608a013567ffffffffffffffff80821115614acb57600080fd5b614ad78d838e016149eb565b909850965060808c0135915080821115614af057600080fd5b614afc8d838e01614a2d565b909650945060a08c0135915080821115614b1557600080fd5b818c0191508c601f830112614b2957600080fd5b813581811115614b3857600080fd5b8d60208260061b8501011115614b4d57600080fd5b6020830194508093505050509295985092959850929598565b848152600060208515158184015260806040840152614b88608084018661460a565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614bf4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614be283835161460a565b94870194925090860190600101614ba8565b50909b9a5050505050505050505050565b60008060208385031215614c1857600080fd5b823567ffffffffffffffff811115614c2f57600080fd5b614c3b85828601614a2d565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614cb557614ca584835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614c64565b5091979650505050505050565b600060208284031215614cd457600080fd5b610bec826149d3565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610d1e565b803561ffff8116811461456357600080fd5b803563ffffffff8116811461456357600080fd5b60006020808385031215614d5157600080fd5b823567ffffffffffffffff811115614d6857600080fd5b8301601f81018513614d7957600080fd5b8035614d876148d08261484a565b8181526102409182028301840191848201919088841115614da757600080fd5b938501935b838510156149c75784890381811215614dc55760008081fd5b614dcd61476e565b614dd6876149d3565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215614e0b5760008081fd5b614e13614791565b9250614e2089890161487c565b83526040614e2f818a01614d18565b8a8501526060614e40818b01614d2a565b8286015260809150614e53828b01614d2a565b9085015260a0614e648a8201614d2a565b8286015260c09150614e77828b01614d18565b9085015260e0614e888a8201614d2a565b828601526101009150614e9c828b01614d18565b90850152610120614eae8a8201614d18565b828601526101409150614ec2828b01614d18565b90850152610160614ed48a8201614d2a565b828601526101809150614ee8828b01614d2a565b908501526101a0614efa8a82016149d3565b828601526101c09150614f0e828b01614d2a565b908501526101e0614f208a8201614d2a565b828601526102009150614f34828b0161487c565b90850152614f438983016145a4565b90840152508088019190915283529384019391850191614dac565b81511515815261022081016020830151614f7e602084018261ffff169052565b506040830151614f96604084018263ffffffff169052565b506060830151614fae606084018263ffffffff169052565b506080830151614fc6608084018263ffffffff169052565b5060a0830151614fdc60a084018261ffff169052565b5060c0830151614ff460c084018263ffffffff169052565b5060e083015161500a60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b600082601f8301126150d557600080fd5b813560206150e56148d08361484a565b82815260069290921b8401810191818101908684111561510457600080fd5b8286015b8481101561515157604081890312156151215760008081fd5b61512961476e565b615132826149d3565b815261513f85830161453f565b81860152835291830191604001615108565b509695505050505050565b6000806040838503121561516f57600080fd5b67ffffffffffffffff8335111561518557600080fd5b83601f84358501011261519757600080fd5b6151a76148d0843585013561484a565b8335840180358083526020808401939260059290921b909101018610156151cd57600080fd5b602085358601015b85358601803560051b016020018110156153da5767ffffffffffffffff813511156151ff57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a0301121561523857600080fd5b61524061476e565b61524c602083016149d3565b815267ffffffffffffffff6040830135111561526757600080fd5b88603f60408401358401011261527c57600080fd5b6152926148d0602060408501358501013561484a565b6020604084810135850182810135808552928401939260e00201018b10156152b957600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156153bb5760e0818d0312156152ec57600080fd5b6152f461476e565b6152fd8261453f565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f0301121561533157600080fd5b6153396147b5565b61534560208401614d2a565b815261535360408401614d2a565b602082015261536460608401614d18565b604082015261537560808401614d2a565b606082015261538660a08401614d2a565b608082015261539860c084013561486e565b60c083013560a0820152602082810191909152908452929092019160e0016152c3565b50806020840152505080855250506020830192506020810190506151d5565b5092505067ffffffffffffffff602084013511156153f757600080fd5b61540784602085013585016150c4565b90509250929050565b600082601f83011261542157600080fd5b813560206154316148d08361484a565b8083825260208201915060208460051b87010193508684111561545357600080fd5b602086015b84811015615151576154698161453f565b8352918301918301615458565b6000806040838503121561548957600080fd5b823567ffffffffffffffff808211156154a157600080fd5b6154ad86838701615410565b935060208501359150808211156154c357600080fd5b506154d085828601615410565b9150509250929050565b600080600080604085870312156154f057600080fd5b843567ffffffffffffffff8082111561550857600080fd5b615514888389016149eb565b9096509450602087013591508082111561552d57600080fd5b5061553a878288016149eb565b95989497509550505050565b6000806040838503121561555957600080fd5b615562836149d3565b91506154076020840161453f565b60006020828403121561558257600080fd5b813567ffffffffffffffff8082111561559a57600080fd5b90830190604082860312156155ae57600080fd5b6155b661476e565b8235828111156155c557600080fd5b6155d187828601615410565b8252506020830135828111156155e657600080fd5b6155f287828601615410565b60208301525095945050505050565b6000602080838503121561561457600080fd5b823567ffffffffffffffff81111561562b57600080fd5b8301601f8101851361563c57600080fd5b803561564a6148d08261484a565b81815260069190911b8201830190838101908783111561566957600080fd5b928401925b828410156156bb57604084890312156156875760008081fd5b61568f61476e565b6156988561453f565b81526156a58686016149d3565b818701528252604093909301929084019061566e565b979650505050505050565b600080604083850312156156d957600080fd5b6156e2836149d3565b9150602083013567ffffffffffffffff8111156156fe57600080fd5b830160a0818603121561571057600080fd5b809150509250929050565b60ff8116811461132157600080fd5b6000602080838503121561573d57600080fd5b823567ffffffffffffffff81111561575457600080fd5b8301601f8101851361576557600080fd5b80356157736148d08261484a565b81815260079190911b8201830190838101908783111561579257600080fd5b928401925b828410156156bb5783880360808112156157b15760008081fd5b6157b961476e565b6157c28661453f565b81526060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156157f65760008081fd5b6157fe6147d8565b925061580b88880161453f565b835260408088013561581c8161571b565b848a0152908701359061582e8261486e565b8301528087019190915282526080939093019290840190615797565b6000806040838503121561585d57600080fd5b6158668361453f565b9150615407602084016149d3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610d1e57610d1e615874565b6000826158f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261592a57600080fd5b83018035915067ffffffffffffffff82111561594557600080fd5b6020019150600681901b360382131561204057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461456357600080fd5b6000604082840312156159ca57600080fd5b6159d261476e565b6159db8361453f565b81526159e96020840161598c565b60208201529392505050565b600060408284031215615a0757600080fd5b615a0f61476e565b6159db836149d3565b60006020808385031215615a2b57600080fd5b823567ffffffffffffffff811115615a4257600080fd5b8301601f81018513615a5357600080fd5b8035615a616148d08261484a565b81815260609182028301840191848201919088841115615a8057600080fd5b938501935b838510156149c75780858a031215615a9d5760008081fd5b615aa56147d8565b615aae8661453f565b8152615abb87870161598c565b878201526040615acc818801614d2a565b9082015283529384019391850191615a85565b81810381811115610d1e57610d1e615874565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615b2757600080fd5b83018035915067ffffffffffffffff821115615b4257600080fd5b60200191503681900382131561204057600080fd5b80820180821115610d1e57610d1e615874565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156150bc5760049490940360031b84901b1690921692915050565b60008085851115615bc057600080fd5b83861115615bcd57600080fd5b5050820193919092039150565b600060408284031215615bec57600080fd5b615bf461476e565b8251815260208301516159e98161486e565b600060208284031215615c1857600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615c5357600080fd5b9190910192915050565b60ff8181168382160190811115610d1e57610d1e615874565b600181815b80851115615ccf57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615cb557615cb5615874565b80851615615cc257918102915b93841c9390800290615c7b565b509250929050565b600082615ce657506001610d1e565b81615cf357506000610d1e565b8160018114615d095760028114615d1357615d2f565b6001915050610d1e565b60ff841115615d2457615d24615874565b50506001821b610d1e565b5060208310610133831016604e8410600b8410161715615d52575081810a610d1e565b615d5c8383615c76565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615d8e57615d8e615874565b029392505050565b6000610bec8383615cd7565b805169ffffffffffffffffffff8116811461456357600080fd5b600080600080600060a08688031215615dd457600080fd5b615ddd86615da2565b9450602086015193506040860151925060608601519150615e0060808701615da2565b90509295509295909350565b600060208284031215615e1e57600080fd5b8151610bec8161571b565b600060408284031215615e3b57600080fd5b615e4361476e565b615e4c8361453f565b8152602083013560208201528091505092915050565b63ffffffff81811683821601908082111561449157614491615874565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI @@ -710,6 +710,28 @@ func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector u return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } +func (_FeeQuoter *FeeQuoterCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FeeQuoter.Contract.SupportsInterface(&_FeeQuoter.CallOpts, interfaceId) +} + +func (_FeeQuoter *FeeQuoterCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FeeQuoter.Contract.SupportsInterface(&_FeeQuoter.CallOpts, interfaceId) +} + func (_FeeQuoter *FeeQuoterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} err := _FeeQuoter.contract.Call(opts, &out, "typeAndVersion") @@ -2949,6 +2971,8 @@ type FeeQuoterInterface interface { error) + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index d839ed59f60..ded2c5431da 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -6,7 +6,7 @@ ccip_encoding_utils: ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEnc ccip_home: ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin 02cb75b4274a5be7f4006cf2b72cc09e77eb6dba4c1a9c720af86668ff8ea1df ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin b368699ae7dbee7c21d049a641642837f18ce2cc8d4ece69509f205de673108e ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 8a0869d14bb5247fbc6d836fc20d123358373ed688e0d3b387d59e7d05496fea +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin aee49c9246d5903e68b175516b3cdfdec5df23e25d53d604cd382b6bc0bf34f7 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 1067f557abeb5570f1da7f050ea982ffad0f35dc064e668a8a0e6af128df490c 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 ec2d3a92348d8e7b8f0d359b62a45157b9d2c750c01fbcf991826c4392f6e218 diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go index 7c0f421526e..8fadeb40e08 100644 --- a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -3416,6 +3416,63 @@ func (_c *FeeQuoterInterface_SetReportPermissions_Call) RunAndReturn(run func(*b return _c } +// SupportsInterface provides a mock function with given fields: opts, interfaceId +func (_m *FeeQuoterInterface) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + ret := _m.Called(opts, interfaceId) + + if len(ret) == 0 { + panic("no return value specified for SupportsInterface") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, [4]byte) (bool, error)); ok { + return rf(opts, interfaceId) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, [4]byte) bool); ok { + r0 = rf(opts, interfaceId) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, [4]byte) error); ok { + r1 = rf(opts, interfaceId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_SupportsInterface_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SupportsInterface' +type FeeQuoterInterface_SupportsInterface_Call struct { + *mock.Call +} + +// SupportsInterface is a helper method to define mock.On call +// - opts *bind.CallOpts +// - interfaceId [4]byte +func (_e *FeeQuoterInterface_Expecter) SupportsInterface(opts interface{}, interfaceId interface{}) *FeeQuoterInterface_SupportsInterface_Call { + return &FeeQuoterInterface_SupportsInterface_Call{Call: _e.mock.On("SupportsInterface", opts, interfaceId)} +} + +func (_c *FeeQuoterInterface_SupportsInterface_Call) Run(run func(opts *bind.CallOpts, interfaceId [4]byte)) *FeeQuoterInterface_SupportsInterface_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].([4]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_SupportsInterface_Call) Return(_a0 bool, _a1 error) *FeeQuoterInterface_SupportsInterface_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_SupportsInterface_Call) RunAndReturn(run func(*bind.CallOpts, [4]byte) (bool, error)) *FeeQuoterInterface_SupportsInterface_Call { + _c.Call.Return(run) + return _c +} + // TransferOwnership provides a mock function with given fields: opts, to func (_m *FeeQuoterInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { ret := _m.Called(opts, to) From 030fd7c5309b43148a637fd762bf346467275bc6 Mon Sep 17 00:00:00 2001 From: ilija42 <57732589+ilija42@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:29:55 -0800 Subject: [PATCH 05/55] Bump common and fix Chain Writer to match common CW name (#15429) * Bump chainlink-common and fix Chain Writer to match common Contract Writer * Generate mocks and add changeset * Disable generated bindings GetLatestValue tests * Bump solana --- .changeset/wet-bags-clean.md | 5 + .mockery.yaml | 2 +- .../ccip/ocrimpls/contract_transmitter.go | 8 +- .../capabilities/ccip/oraclecreator/plugin.go | 12 +- .../targets/mocks/chain_writer.go | 435 ------------------ .../targets/mocks/contract_writer.go | 435 ++++++++++++++++++ core/capabilities/targets/write_target.go | 4 +- .../capabilities/targets/write_target_test.go | 2 +- core/scripts/go.mod | 13 +- core/scripts/go.sum | 28 +- .../ocr2/plugins/generic/relayerset_test.go | 2 +- core/services/relay/dummy/relayer.go | 2 +- .../relay/evm/bindings/chain_reader_tester.go | 2 +- .../relay/evm/chain_components_test.go | 5 +- core/services/relay/evm/chain_writer.go | 2 +- .../chain_writer_historical_wrapper_test.go | 9 +- core/services/relay/evm/evm.go | 2 +- .../evm/evmtesting/bindings_test_adapter.go | 18 +- .../chain_components_interface_tester.go | 4 +- core/services/relay/evm/write_target.go | 2 +- core/web/testutils/mock_relayer.go | 2 +- deployment/go.mod | 14 +- deployment/go.sum | 28 +- go.mod | 28 +- go.sum | 60 +-- .../contracts/ccipreader_test.go | 4 +- integration-tests/go.mod | 12 +- integration-tests/go.sum | 28 +- integration-tests/load/go.mod | 12 +- integration-tests/load/go.sum | 28 +- integration-tests/smoke/ccip/ccip_rmn_test.go | 4 +- 31 files changed, 609 insertions(+), 603 deletions(-) create mode 100644 .changeset/wet-bags-clean.md delete mode 100644 core/capabilities/targets/mocks/chain_writer.go create mode 100644 core/capabilities/targets/mocks/contract_writer.go diff --git a/.changeset/wet-bags-clean.md b/.changeset/wet-bags-clean.md new file mode 100644 index 00000000000..53da05426c9 --- /dev/null +++ b/.changeset/wet-bags-clean.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Change ChainWriter naming to ContractWriter to consolidate Relayer chain interfaces #internal diff --git a/.mockery.yaml b/.mockery.yaml index 1cb8c375ba0..dd9024cc066 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -348,7 +348,7 @@ packages: Codec: config: dir: core/services/relay/evm/mocks - ChainWriter: + ContractWriter: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp: config: dir: core/gethwrappers/ccip/mocks/ diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index d3ca35bbe83..7bb64d99eb6 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -56,7 +56,7 @@ func ToExecCalldata(rawReportCtx [3][32]byte, report []byte, _, _ [][32]byte, _ var _ ocr3types.ContractTransmitter[[]byte] = &commitTransmitter[[]byte]{} type commitTransmitter[RI any] struct { - cw commontypes.ChainWriter + cw commontypes.ContractWriter fromAccount ocrtypes.Account contractName string method string @@ -65,7 +65,7 @@ type commitTransmitter[RI any] struct { } func XXXNewContractTransmitterTestsOnly[RI any]( - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, fromAccount ocrtypes.Account, contractName string, method string, @@ -83,7 +83,7 @@ func XXXNewContractTransmitterTestsOnly[RI any]( } func NewCommitContractTransmitter[RI any]( - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, ) ocr3types.ContractTransmitter[RI] { @@ -98,7 +98,7 @@ func NewCommitContractTransmitter[RI any]( } func NewExecContractTransmitter[RI any]( - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, ) ocr3types.ContractTransmitter[RI] { diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index a5063eb8d1c..6b63491f8e6 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -222,8 +222,8 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( config cctypes.OCR3ConfigWithMeta, destRelayID types.RelayID, contractReaders map[cciptypes.ChainSelector]types.ContractReader, - chainWriters map[cciptypes.ChainSelector]types.ChainWriter, - destChainWriter types.ChainWriter, + chainWriters map[cciptypes.ChainSelector]types.ContractWriter, + destChainWriter types.ContractWriter, destFromAccounts []string, publicConfig ocr3confighelper.PublicConfig, ) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { @@ -302,7 +302,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( chainFamily string, ) ( map[cciptypes.ChainSelector]types.ContractReader, - map[cciptypes.ChainSelector]types.ChainWriter, + map[cciptypes.ChainSelector]types.ContractWriter, error, ) { ofc, err := decodeAndValidateOffchainConfig(pluginType, publicCfg) @@ -325,7 +325,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( } contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) - chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) + chainWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) for relayID, relayer := range i.relayers { chainID := relayID.ChainID @@ -481,7 +481,7 @@ func createChainWriter( transmitters map[types.RelayID][]string, execBatchGasLimit uint64, chainFamily string, -) (types.ChainWriter, error) { +) (types.ContractWriter, error) { var fromAddress common.Address transmitter, ok := transmitters[types.NewRelayID(chainFamily, chainID)] if ok { @@ -503,7 +503,7 @@ func createChainWriter( return nil, fmt.Errorf("failed to marshal chain writer config: %w", err) } - cw, err := relayer.NewChainWriter(ctx, chainWriterConfig) + cw, err := relayer.NewContractWriter(ctx, chainWriterConfig) if err != nil { return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chainID, err) } diff --git a/core/capabilities/targets/mocks/chain_writer.go b/core/capabilities/targets/mocks/chain_writer.go deleted file mode 100644 index 5d7102fd4df..00000000000 --- a/core/capabilities/targets/mocks/chain_writer.go +++ /dev/null @@ -1,435 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package mocks - -import ( - context "context" - big "math/big" - - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -// ChainWriter is an autogenerated mock type for the ChainWriter type -type ChainWriter struct { - mock.Mock -} - -type ChainWriter_Expecter struct { - mock *mock.Mock -} - -func (_m *ChainWriter) EXPECT() *ChainWriter_Expecter { - return &ChainWriter_Expecter{mock: &_m.Mock} -} - -// Close provides a mock function with given fields: -func (_m *ChainWriter) Close() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Close") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type ChainWriter_Close_Call struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) Close() *ChainWriter_Close_Call { - return &ChainWriter_Close_Call{Call: _e.mock.On("Close")} -} - -func (_c *ChainWriter_Close_Call) Run(run func()) *ChainWriter_Close_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_Close_Call) Return(_a0 error) *ChainWriter_Close_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Close_Call) RunAndReturn(run func() error) *ChainWriter_Close_Call { - _c.Call.Return(run) - return _c -} - -// GetFeeComponents provides a mock function with given fields: ctx -func (_m *ChainWriter) GetFeeComponents(ctx context.Context) (*types.ChainFeeComponents, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for GetFeeComponents") - } - - var r0 *types.ChainFeeComponents - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*types.ChainFeeComponents, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *types.ChainFeeComponents); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ChainFeeComponents) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ChainWriter_GetFeeComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeComponents' -type ChainWriter_GetFeeComponents_Call struct { - *mock.Call -} - -// GetFeeComponents is a helper method to define mock.On call -// - ctx context.Context -func (_e *ChainWriter_Expecter) GetFeeComponents(ctx interface{}) *ChainWriter_GetFeeComponents_Call { - return &ChainWriter_GetFeeComponents_Call{Call: _e.mock.On("GetFeeComponents", ctx)} -} - -func (_c *ChainWriter_GetFeeComponents_Call) Run(run func(ctx context.Context)) *ChainWriter_GetFeeComponents_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ChainWriter_GetFeeComponents_Call) Return(_a0 *types.ChainFeeComponents, _a1 error) *ChainWriter_GetFeeComponents_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ChainWriter_GetFeeComponents_Call) RunAndReturn(run func(context.Context) (*types.ChainFeeComponents, error)) *ChainWriter_GetFeeComponents_Call { - _c.Call.Return(run) - return _c -} - -// GetTransactionStatus provides a mock function with given fields: ctx, transactionID -func (_m *ChainWriter) GetTransactionStatus(ctx context.Context, transactionID string) (types.TransactionStatus, error) { - ret := _m.Called(ctx, transactionID) - - if len(ret) == 0 { - panic("no return value specified for GetTransactionStatus") - } - - var r0 types.TransactionStatus - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (types.TransactionStatus, error)); ok { - return rf(ctx, transactionID) - } - if rf, ok := ret.Get(0).(func(context.Context, string) types.TransactionStatus); ok { - r0 = rf(ctx, transactionID) - } else { - r0 = ret.Get(0).(types.TransactionStatus) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, transactionID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ChainWriter_GetTransactionStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransactionStatus' -type ChainWriter_GetTransactionStatus_Call struct { - *mock.Call -} - -// GetTransactionStatus is a helper method to define mock.On call -// - ctx context.Context -// - transactionID string -func (_e *ChainWriter_Expecter) GetTransactionStatus(ctx interface{}, transactionID interface{}) *ChainWriter_GetTransactionStatus_Call { - return &ChainWriter_GetTransactionStatus_Call{Call: _e.mock.On("GetTransactionStatus", ctx, transactionID)} -} - -func (_c *ChainWriter_GetTransactionStatus_Call) Run(run func(ctx context.Context, transactionID string)) *ChainWriter_GetTransactionStatus_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ChainWriter_GetTransactionStatus_Call) Return(_a0 types.TransactionStatus, _a1 error) *ChainWriter_GetTransactionStatus_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ChainWriter_GetTransactionStatus_Call) RunAndReturn(run func(context.Context, string) (types.TransactionStatus, error)) *ChainWriter_GetTransactionStatus_Call { - _c.Call.Return(run) - return _c -} - -// HealthReport provides a mock function with given fields: -func (_m *ChainWriter) HealthReport() map[string]error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HealthReport") - } - - var r0 map[string]error - if rf, ok := ret.Get(0).(func() map[string]error); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]error) - } - } - - return r0 -} - -// ChainWriter_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type ChainWriter_HealthReport_Call struct { - *mock.Call -} - -// HealthReport is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) HealthReport() *ChainWriter_HealthReport_Call { - return &ChainWriter_HealthReport_Call{Call: _e.mock.On("HealthReport")} -} - -func (_c *ChainWriter_HealthReport_Call) Run(run func()) *ChainWriter_HealthReport_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_HealthReport_Call) Return(_a0 map[string]error) *ChainWriter_HealthReport_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_HealthReport_Call) RunAndReturn(run func() map[string]error) *ChainWriter_HealthReport_Call { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *ChainWriter) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// ChainWriter_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type ChainWriter_Name_Call struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) Name() *ChainWriter_Name_Call { - return &ChainWriter_Name_Call{Call: _e.mock.On("Name")} -} - -func (_c *ChainWriter_Name_Call) Run(run func()) *ChainWriter_Name_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_Name_Call) Return(_a0 string) *ChainWriter_Name_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Name_Call) RunAndReturn(run func() string) *ChainWriter_Name_Call { - _c.Call.Return(run) - return _c -} - -// Ready provides a mock function with given fields: -func (_m *ChainWriter) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type ChainWriter_Ready_Call struct { - *mock.Call -} - -// Ready is a helper method to define mock.On call -func (_e *ChainWriter_Expecter) Ready() *ChainWriter_Ready_Call { - return &ChainWriter_Ready_Call{Call: _e.mock.On("Ready")} -} - -func (_c *ChainWriter_Ready_Call) Run(run func()) *ChainWriter_Ready_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainWriter_Ready_Call) Return(_a0 error) *ChainWriter_Ready_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Ready_Call) RunAndReturn(run func() error) *ChainWriter_Ready_Call { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: _a0 -func (_m *ChainWriter) Start(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for Start") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type ChainWriter_Start_Call struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - _a0 context.Context -func (_e *ChainWriter_Expecter) Start(_a0 interface{}) *ChainWriter_Start_Call { - return &ChainWriter_Start_Call{Call: _e.mock.On("Start", _a0)} -} - -func (_c *ChainWriter_Start_Call) Run(run func(_a0 context.Context)) *ChainWriter_Start_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ChainWriter_Start_Call) Return(_a0 error) *ChainWriter_Start_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_Start_Call) RunAndReturn(run func(context.Context) error) *ChainWriter_Start_Call { - _c.Call.Return(run) - return _c -} - -// SubmitTransaction provides a mock function with given fields: ctx, contractName, method, args, transactionID, toAddress, meta, value -func (_m *ChainWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { - ret := _m.Called(ctx, contractName, method, args, transactionID, toAddress, meta, value) - - if len(ret) == 0 { - panic("no return value specified for SubmitTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error); ok { - r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ChainWriter_SubmitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubmitTransaction' -type ChainWriter_SubmitTransaction_Call struct { - *mock.Call -} - -// SubmitTransaction is a helper method to define mock.On call -// - ctx context.Context -// - contractName string -// - method string -// - args any -// - transactionID string -// - toAddress string -// - meta *types.TxMeta -// - value *big.Int -func (_e *ChainWriter_Expecter) SubmitTransaction(ctx interface{}, contractName interface{}, method interface{}, args interface{}, transactionID interface{}, toAddress interface{}, meta interface{}, value interface{}) *ChainWriter_SubmitTransaction_Call { - return &ChainWriter_SubmitTransaction_Call{Call: _e.mock.On("SubmitTransaction", ctx, contractName, method, args, transactionID, toAddress, meta, value)} -} - -func (_c *ChainWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ChainWriter_SubmitTransaction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(any), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) - }) - return _c -} - -func (_c *ChainWriter_SubmitTransaction_Call) Return(_a0 error) *ChainWriter_SubmitTransaction_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error) *ChainWriter_SubmitTransaction_Call { - _c.Call.Return(run) - return _c -} - -// NewChainWriter creates a new instance of ChainWriter. 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 NewChainWriter(t interface { - mock.TestingT - Cleanup(func()) -}) *ChainWriter { - mock := &ChainWriter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/targets/mocks/contract_writer.go b/core/capabilities/targets/mocks/contract_writer.go new file mode 100644 index 00000000000..c6128e68fc7 --- /dev/null +++ b/core/capabilities/targets/mocks/contract_writer.go @@ -0,0 +1,435 @@ +// Code generated by mockery v2.46.3. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// ContractWriter is an autogenerated mock type for the ContractWriter type +type ContractWriter struct { + mock.Mock +} + +type ContractWriter_Expecter struct { + mock *mock.Mock +} + +func (_m *ContractWriter) EXPECT() *ContractWriter_Expecter { + return &ContractWriter_Expecter{mock: &_m.Mock} +} + +// Close provides a mock function with given fields: +func (_m *ContractWriter) Close() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Close") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' +type ContractWriter_Close_Call struct { + *mock.Call +} + +// Close is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) Close() *ContractWriter_Close_Call { + return &ContractWriter_Close_Call{Call: _e.mock.On("Close")} +} + +func (_c *ContractWriter_Close_Call) Run(run func()) *ContractWriter_Close_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_Close_Call) Return(_a0 error) *ContractWriter_Close_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Close_Call) RunAndReturn(run func() error) *ContractWriter_Close_Call { + _c.Call.Return(run) + return _c +} + +// GetFeeComponents provides a mock function with given fields: ctx +func (_m *ContractWriter) GetFeeComponents(ctx context.Context) (*types.ChainFeeComponents, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetFeeComponents") + } + + var r0 *types.ChainFeeComponents + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*types.ChainFeeComponents, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *types.ChainFeeComponents); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ChainFeeComponents) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractWriter_GetFeeComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeComponents' +type ContractWriter_GetFeeComponents_Call struct { + *mock.Call +} + +// GetFeeComponents is a helper method to define mock.On call +// - ctx context.Context +func (_e *ContractWriter_Expecter) GetFeeComponents(ctx interface{}) *ContractWriter_GetFeeComponents_Call { + return &ContractWriter_GetFeeComponents_Call{Call: _e.mock.On("GetFeeComponents", ctx)} +} + +func (_c *ContractWriter_GetFeeComponents_Call) Run(run func(ctx context.Context)) *ContractWriter_GetFeeComponents_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ContractWriter_GetFeeComponents_Call) Return(_a0 *types.ChainFeeComponents, _a1 error) *ContractWriter_GetFeeComponents_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractWriter_GetFeeComponents_Call) RunAndReturn(run func(context.Context) (*types.ChainFeeComponents, error)) *ContractWriter_GetFeeComponents_Call { + _c.Call.Return(run) + return _c +} + +// GetTransactionStatus provides a mock function with given fields: ctx, transactionID +func (_m *ContractWriter) GetTransactionStatus(ctx context.Context, transactionID string) (types.TransactionStatus, error) { + ret := _m.Called(ctx, transactionID) + + if len(ret) == 0 { + panic("no return value specified for GetTransactionStatus") + } + + var r0 types.TransactionStatus + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (types.TransactionStatus, error)); ok { + return rf(ctx, transactionID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) types.TransactionStatus); ok { + r0 = rf(ctx, transactionID) + } else { + r0 = ret.Get(0).(types.TransactionStatus) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, transactionID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractWriter_GetTransactionStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransactionStatus' +type ContractWriter_GetTransactionStatus_Call struct { + *mock.Call +} + +// GetTransactionStatus is a helper method to define mock.On call +// - ctx context.Context +// - transactionID string +func (_e *ContractWriter_Expecter) GetTransactionStatus(ctx interface{}, transactionID interface{}) *ContractWriter_GetTransactionStatus_Call { + return &ContractWriter_GetTransactionStatus_Call{Call: _e.mock.On("GetTransactionStatus", ctx, transactionID)} +} + +func (_c *ContractWriter_GetTransactionStatus_Call) Run(run func(ctx context.Context, transactionID string)) *ContractWriter_GetTransactionStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *ContractWriter_GetTransactionStatus_Call) Return(_a0 types.TransactionStatus, _a1 error) *ContractWriter_GetTransactionStatus_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractWriter_GetTransactionStatus_Call) RunAndReturn(run func(context.Context, string) (types.TransactionStatus, error)) *ContractWriter_GetTransactionStatus_Call { + _c.Call.Return(run) + return _c +} + +// HealthReport provides a mock function with given fields: +func (_m *ContractWriter) HealthReport() map[string]error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HealthReport") + } + + var r0 map[string]error + if rf, ok := ret.Get(0).(func() map[string]error); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]error) + } + } + + return r0 +} + +// ContractWriter_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' +type ContractWriter_HealthReport_Call struct { + *mock.Call +} + +// HealthReport is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) HealthReport() *ContractWriter_HealthReport_Call { + return &ContractWriter_HealthReport_Call{Call: _e.mock.On("HealthReport")} +} + +func (_c *ContractWriter_HealthReport_Call) Run(run func()) *ContractWriter_HealthReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_HealthReport_Call) Return(_a0 map[string]error) *ContractWriter_HealthReport_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_HealthReport_Call) RunAndReturn(run func() map[string]error) *ContractWriter_HealthReport_Call { + _c.Call.Return(run) + return _c +} + +// Name provides a mock function with given fields: +func (_m *ContractWriter) Name() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Name") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// ContractWriter_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' +type ContractWriter_Name_Call struct { + *mock.Call +} + +// Name is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) Name() *ContractWriter_Name_Call { + return &ContractWriter_Name_Call{Call: _e.mock.On("Name")} +} + +func (_c *ContractWriter_Name_Call) Run(run func()) *ContractWriter_Name_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_Name_Call) Return(_a0 string) *ContractWriter_Name_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Name_Call) RunAndReturn(run func() string) *ContractWriter_Name_Call { + _c.Call.Return(run) + return _c +} + +// Ready provides a mock function with given fields: +func (_m *ContractWriter) Ready() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Ready") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' +type ContractWriter_Ready_Call struct { + *mock.Call +} + +// Ready is a helper method to define mock.On call +func (_e *ContractWriter_Expecter) Ready() *ContractWriter_Ready_Call { + return &ContractWriter_Ready_Call{Call: _e.mock.On("Ready")} +} + +func (_c *ContractWriter_Ready_Call) Run(run func()) *ContractWriter_Ready_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ContractWriter_Ready_Call) Return(_a0 error) *ContractWriter_Ready_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Ready_Call) RunAndReturn(run func() error) *ContractWriter_Ready_Call { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function with given fields: _a0 +func (_m *ContractWriter) Start(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type ContractWriter_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - _a0 context.Context +func (_e *ContractWriter_Expecter) Start(_a0 interface{}) *ContractWriter_Start_Call { + return &ContractWriter_Start_Call{Call: _e.mock.On("Start", _a0)} +} + +func (_c *ContractWriter_Start_Call) Run(run func(_a0 context.Context)) *ContractWriter_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ContractWriter_Start_Call) Return(_a0 error) *ContractWriter_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_Start_Call) RunAndReturn(run func(context.Context) error) *ContractWriter_Start_Call { + _c.Call.Return(run) + return _c +} + +// SubmitTransaction provides a mock function with given fields: ctx, contractName, method, args, transactionID, toAddress, meta, value +func (_m *ContractWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { + ret := _m.Called(ctx, contractName, method, args, transactionID, toAddress, meta, value) + + if len(ret) == 0 { + panic("no return value specified for SubmitTransaction") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error); ok { + r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractWriter_SubmitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubmitTransaction' +type ContractWriter_SubmitTransaction_Call struct { + *mock.Call +} + +// SubmitTransaction is a helper method to define mock.On call +// - ctx context.Context +// - contractName string +// - method string +// - args any +// - transactionID string +// - toAddress string +// - meta *types.TxMeta +// - value *big.Int +func (_e *ContractWriter_Expecter) SubmitTransaction(ctx interface{}, contractName interface{}, method interface{}, args interface{}, transactionID interface{}, toAddress interface{}, meta interface{}, value interface{}) *ContractWriter_SubmitTransaction_Call { + return &ContractWriter_SubmitTransaction_Call{Call: _e.mock.On("SubmitTransaction", ctx, contractName, method, args, transactionID, toAddress, meta, value)} +} + +func (_c *ContractWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ContractWriter_SubmitTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(any), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) + }) + return _c +} + +func (_c *ContractWriter_SubmitTransaction_Call) Return(_a0 error) *ContractWriter_SubmitTransaction_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error) *ContractWriter_SubmitTransaction_Call { + _c.Call.Return(run) + return _c +} + +// NewContractWriter creates a new instance of ContractWriter. 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 NewContractWriter(t interface { + mock.TestingT + Cleanup(func()) +}) *ContractWriter { + mock := &ContractWriter{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 8fe0d58018a..09a0bbd2b36 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -31,7 +31,7 @@ const transactionStatusCheckInterval = 2 * time.Second type WriteTarget struct { cr ContractValueGetter - cw commontypes.ChainWriter + cw commontypes.ContractWriter binding commontypes.BoundContract forwarderAddress string // The minimum amount of gas that the receiver contract must get to process the forwarder report @@ -67,7 +67,7 @@ func NewWriteTarget( lggr logger.Logger, id string, cr ContractValueGetter, - cw commontypes.ChainWriter, + cw commontypes.ContractWriter, forwarderAddress string, txGasLimit uint64, ) *WriteTarget { diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go index 801bdf2ea9a..a702d78cb5d 100644 --- a/core/capabilities/targets/write_target_test.go +++ b/core/capabilities/targets/write_target_test.go @@ -27,7 +27,7 @@ func TestWriteTarget(t *testing.T) { lggr := logger.TestLogger(t) ctx := context.Background() - cw := mocks.NewChainWriter(t) + cw := mocks.NewContractWriter(t) cr := mocks.NewContractValueGetter(t) forwarderA := testutils.NewAddress() diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 9799b070f86..94eea2b4b3a 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/core/scripts -go 1.23 +go 1.23.3 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 @@ -265,7 +265,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/onsi/ginkgo/v2 v2.20.1 // indirect - github.com/onsi/gomega v1.34.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -297,14 +296,14 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect github.com/smartcontractkit/chain-selectors v1.0.31 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 74eff9fb62a..e312f248ceb 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -181,10 +181,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -1140,12 +1140,12 @@ github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 h1:A/qi1YCY/9V9i/sthhizZCA0EECAcBfDKeA2w27H5fo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= @@ -1154,10 +1154,10 @@ github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 h1:gkrjGJAtbKMOliJPaZ73EyJmO8AyDVi80+PEJocRMn4= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749/go.mod h1:nkIegLHodyrrZguxkYEHcNw2vAXv8H8xlCoLzwylcL0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= diff --git a/core/services/ocr2/plugins/generic/relayerset_test.go b/core/services/ocr2/plugins/generic/relayerset_test.go index 44ed216520f..cd9d28ffd60 100644 --- a/core/services/ocr2/plugins/generic/relayerset_test.go +++ b/core/services/ocr2/plugins/generic/relayerset_test.go @@ -150,7 +150,7 @@ func (t *TestRelayer) Ready() error { panic("implement me") } func (t *TestRelayer) HealthReport() map[string]error { panic("implement me") } -func (t *TestRelayer) NewChainWriter(_ context.Context, _ []byte) (types.ChainWriter, error) { +func (t *TestRelayer) NewContractWriter(_ context.Context, _ []byte) (types.ContractWriter, error) { panic("implement me") } diff --git a/core/services/relay/dummy/relayer.go b/core/services/relay/dummy/relayer.go index 3275272b46f..ba65d10e911 100644 --- a/core/services/relay/dummy/relayer.go +++ b/core/services/relay/dummy/relayer.go @@ -31,7 +31,7 @@ func NewRelayer(lggr logger.Logger, chainID string) loop.Relayer { return &relayer{lggr, chainID} } -func (r *relayer) NewChainWriter(ctx context.Context, chainWriterConfig []byte) (types.ChainWriter, error) { +func (r *relayer) NewContractWriter(ctx context.Context, chainWriterConfig []byte) (types.ContractWriter, error) { return nil, nil } diff --git a/core/services/relay/evm/bindings/chain_reader_tester.go b/core/services/relay/evm/bindings/chain_reader_tester.go index f15f1431679..e5299b0d59a 100644 --- a/core/services/relay/evm/bindings/chain_reader_tester.go +++ b/core/services/relay/evm/bindings/chain_reader_tester.go @@ -13,7 +13,7 @@ import ( type ChainReaderTester struct { BoundContract types.BoundContract ContractReader types.ContractReader - ChainWriter types.ChainWriter + ChainWriter types.ContractWriter } type AccountStruct struct { diff --git a/core/services/relay/evm/chain_components_test.go b/core/services/relay/evm/chain_components_test.go index f8174017c22..2fcdad0184c 100644 --- a/core/services/relay/evm/chain_components_test.go +++ b/core/services/relay/evm/chain_components_test.go @@ -22,6 +22,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -208,6 +209,8 @@ func TestContractReaderEventsInitValidation(t *testing.T) { func TestChainComponents(t *testing.T) { t.Parallel() it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}} + // TODO, generated binding tests are broken + it.DisableTests([]string{interfacetests.ContractReaderGetLatestValue}) it.Init(t) // add new subtests here so that it can be run on real chains too @@ -310,7 +313,7 @@ func (h *helper) ChainReaderEVMClient(ctx context.Context, t *testing.T, ht logp return cwh } -func (h *helper) WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter { +func (h *helper) WrappedChainWriter(cw clcommontypes.ContractWriter, client client.Client) clcommontypes.ContractWriter { cwhw := evm.NewChainWriterHistoricalWrapper(cw, client.(*evm.ClientWithContractHistory)) return cwhw } diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index 779a13de90c..ab82a67084c 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -26,7 +26,7 @@ import ( type ChainWriterService interface { services.ServiceCtx - commontypes.ChainWriter + commontypes.ContractWriter } // Compile-time assertion that chainWriter implements the ChainWriterService interface. diff --git a/core/services/relay/evm/chain_writer_historical_wrapper_test.go b/core/services/relay/evm/chain_writer_historical_wrapper_test.go index 233d7bc2e2f..3e661b553e2 100644 --- a/core/services/relay/evm/chain_writer_historical_wrapper_test.go +++ b/core/services/relay/evm/chain_writer_historical_wrapper_test.go @@ -2,7 +2,6 @@ package evm import ( "context" - "math/big" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -15,12 +14,12 @@ import ( // Since the geth simulated backend doesn't support historical data, we use this // thin wrapper. type ChainWriterHistoricalWrapper struct { - commontypes.ChainWriter + commontypes.ContractWriter cwh *ClientWithContractHistory } -func NewChainWriterHistoricalWrapper(cw commontypes.ChainWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper { - return &ChainWriterHistoricalWrapper{ChainWriter: cw, cwh: cwh} +func NewChainWriterHistoricalWrapper(cw commontypes.ContractWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper { + return &ChainWriterHistoricalWrapper{ContractWriter: cw, cwh: cwh} } func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, contractName, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error { @@ -38,7 +37,7 @@ func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, return err } } - return cwhw.ChainWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) + return cwhw.ContractWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) } func (cwhw *ChainWriterHistoricalWrapper) getPrimitiveValueIfPossible(args any) (bool, uint64) { diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index cb97155473f..847b5bb72d9 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -845,7 +845,7 @@ func generateTransmitterFrom(ctx context.Context, rargs commontypes.RelayArgs, e return transmitter, nil } -func (r *Relayer) NewChainWriter(_ context.Context, config []byte) (commontypes.ChainWriter, error) { +func (r *Relayer) NewContractWriter(_ context.Context, config []byte) (commontypes.ContractWriter, 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) diff --git a/core/services/relay/evm/evmtesting/bindings_test_adapter.go b/core/services/relay/evm/evmtesting/bindings_test_adapter.go index 3dd625266ad..6c391aa0a7f 100644 --- a/core/services/relay/evm/evmtesting/bindings_test_adapter.go +++ b/core/services/relay/evm/evmtesting/bindings_test_adapter.go @@ -146,23 +146,23 @@ func (b bindingClientTester) addDefaultBindings(t *testing.T) { if chainReaderTester == nil { chainReaderTester = &bindings.ChainReaderTester{ BoundContract: binding, - ChainWriter: b.bindingsMapping.chainWriterProxy.ChainWriter, + ChainWriter: b.bindingsMapping.chainWriterProxy.ContractWriter, } b.bindingsMapping.chainReaderTesters[binding.Address] = chainReaderTester } else { - chainReaderTester.ChainWriter = b.bindingsMapping.chainWriterProxy.ChainWriter + chainReaderTester.ChainWriter = b.bindingsMapping.chainWriterProxy.ContractWriter } } } -func (b bindingClientTester) GetChainWriter(t *testing.T) commontypes.ChainWriter { - chainWriter := b.ChainComponentsInterfaceTester.GetChainWriter(t) - if b.bindingsMapping.chainWriterProxy.ChainWriter == nil { +func (b bindingClientTester) GetChainWriter(t *testing.T) commontypes.ContractWriter { + chainWriter := b.ChainComponentsInterfaceTester.GetContractWriter(t) + if b.bindingsMapping.chainWriterProxy.ContractWriter == nil { b.addDefaultBindings(t) for _, tester := range b.bindingsMapping.chainReaderTesters { tester.ChainWriter = chainWriter } - b.bindingsMapping.chainWriterProxy.ChainWriter = chainWriter + b.bindingsMapping.chainWriterProxy.ContractWriter = chainWriter } return b.bindingsMapping.chainWriterProxy } @@ -182,7 +182,7 @@ type bindingContractReaderProxy struct { } type bindingChainWriterProxy struct { - commontypes.ChainWriter + commontypes.ContractWriter bm *bindingsMapping } @@ -192,7 +192,7 @@ func (b bindingContractReaderProxy) Bind(ctx context.Context, boundContracts []c b.bm.chainReaderTesters[updatedBinding.Address] = &bindings.ChainReaderTester{ BoundContract: updatedBinding, ContractReader: b.ContractReader, - ChainWriter: b.bm.chainWriterProxy.ChainWriter, + ChainWriter: b.bm.chainWriterProxy.ContractWriter, } } return b.ContractReader.Bind(ctx, updatedBindings) @@ -258,7 +258,7 @@ func (b bindingChainWriterProxy) SubmitTransaction(ctx context.Context, contract } func (b *bindingChainWriterProxy) GetTransactionStatus(ctx context.Context, transactionID string) (commontypes.TransactionStatus, error) { - return b.ChainWriter.GetTransactionStatus(ctx, transactionID) + return b.ContractWriter.GetTransactionStatus(ctx, transactionID) } func removeAddressFromReadIdentifier(s string) string { diff --git a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go index 33f2d1ff9dd..71bd94f0e9f 100644 --- a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go +++ b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go @@ -57,7 +57,7 @@ type EVMChainComponentsInterfaceTesterHelper[T TestingT[T]] interface { TXM(T, client.Client) evmtxmgr.TxManager // To enable the historical wrappers required for Simulated Backend tests. ChainReaderEVMClient(ctx context.Context, t T, ht logpoller.HeadTracker, conf types.ChainReaderConfig) client.Client - WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter + WrappedChainWriter(cw clcommontypes.ContractWriter, client client.Client) clcommontypes.ContractWriter } type EVMChainComponentsInterfaceTester[T TestingT[T]] struct { @@ -395,7 +395,7 @@ func (it *EVMChainComponentsInterfaceTester[T]) GetContractReader(t T) clcommont func (it *EVMChainComponentsInterfaceTester[T]) GenerateBlocksTillConfidenceLevel(t T, contractName, readName string, confidenceLevel primitives.ConfidenceLevel) { } -func (it *EVMChainComponentsInterfaceTester[T]) GetChainWriter(t T) clcommontypes.ChainWriter { +func (it *EVMChainComponentsInterfaceTester[T]) GetContractWriter(t T) clcommontypes.ContractWriter { ctx := it.Helper.Context(t) if it.cw != nil { return it.cw diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index cd30e8ab3c3..994dbbb77ce 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -68,7 +68,7 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain return nil, fmt.Errorf("failed to marshal chainwriter config: %w", err) } - cw, err := relayer.NewChainWriter(ctx, encodedWriterConfig) + cw, err := relayer.NewContractWriter(ctx, encodedWriterConfig) if err != nil { return nil, err } diff --git a/core/web/testutils/mock_relayer.go b/core/web/testutils/mock_relayer.go index 4666f9da6a4..c96bf5ee494 100644 --- a/core/web/testutils/mock_relayer.go +++ b/core/web/testutils/mock_relayer.go @@ -33,7 +33,7 @@ func (m MockRelayer) HealthReport() map[string]error { panic("not implemented") } -func (m MockRelayer) NewChainWriter(_ context.Context, _ []byte) (commontypes.ChainWriter, error) { +func (m MockRelayer) NewContractWriter(_ context.Context, _ []byte) (commontypes.ContractWriter, error) { panic("not implemented") } diff --git a/deployment/go.mod b/deployment/go.mod index f1584f39072..e1d51c46433 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/deployment -go 1.23 +go 1.23.3 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ @@ -22,8 +22,8 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.31 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 @@ -108,7 +108,7 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect @@ -401,12 +401,12 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 // indirect github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 // indirect diff --git a/deployment/go.sum b/deployment/go.sum index f40e5b5f21f..a2dc68f9dc6 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -276,10 +276,10 @@ github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1l github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -1409,12 +1409,12 @@ github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 h1:A/qi1YCY/9V9i/sthhizZCA0EECAcBfDKeA2w27H5fo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= @@ -1423,10 +1423,10 @@ github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 h1:gkrjGJAtbKMOliJPaZ73EyJmO8AyDVi80+PEJocRMn4= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749/go.mod h1:nkIegLHodyrrZguxkYEHcNw2vAXv8H8xlCoLzwylcL0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= diff --git a/go.mod b/go.mod index 8e27aab784e..75557e56d2b 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/smartcontractkit/chainlink/v2 -go 1.23 +go 1.23.3 require ( github.com/Depado/ginprom v1.8.0 - github.com/Masterminds/semver/v3 v3.2.1 + github.com/Masterminds/semver/v3 v3.3.0 github.com/Masterminds/sprig/v3 v3.2.3 github.com/NethermindEth/juno v0.3.1 github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb @@ -31,7 +31,7 @@ require ( github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-viper/mapstructure/v2 v2.1.0 github.com/go-webauthn/webauthn v0.9.4 - github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da + github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 github.com/google/uuid v1.6.0 github.com/gorilla/securecookie v1.1.2 github.com/gorilla/sessions v1.2.2 @@ -58,15 +58,15 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/onsi/gomega v1.33.1 + github.com/onsi/gomega v1.34.2 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pelletier/go-toml v1.9.5 - github.com/pelletier/go-toml/v2 v2.2.2 + github.com/pelletier/go-toml/v2 v2.2.3 github.com/pkg/errors v0.9.1 github.com/pressly/goose/v3 v3.21.1 - github.com/prometheus/client_golang v1.20.0 + github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.59.1 + github.com/prometheus/common v0.60.0 github.com/prometheus/prometheus v0.54.1 github.com/robfig/cron/v3 v3.0.1 github.com/rogpeppe/go-internal v1.13.1 @@ -76,14 +76,14 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db github.com/smartcontractkit/chainlink-feeds v0.1.1 github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de @@ -295,6 +295,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.1.10 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect @@ -363,10 +364,9 @@ require ( go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/ratelimit v0.3.0 // indirect + go.uber.org/ratelimit v0.3.1 // indirect golang.org/x/arch v0.11.0 // indirect golang.org/x/net v0.30.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/api v0.202.0 // indirect diff --git a/go.sum b/go.sum index 71832f08801..fb8eab948e4 100644 --- a/go.sum +++ b/go.sum @@ -112,8 +112,8 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -186,10 +186,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -589,8 +589,8 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da h1:xRmpO92tb8y+Z85iUOMOicpCfaYcv7o3Cg3wKrIpg8g= -github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= @@ -968,14 +968,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= +github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -997,8 +997,8 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko 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.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= 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= @@ -1025,8 +1025,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= -github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1037,8 +1037,8 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1123,22 +1123,22 @@ github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 h1:A/qi1YCY/9V9i/sthhizZCA0EECAcBfDKeA2w27H5fo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 h1:gkrjGJAtbKMOliJPaZ73EyJmO8AyDVi80+PEJocRMn4= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749/go.mod h1:nkIegLHodyrrZguxkYEHcNw2vAXv8H8xlCoLzwylcL0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= @@ -1388,8 +1388,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= -go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw= -go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI= +go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= +go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go index 5f17bb61d85..cec9564a30d 100644 --- a/integration-tests/contracts/ccipreader_test.go +++ b/integration-tests/contracts/ccipreader_test.go @@ -925,7 +925,7 @@ func testSetupRealContracts( for chain, cr := range crs { contractReaders[chain] = cr } - contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) + contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, cciptypes.ChainSelector(destChain), nil) return reader @@ -1034,7 +1034,7 @@ func testSetup( for chain, cr := range otherCrs { contractReaders[chain] = cr } - contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) + contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, params.DestChain, nil) t.Cleanup(func() { diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 63a298a243f..8d7bcec57b2 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/integration-tests -go 1.23 +go 1.23.3 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ @@ -37,8 +37,8 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 @@ -417,12 +417,12 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 9e3bf3c0e90..125e890aa25 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -268,10 +268,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -1430,12 +1430,12 @@ github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 h1:A/qi1YCY/9V9i/sthhizZCA0EECAcBfDKeA2w27H5fo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= @@ -1444,10 +1444,10 @@ github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 h1:gkrjGJAtbKMOliJPaZ73EyJmO8AyDVi80+PEJocRMn4= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749/go.mod h1:nkIegLHodyrrZguxkYEHcNw2vAXv8H8xlCoLzwylcL0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 79b5f8b2ae3..b75a854daac 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink/load-tests -go 1.23 +go 1.23.3 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -17,7 +17,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 @@ -399,13 +399,13 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.31 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 2b1abf1a0d3..84833e7e665 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -272,10 +272,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -1421,12 +1421,12 @@ github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6 h1:A/qi1YCY/9V9i/sthhizZCA0EECAcBfDKeA2w27H5fo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241128080738-06bef8620ac6/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d h1:0tnjo1gpG16PHAouXamgDAAu6e7PWaM0Ppq6dMWnjx0= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241125150608-97ceadb2072d/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= @@ -1435,10 +1435,10 @@ github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749 h1:gkrjGJAtbKMOliJPaZ73EyJmO8AyDVi80+PEJocRMn4= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127201057-3c9282e39749/go.mod h1:nkIegLHodyrrZguxkYEHcNw2vAXv8H8xlCoLzwylcL0= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 h1:lvn9Yxah+QD1/PcgijLO0dNRa28HuQWZl8Kkxh46KJc= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= diff --git a/integration-tests/smoke/ccip/ccip_rmn_test.go b/integration-tests/smoke/ccip/ccip_rmn_test.go index 201982e19d1..6cd6bd9d63f 100644 --- a/integration-tests/smoke/ccip/ccip_rmn_test.go +++ b/integration-tests/smoke/ccip/ccip_rmn_test.go @@ -18,7 +18,7 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn/types" + "github.com/smartcontractkit/chainlink-ccip/pkg/reader" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" @@ -620,7 +620,7 @@ func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing } for _, subjectDescription := range cursedSubjects { - subj := types.GlobalCurseSubject + subj := reader.GlobalCurseSubject if subjectDescription != globalCurse { subj = chainSelectorToBytes16(tc.pf.chainSelectors[subjectDescription]) } From e0de391d3bc58b8c6adf422c68e64583b47dbb96 Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Wed, 4 Dec 2024 11:04:25 -0800 Subject: [PATCH 06/55] feat: validate contracts changeset files (#15468) * feat: validate contracts changeset files * fix: remove explicit passing of github token --- .github/workflows/changeset.yml | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index 19d17ddb588..5d6b2deafe2 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -162,3 +162,42 @@ jobs: run: | echo "Please include at least one tag in the core changeset file" exit 1 + + contracts-changeset: + name: Contracts Changeset Checker + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.1 + with: + fetch-depth: 0 + + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: files-changed + with: + predicate-quantifier: every + list-files: shell + filters: | + contracts-changeset: + - added|modified: 'contracts/.changeset/*.md' + + - name: Setup node + uses: ./.github/actions/setup-node + if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} + + - name: Validate changeset files + if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} + working-directory: contracts + run: | + pnpm changeset version + + - name: Comment Failure + if: ${{ failure() && steps.files-changed.outputs.contracts-changeset == 'true' }} + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + message: | + It appears that the changeset file you've added or modified in `contracts/.changeset` is not valid. + Please delete the file and run `pnpm changeset` in the contracts directory. + From 03207929cc9f7ebbe0cba0b2454df250bf4e8bc9 Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:57:25 -0800 Subject: [PATCH 07/55] fix set users (#15506) --- deployment/environment/devenv/chain.go | 1 - 1 file changed, 1 deletion(-) diff --git a/deployment/environment/devenv/chain.go b/deployment/environment/devenv/chain.go index ae381e448da..407b898cb04 100644 --- a/deployment/environment/devenv/chain.go +++ b/deployment/environment/devenv/chain.go @@ -42,7 +42,6 @@ func (c *ChainConfig) SetUsers(pvtkeys []string) error { return fmt.Errorf("no private keys provided for users, deployer key is also not set") } } - c.Users = make([]*bind.TransactOpts, len(pvtkeys)) for _, pvtKeyStr := range pvtkeys { pvtKey, err := crypto.HexToECDSA(pvtKeyStr) if err != nil { From 103dba23e8aa8b7679f14b8d5da0d995335667e7 Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:13:19 -0800 Subject: [PATCH 08/55] [KS-603][Deployments][Keystone] Minor refactor to expose registry methods publicly (#15511) --- .../keystone/changeset/internal/test/utils.go | 20 ++- deployment/keystone/deploy.go | 118 ++++++++++-------- 2 files changed, 84 insertions(+), 54 deletions(-) diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/internal/test/utils.go index 268ad169ca7..df01266043a 100644 --- a/deployment/keystone/changeset/internal/test/utils.go +++ b/deployment/keystone/changeset/internal/test/utils.go @@ -111,10 +111,24 @@ func deployCapReg(t *testing.T, chain deployment.Chain) *kcr.CapabilitiesRegistr } func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, nops []kcr.CapabilitiesRegistryNodeOperator) *kslib.RegisterNOPSResponse { + env := &deployment.Environment{ + Logger: lggr, + Chains: map[uint64]deployment.Chain{ + chain.Selector: chain, + }, + ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ + chain.Selector: { + registry.Address().String(): deployment.TypeAndVersion{ + Type: kslib.CapabilitiesRegistry, + Version: deployment.Version1_0_0, + }, + }, + }), + } resp, err := kslib.RegisterNOPS(context.TODO(), lggr, kslib.RegisterNOPSRequest{ - Chain: chain, - Registry: registry, - Nops: nops, + Env: env, + RegistryChainSelector: chain.Selector, + Nops: nops, }) require.NoError(t, err) return resp diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index 7b304c1ba0c..374f7f06460 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -173,38 +173,46 @@ func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, return donInfos, nil } -// ConfigureRegistry configures the registry contract with the given DONS and their capabilities -// the address book is required to contain the addresses of the deployed registry contract -func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { - registryChain, ok := req.Env.Chains[req.RegistryChainSel] +func GetRegistryContract(e *deployment.Environment, registryChainSel uint64, addrBook deployment.AddressBook) (*kcr.CapabilitiesRegistry, deployment.Chain, error) { + registryChain, ok := e.Chains[registryChainSel] if !ok { - return nil, fmt.Errorf("chain %d not found in environment", req.RegistryChainSel) + return nil, deployment.Chain{}, fmt.Errorf("chain %d not found in environment", registryChainSel) } - contractSetsResp, err := GetContractSets(req.Env.Logger, &GetContractSetsRequest{ - Chains: req.Env.Chains, + contractSetsResp, err := GetContractSets(e.Logger, &GetContractSetsRequest{ + Chains: e.Chains, AddressBook: addrBook, }) if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) - } - - donInfos, err := DonInfos(req.Dons, req.Env.Offchain) - if err != nil { - return nil, fmt.Errorf("failed to get don infos: %w", err) + return nil, deployment.Chain{}, fmt.Errorf("failed to get contract sets: %w", err) } // ensure registry is deployed and get the registry contract and chain var registry *kcr.CapabilitiesRegistry - registryChainContracts, ok := contractSetsResp.ContractSets[req.RegistryChainSel] + registryChainContracts, ok := contractSetsResp.ContractSets[registryChainSel] if !ok { - return nil, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", req.RegistryChainSel) + return nil, deployment.Chain{}, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", registryChainSel) } registry = registryChainContracts.CapabilitiesRegistry if registry == nil { - return nil, fmt.Errorf("no registry contract found") + return nil, deployment.Chain{}, fmt.Errorf("no registry contract found") + } + e.Logger.Debugf("registry contract address: %s, chain %d", registry.Address().String(), registryChainSel) + return registry, registryChain, nil +} + +// ConfigureRegistry configures the registry contract with the given DONS and their capabilities +// the address book is required to contain the addresses of the deployed registry contract +func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSel, addrBook) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + + donInfos, err := DonInfos(req.Dons, req.Env.Offchain) + if err != nil { + return nil, fmt.Errorf("failed to get don infos: %w", err) } - lggr.Debugf("registry contract address: %s, chain %d", registry.Address().String(), req.RegistryChainSel) // all the subsequent calls to the registry are in terms of nodes // compute the mapping of dons to their nodes for reuse in various registry calls @@ -222,22 +230,22 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon } // register capabilities - capabilitiesResp, err := registerCapabilities(lggr, registerCapabilitiesRequest{ - chain: registryChain, - registry: registry, - donToCapabilities: donToCapabilities, + capabilitiesResp, err := RegisterCapabilities(lggr, RegisterCapabilitiesRequest{ + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + DonToCapabilities: donToCapabilities, }) if err != nil { return nil, fmt.Errorf("failed to register capabilities: %w", err) } - lggr.Infow("registered capabilities", "capabilities", capabilitiesResp.donToCapabilities) + lggr.Infow("registered capabilities", "capabilities", capabilitiesResp.DonToCapabilities) // register node operators nopsList := maps.Keys(nopsToNodeIDs) nopsResp, err := RegisterNOPS(ctx, lggr, RegisterNOPSRequest{ - Chain: registryChain, - Registry: registry, - Nops: nopsList, + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + Nops: nopsList, }) if err != nil { return nil, fmt.Errorf("failed to register node operators: %w", err) @@ -250,7 +258,7 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon chain: registryChain, nopToNodeIDs: nopsToNodeIDs, donToNodes: donToNodes, - donToCapabilities: capabilitiesResp.donToCapabilities, + donToCapabilities: capabilitiesResp.DonToCapabilities, nops: nopsResp.Nops, }) if err != nil { @@ -265,7 +273,7 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon registry: registry, chain: registryChain, nodeIDToParams: nodesResp.nodeIDToParams, - donToCapabilities: capabilitiesResp.donToCapabilities, + donToCapabilities: capabilitiesResp.DonToCapabilities, donToNodes: donToNodes, }) if err != nil { @@ -410,14 +418,14 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C } -type registerCapabilitiesRequest struct { - chain deployment.Chain - registry *kcr.CapabilitiesRegistry - donToCapabilities map[string][]kcr.CapabilitiesRegistryCapability +type RegisterCapabilitiesRequest struct { + Env *deployment.Environment + RegistryChainSelector uint64 + DonToCapabilities map[string][]kcr.CapabilitiesRegistryCapability } -type registerCapabilitiesResponse struct { - donToCapabilities map[string][]RegisteredCapability +type RegisterCapabilitiesResponse struct { + DonToCapabilities map[string][]RegisteredCapability } type RegisteredCapability struct { @@ -425,25 +433,29 @@ type RegisteredCapability struct { ID [32]byte } -// registerCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) -func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) (*registerCapabilitiesResponse, error) { - if len(req.donToCapabilities) == 0 { +// RegisterCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) +func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) (*RegisterCapabilitiesResponse, error) { + if len(req.DonToCapabilities) == 0 { return nil, fmt.Errorf("no capabilities to register") } - lggr.Infow("registering capabilities...", "len", len(req.donToCapabilities)) - resp := ®isterCapabilitiesResponse{ - donToCapabilities: make(map[string][]RegisteredCapability), + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + lggr.Infow("registering capabilities...", "len", len(req.DonToCapabilities)) + resp := &RegisterCapabilitiesResponse{ + DonToCapabilities: make(map[string][]RegisteredCapability), } // capability could be hosted on multiple dons. need to deduplicate uniqueCaps := make(map[kcr.CapabilitiesRegistryCapability][32]byte) - for don, caps := range req.donToCapabilities { + for don, caps := range req.DonToCapabilities { var registerCaps []RegisteredCapability for _, cap := range caps { id, ok := uniqueCaps[cap] if !ok { var err error - id, err = req.registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + id, err = registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) if err != nil { return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) } @@ -456,7 +468,7 @@ func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) ( lggr.Debugw("hashed capability id", "capability", cap, "id", id) registerCaps = append(registerCaps, registerCap) } - resp.donToCapabilities[don] = registerCaps + resp.DonToCapabilities[don] = registerCaps } var capabilities []kcr.CapabilitiesRegistryCapability @@ -464,7 +476,7 @@ func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) ( capabilities = append(capabilities, cap) } - err := AddCapabilities(lggr, req.registry, req.chain, capabilities) + err = AddCapabilities(lggr, registry, registryChain, capabilities) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -472,9 +484,9 @@ func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) ( } type RegisterNOPSRequest struct { - Chain deployment.Chain - Registry *kcr.CapabilitiesRegistry - Nops []kcr.CapabilitiesRegistryNodeOperator + Env *deployment.Environment + RegistryChainSelector uint64 + Nops []kcr.CapabilitiesRegistryNodeOperator } type RegisterNOPSResponse struct { @@ -482,8 +494,12 @@ type RegisterNOPSResponse struct { } func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSRequest) (*RegisterNOPSResponse, error) { + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } lggr.Infow("registering node operators...", "len", len(req.Nops)) - existingNops, err := req.Registry.GetNodeOperators(&bind.CallOpts{}) + existingNops, err := registry.GetNodeOperators(&bind.CallOpts{}) if err != nil { return nil, err } @@ -512,19 +528,19 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque lggr.Debug("no new node operators to register") return resp, nil } - tx, err := req.Registry.AddNodeOperators(req.Chain.DeployerKey, nops) + tx, err := registry.AddNodeOperators(registryChain.DeployerKey, nops) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } // for some reason that i don't understand, the confirm must be called before the WaitMined or the latter will hang // (at least for a simulated backend chain) - _, err = req.Chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) } - receipt, err := bind.WaitMined(ctx, req.Chain.Client, tx) + receipt, err := bind.WaitMined(ctx, registryChain.Client, tx) if err != nil { return nil, fmt.Errorf("failed to mine AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) } @@ -532,7 +548,7 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque return nil, fmt.Errorf("expected %d log entries for AddNodeOperators, got %d", len(nops), len(receipt.Logs)) } for i, log := range receipt.Logs { - o, err := req.Registry.ParseNodeOperatorAdded(*log) + o, err := registry.ParseNodeOperatorAdded(*log) if err != nil { return nil, fmt.Errorf("failed to parse log %d for operator added: %w", i, err) } From 1bfd6e4903fae2bc0ab6a5e9cbab692abaecef8b Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Wed, 4 Dec 2024 18:28:00 -0500 Subject: [PATCH 09/55] Transfer to timelock (#15507) * Transfer to timelock * Side quest support link view * Adjust keystone * KS test working * Comments and fix test * Comments and fix another test --- deployment/address_book.go | 15 ++ .../ccip/changeset/accept_ownership_test.go | 108 ++++--------- .../changeset/cs_active_candidate_test.go | 8 +- .../ccip/changeset/cs_add_chain_test.go | 41 +++-- .../ccip/changeset/cs_deploy_chain_test.go | 64 ++++---- deployment/ccip/changeset/cs_prerequisites.go | 27 ---- .../ccip/changeset/cs_prerequisites_test.go | 1 - .../ccip/changeset/save_existing_test.go | 3 +- deployment/ccip/changeset/state.go | 26 ++-- deployment/ccip/changeset/test_helpers.go | 4 + deployment/ccip/changeset/token_info.go | 7 +- deployment/ccip/view/view.go | 1 + .../common/changeset/accept_ownership.go | 105 ------------- .../common/changeset/accept_ownership_test.go | 76 --------- .../common/changeset/deploy_link_token.go | 24 +-- .../changeset/deploy_link_token_test.go | 42 ++--- deployment/common/changeset/state.go | 26 ++++ .../common/changeset/transfer_ownership.go | 71 --------- .../transfer_to_mcms_with_timelock.go | 144 ++++++++++++++++++ .../transfer_to_mcms_with_timelock_test.go | 69 +++++++++ deployment/common/proposalutils/propose.go | 2 +- deployment/common/view/v1_0/link_token.go | 43 ++++++ deployment/environment/memory/environment.go | 3 + .../keystone/changeset/accept_ownership.go | 56 ++----- .../changeset/accept_ownership_test.go | 96 ++++++------ deployment/keystone/changeset/deploy_ocr3.go | 8 +- .../keystone/changeset/transfer_ownership.go | 84 ---------- .../changeset/transfer_ownership_test.go | 72 --------- .../testsetups/ccip/test_helpers.go | 4 + 29 files changed, 514 insertions(+), 716 deletions(-) delete mode 100644 deployment/common/changeset/accept_ownership.go delete mode 100644 deployment/common/changeset/accept_ownership_test.go delete mode 100644 deployment/common/changeset/transfer_ownership.go create mode 100644 deployment/common/changeset/transfer_to_mcms_with_timelock.go create mode 100644 deployment/common/changeset/transfer_to_mcms_with_timelock_test.go create mode 100644 deployment/common/view/v1_0/link_token.go delete mode 100644 deployment/keystone/changeset/transfer_ownership.go delete mode 100644 deployment/keystone/changeset/transfer_ownership_test.go diff --git a/deployment/address_book.go b/deployment/address_book.go index 7997507554f..28d728bf6c7 100644 --- a/deployment/address_book.go +++ b/deployment/address_book.go @@ -256,3 +256,18 @@ func SearchAddressBook(ab AddressBook, chain uint64, typ ContractType) (string, return "", fmt.Errorf("not found") } + +func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool, error) { + addrs, err := ab.AddressesForChain(chain) + if err != nil { + return false, err + } + + for addr := range addrs { + if addr == addrToFind { + return true, nil + } + } + + return false, nil +} diff --git a/deployment/ccip/changeset/accept_ownership_test.go b/deployment/ccip/changeset/accept_ownership_test.go index 7164fe1786a..796db6aed09 100644 --- a/deployment/ccip/changeset/accept_ownership_test.go +++ b/deployment/ccip/changeset/accept_ownership_test.go @@ -2,14 +2,10 @@ package changeset import ( "testing" - "time" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -47,15 +43,9 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) { _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocks, []commonchangeset.ChangesetApplication{ // note this doesn't have proposals. { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewTransferOwnershipChangeset), + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), Config: genTestTransferOwnershipConfig(e, allChains, state), }, - // this has proposals, ApplyChangesets will sign & execute them. - // in practice, signing and executing are separated processes. - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewAcceptOwnershipChangeset), - Config: genTestAcceptOwnershipConfig(e, allChains, state), - }, }) require.NoError(t, err) @@ -66,21 +56,21 @@ func genTestTransferOwnershipConfig( e DeployedEnv, chains []uint64, state CCIPOnChainState, -) commonchangeset.TransferOwnershipConfig { +) commonchangeset.TransferToMCMSWithTimelockConfig { var ( timelocksPerChain = make(map[uint64]common.Address) - contracts = make(map[uint64][]commonchangeset.OwnershipTransferrer) + contracts = make(map[uint64][]common.Address) ) // chain contracts for _, chain := range chains { timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() - contracts[chain] = []commonchangeset.OwnershipTransferrer{ - state.Chains[chain].OnRamp, - state.Chains[chain].OffRamp, - state.Chains[chain].FeeQuoter, - state.Chains[chain].NonceManager, - state.Chains[chain].RMNRemote, + contracts[chain] = []common.Address{ + state.Chains[chain].OnRamp.Address(), + state.Chains[chain].OffRamp.Address(), + state.Chains[chain].FeeQuoter.Address(), + state.Chains[chain].NonceManager.Address(), + state.Chains[chain].RMNRemote.Address(), } } @@ -88,54 +78,13 @@ func genTestTransferOwnershipConfig( homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() timelocksPerChain[e.HomeChainSel] = homeChainTimelockAddress contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel], - state.Chains[e.HomeChainSel].CapabilityRegistry, - state.Chains[e.HomeChainSel].CCIPHome, - state.Chains[e.HomeChainSel].RMNHome, - ) - - return commonchangeset.TransferOwnershipConfig{ - OwnersPerChain: timelocksPerChain, - Contracts: contracts, - } -} - -func genTestAcceptOwnershipConfig( - e DeployedEnv, - chains []uint64, - state CCIPOnChainState, -) commonchangeset.AcceptOwnershipConfig { - var ( - timelocksPerChain = make(map[uint64]common.Address) - proposerMCMses = make(map[uint64]*gethwrappers.ManyChainMultiSig) - contracts = make(map[uint64][]commonchangeset.OwnershipAcceptor) - ) - for _, chain := range chains { - timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() - proposerMCMses[chain] = state.Chains[chain].ProposerMcm - contracts[chain] = []commonchangeset.OwnershipAcceptor{ - state.Chains[chain].OnRamp, - state.Chains[chain].OffRamp, - state.Chains[chain].FeeQuoter, - state.Chains[chain].NonceManager, - state.Chains[chain].RMNRemote, - } - } - - // add home chain contracts. - // this overwrite should be fine. - timelocksPerChain[e.HomeChainSel] = state.Chains[e.HomeChainSel].Timelock.Address() - proposerMCMses[e.HomeChainSel] = state.Chains[e.HomeChainSel].ProposerMcm - contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel], - state.Chains[e.HomeChainSel].CapabilityRegistry, - state.Chains[e.HomeChainSel].CCIPHome, - state.Chains[e.HomeChainSel].RMNHome, + state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + state.Chains[e.HomeChainSel].CCIPHome.Address(), + state.Chains[e.HomeChainSel].RMNHome.Address(), ) - return commonchangeset.AcceptOwnershipConfig{ - OwnersPerChain: timelocksPerChain, - ProposerMCMSes: proposerMCMses, - Contracts: contracts, - MinDelay: time.Duration(0), + return commonchangeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contracts, } } @@ -147,19 +96,16 @@ func assertTimelockOwnership( chains []uint64, state CCIPOnChainState, ) { - ctx := tests.Context(t) // check that the ownership has been transferred correctly for _, chain := range chains { - for _, contract := range []commonchangeset.OwnershipTransferrer{ - state.Chains[chain].OnRamp, - state.Chains[chain].OffRamp, - state.Chains[chain].FeeQuoter, - state.Chains[chain].NonceManager, - state.Chains[chain].RMNRemote, + for _, contract := range []common.Address{ + state.Chains[chain].OnRamp.Address(), + state.Chains[chain].OffRamp.Address(), + state.Chains[chain].FeeQuoter.Address(), + state.Chains[chain].NonceManager.Address(), + state.Chains[chain].RMNRemote.Address(), } { - owner, err := contract.Owner(&bind.CallOpts{ - Context: ctx, - }) + owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[chain].Client) require.NoError(t, err) require.Equal(t, state.Chains[chain].Timelock.Address(), owner) } @@ -167,14 +113,12 @@ func assertTimelockOwnership( // check home chain contracts ownership homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() - for _, contract := range []commonchangeset.OwnershipTransferrer{ - state.Chains[e.HomeChainSel].CapabilityRegistry, - state.Chains[e.HomeChainSel].CCIPHome, - state.Chains[e.HomeChainSel].RMNHome, + for _, contract := range []common.Address{ + state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), + state.Chains[e.HomeChainSel].CCIPHome.Address(), + state.Chains[e.HomeChainSel].RMNHome.Address(), } { - owner, err := contract.Owner(&bind.CallOpts{ - Context: ctx, - }) + owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[e.HomeChainSel].Client) require.NoError(t, err) require.Equal(t, homeChainTimelockAddress, owner) } diff --git a/deployment/ccip/changeset/cs_active_candidate_test.go b/deployment/ccip/changeset/cs_active_candidate_test.go index 6efdacc3b7c..4bd0c9fd7a4 100644 --- a/deployment/ccip/changeset/cs_active_candidate_test.go +++ b/deployment/ccip/changeset/cs_active_candidate_test.go @@ -98,15 +98,9 @@ func TestActiveCandidate(t *testing.T) { _, err = commonchangeset.ApplyChangesets(t, e, timelocks, []commonchangeset.ChangesetApplication{ // note this doesn't have proposals. { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewTransferOwnershipChangeset), + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), Config: genTestTransferOwnershipConfig(tenv, allChains, state), }, - // this has proposals, ApplyChangesets will sign & execute them. - // in practice, signing and executing are separated processes. - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewAcceptOwnershipChangeset), - Config: genTestAcceptOwnershipConfig(tenv, allChains, state), - }, }) require.NoError(t, err) // Apply the accept ownership proposal to all the chains. diff --git a/deployment/ccip/changeset/cs_add_chain_test.go b/deployment/ccip/changeset/cs_add_chain_test.go index e53a147edea..b8a845ac27c 100644 --- a/deployment/ccip/changeset/cs_add_chain_test.go +++ b/deployment/ccip/changeset/cs_add_chain_test.go @@ -58,13 +58,21 @@ func TestAddChainInbound(t *testing.T) { TimelockExecutors: e.Env.AllDeployerKeys(), TimelockMinDelay: big.NewInt(0), } - out, err := commonchangeset.DeployMCMSWithTimelock(e.Env, map[uint64]commontypes.MCMSWithTimelockConfig{ - initialDeploy[0]: cfg, - initialDeploy[1]: cfg, - initialDeploy[2]: cfg, + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: initialDeploy, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]commontypes.MCMSWithTimelockConfig{ + initialDeploy[0]: cfg, + initialDeploy[1]: cfg, + initialDeploy[2]: cfg, + }, + }, }) require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(out.AddressBook)) newAddresses = deployment.NewMemoryAddressBook() tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) @@ -99,12 +107,19 @@ func TestAddChainInbound(t *testing.T) { require.NoError(t, err) // Deploy contracts to new chain - out, err = commonchangeset.DeployMCMSWithTimelock(e.Env, map[uint64]commontypes.MCMSWithTimelockConfig{ - newChain: cfg, + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: []uint64{newChain}, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]commontypes.MCMSWithTimelockConfig{ + newChain: cfg, + }, + }, }) require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(out.AddressBook)) - newAddresses = deployment.NewMemoryAddressBook() err = deployPrerequisiteChainContracts(e.Env, newAddresses, []uint64{newChain}, nil) @@ -138,15 +153,9 @@ func TestAddChainInbound(t *testing.T) { }, []commonchangeset.ChangesetApplication{ // note this doesn't have proposals. { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewTransferOwnershipChangeset), + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), Config: genTestTransferOwnershipConfig(e, initialDeploy, state), }, - // this has proposals, ApplyChangesets will sign & execute them. - // in practice, signing and executing are separated processes. - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.NewAcceptOwnershipChangeset), - Config: genTestAcceptOwnershipConfig(e, initialDeploy, state), - }, }) require.NoError(t, err) diff --git a/deployment/ccip/changeset/cs_deploy_chain_test.go b/deployment/ccip/changeset/cs_deploy_chain_test.go index 7965fe8e725..234d73cc4b5 100644 --- a/deployment/ccip/changeset/cs_deploy_chain_test.go +++ b/deployment/ccip/changeset/cs_deploy_chain_test.go @@ -28,27 +28,6 @@ func TestDeployChainContractsChangeset(t *testing.T) { nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) require.NoError(t, err) p2pIds := nodes.NonBootstraps().PeerIDs() - // deploy home chain - homeChainCfg := DeployHomeChainConfig{ - HomeChainSel: homeChainSel, - RMNStaticConfig: NewTestRMNStaticConfig(), - RMNDynamicConfig: NewTestRMNDynamicConfig(), - NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), - NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ - "NodeOperator": p2pIds, - }, - } - output, err := DeployHomeChain(e, homeChainCfg) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - - // deploy pre-requisites - prerequisites, err := DeployPrerequisites(e, DeployPrerequisiteConfig{ - ChainSelectors: selectors, - }) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(prerequisites.AddressBook)) - cfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) for _, chain := range e.AllChainSelectors() { cfg[chain] = commontypes.MCMSWithTimelockConfig{ @@ -59,17 +38,42 @@ func TestDeployChainContractsChangeset(t *testing.T) { TimelockMinDelay: big.NewInt(0), } } - output, err = commonchangeset.DeployMCMSWithTimelock(e, cfg) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - - // deploy ccip chain contracts - output, err = DeployChainContracts(e, DeployChainContractsConfig{ - ChainSelectors: selectors, - HomeChainSelector: homeChainSel, + e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(DeployHomeChain), + Config: DeployHomeChainConfig{ + HomeChainSel: homeChainSel, + RMNStaticConfig: NewTestRMNStaticConfig(), + RMNDynamicConfig: NewTestRMNDynamicConfig(), + NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ + "NodeOperator": p2pIds, + }, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: selectors, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: cfg, + }, + { + Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), + Config: DeployPrerequisiteConfig{ + ChainSelectors: selectors, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), + Config: DeployChainContractsConfig{ + ChainSelectors: selectors, + HomeChainSelector: homeChainSel, + }, + }, }) require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) // load onchain state state, err := LoadOnchainState(e) diff --git a/deployment/ccip/changeset/cs_prerequisites.go b/deployment/ccip/changeset/cs_prerequisites.go index f6c502d9ad5..e610dfaaeeb 100644 --- a/deployment/ccip/changeset/cs_prerequisites.go +++ b/deployment/ccip/changeset/cs_prerequisites.go @@ -2,7 +2,6 @@ package changeset import ( "fmt" - "math/big" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" @@ -16,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3" ) @@ -126,7 +124,6 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address lggr := e.Logger chainState, chainExists := state.Chains[chain.Selector] var weth9Contract *weth9.WETH9 - var linkTokenContract *burn_mint_erc677.BurnMintERC677 var tokenAdminReg *token_admin_registry.TokenAdminRegistry var registryModule *registry_module_owner_custom.RegistryModuleOwnerCustom var rmnProxy *rmn_proxy_contract.RMNProxyContract @@ -134,7 +131,6 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address var mc3 *multicall3.Multicall3 if chainExists { weth9Contract = chainState.Weth9 - linkTokenContract = chainState.LinkToken tokenAdminReg = chainState.TokenAdminRegistry registryModule = chainState.RegistryModule rmnProxy = chainState.RMNProxyExisting @@ -257,29 +253,6 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } else { lggr.Infow("weth9 already deployed", "addr", weth9Contract.Address) } - if linkTokenContract == nil { - linkToken, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { - linkTokenAddr, tx2, linkToken, err2 := burn_mint_erc677.DeployBurnMintERC677( - chain.DeployerKey, - chain.Client, - "Link Token", - "LINK", - uint8(18), - big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), - ) - return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - linkTokenAddr, linkToken, tx2, deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy linkToken", "err", err) - return err - } - lggr.Infow("deployed linkToken", "addr", linkToken.Address) - } else { - lggr.Infow("linkToken already deployed", "addr", linkTokenContract.Address) - } // if router is not already deployed, we deploy it if r == nil { routerContract, err := deployment.DeployContract(e.Logger, chain, ab, diff --git a/deployment/ccip/changeset/cs_prerequisites_test.go b/deployment/ccip/changeset/cs_prerequisites_test.go index 1a167b2816c..da1ff9c83a9 100644 --- a/deployment/ccip/changeset/cs_prerequisites_test.go +++ b/deployment/ccip/changeset/cs_prerequisites_test.go @@ -28,7 +28,6 @@ func TestDeployPrerequisites(t *testing.T) { require.NoError(t, err) state, err := LoadOnchainState(e) require.NoError(t, err) - require.NotNil(t, state.Chains[newChain].LinkToken) require.NotNil(t, state.Chains[newChain].Weth9) require.NotNil(t, state.Chains[newChain].TokenAdminRegistry) require.NotNil(t, state.Chains[newChain].RegistryModule) diff --git a/deployment/ccip/changeset/save_existing_test.go b/deployment/ccip/changeset/save_existing_test.go index 93f3d7e067d..080ed80481a 100644 --- a/deployment/ccip/changeset/save_existing_test.go +++ b/deployment/ccip/changeset/save_existing_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -29,7 +30,7 @@ func TestSaveExistingCCIP(t *testing.T) { ExistingContracts: []commonchangeset.Contract{ { Address: common.BigToAddress(big.NewInt(1)), - TypeAndVersion: deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0), + TypeAndVersion: deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0), ChainSelector: chain1, }, { diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go index fe7b7008982..20763523141 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/changeset/state.go @@ -51,7 +51,6 @@ import ( var ( MockRMN deployment.ContractType = "MockRMN" RMNRemote deployment.ContractType = "RMNRemote" - LinkToken deployment.ContractType = "LinkToken" ARMProxy deployment.ContractType = "ARMProxy" WETH9 deployment.ContractType = "WETH9" Router deployment.ContractType = "Router" @@ -83,6 +82,7 @@ var ( // on a chain. If a binding is nil, it means here is no such contract on the chain. type CCIPChainState struct { commoncs.MCMSWithTimelockState + commoncs.LinkTokenState OnRamp *onramp.OnRamp OffRamp *offramp.OffRamp FeeQuoter *fee_quoter.FeeQuoter @@ -103,8 +103,6 @@ type CCIPChainState struct { Weth9 *weth9.WETH9 RMNRemote *rmn_remote.RMNRemote MockRMN *mock_rmn_contract.MockRMNContract - // TODO: May need to support older link too - LinkToken *burn_mint_erc677.BurnMintERC677 // Map between token Descriptor (e.g. LinkSymbol, WethSymbol) // and the respective token contract // This is more of an illustration of how we'll have tokens, and it might need some work later to work properly. @@ -221,6 +219,13 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { } chainView.MCMSWithTimelock = mcmsView } + if c.LinkToken != nil { + linkTokenView, err := common_v1_0.GenerateLinkTokenView(c.LinkToken) + if err != nil { + return chainView, err + } + chainView.LinkToken = linkTokenView + } return chainView, nil } @@ -290,12 +295,19 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.MCMSWithTimelockState = *mcmsWithTimelock + + linkState, err := commoncs.LoadLinkTokenState(chain, addresses) + if err != nil { + return state, err + } + state.LinkTokenState = *linkState for address, tvStr := range addresses { switch tvStr.String() { case deployment.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0).String(), deployment.NewTypeAndVersion(commontypes.ProposerManyChainMultisig, deployment.Version1_0_0).String(), deployment.NewTypeAndVersion(commontypes.CancellerManyChainMultisig, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(): + deployment.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(), + deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String(): continue case deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0).String(): cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) @@ -399,12 +411,6 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.FeeQuoter = fq - case deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0).String(): - lt, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.LinkToken = lt case deployment.NewTypeAndVersion(USDCToken, deployment.Version1_0_0).String(): ut, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) if err != nil { diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index a5a5881a4e5..742fe39200a 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -293,6 +293,10 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, // Need to deploy prerequisites first so that we can form the USDC config // no proposals to be made, timelock can be passed as nil here e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: allChains, + }, { Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), Config: DeployPrerequisiteConfig{ diff --git a/deployment/ccip/changeset/token_info.go b/deployment/ccip/changeset/token_info.go index 5bd6b2ed66e..7c008a8a884 100644 --- a/deployment/ccip/changeset/token_info.go +++ b/deployment/ccip/changeset/token_info.go @@ -3,12 +3,11 @@ package changeset import ( "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" ) type TokenSymbol string @@ -68,7 +67,7 @@ func (tc *TokenConfig) UpsertTokenInfo( // GetTokenInfo Adds mapping between dest chain tokens and their respective aggregators on feed chain. func (tc *TokenConfig) GetTokenInfo( lggr logger.Logger, - linkToken *burn_mint_erc677.BurnMintERC677, + linkToken *link_token.LinkToken, wethToken *weth9.WETH9, ) map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo { tokenToAggregate := make(map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo) diff --git a/deployment/ccip/view/view.go b/deployment/ccip/view/view.go index 318e09100b9..836dc9c65dd 100644 --- a/deployment/ccip/view/view.go +++ b/deployment/ccip/view/view.go @@ -27,6 +27,7 @@ type ChainView struct { OffRamp map[string]v1_6.OffRampView `json:"offRamp,omitempty"` CapabilityRegistry map[string]common_v1_0.CapabilityRegistryView `json:"capabilityRegistry,omitempty"` MCMSWithTimelock common_v1_0.MCMSWithTimelockView `json:"mcmsWithTimelock,omitempty"` + LinkToken common_v1_0.LinkTokenView `json:"linkToken,omitempty"` } func NewChain() ChainView { diff --git a/deployment/common/changeset/accept_ownership.go b/deployment/common/changeset/accept_ownership.go deleted file mode 100644 index 79aa876eabb..00000000000 --- a/deployment/common/changeset/accept_ownership.go +++ /dev/null @@ -1,105 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" -) - -type OwnershipAcceptor interface { - AcceptOwnership(opts *bind.TransactOpts) (*gethtypes.Transaction, error) - Address() common.Address -} - -type AcceptOwnershipConfig struct { - // OwnersPerChain is a mapping from chain selector to the owner contract address on that chain. - OwnersPerChain map[uint64]common.Address - - // ProposerMCMSes is a mapping from chain selector to the proposer MCMS contract on that chain. - ProposerMCMSes map[uint64]*gethwrappers.ManyChainMultiSig - - // Contracts is a mapping from chain selector to the ownership acceptors on that chain. - // Proposal will be generated for these contracts. - Contracts map[uint64][]OwnershipAcceptor - - // MinDelay is the minimum amount of time that must pass before the proposal - // can be executed onchain. - // This is typically set to 3 hours but can be set to 0 for immediate execution (useful for tests). - MinDelay time.Duration -} - -func (a AcceptOwnershipConfig) Validate() error { - // check that we have owners and proposer mcmses for the chains - // in the Contracts field. - for chainSelector := range a.Contracts { - if _, ok := a.OwnersPerChain[chainSelector]; !ok { - return fmt.Errorf("missing owner for chain %d", chainSelector) - } - if _, ok := a.ProposerMCMSes[chainSelector]; !ok { - return fmt.Errorf("missing proposer MCMS for chain %d", chainSelector) - } - } - - return nil -} - -// type assertion - comply with deployment.ChangeSet interface -var _ deployment.ChangeSet[AcceptOwnershipConfig] = NewAcceptOwnershipChangeset - -// NewAcceptOwnershipChangeset creates a changeset that contains a proposal to accept ownership of the contracts -// provided in the configuration. -func NewAcceptOwnershipChangeset( - e deployment.Environment, - cfg AcceptOwnershipConfig, -) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid accept ownership config: %w", err) - } - - var batches []timelock.BatchChainOperation - for chainSelector, ownershipAcceptors := range cfg.Contracts { - var ops []mcms.Operation - for _, ownershipAcceptor := range ownershipAcceptors { - tx, err := ownershipAcceptor.AcceptOwnership(deployment.SimTransactOpts()) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate accept ownership calldata of %T: %w", ownershipAcceptor, err) - } - - ops = append(ops, mcms.Operation{ - To: ownershipAcceptor.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }) - } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSelector), - Batch: ops, - }) - } - - proposal, err := proposalutils.BuildProposalFromBatches( - cfg.OwnersPerChain, - cfg.ProposerMCMSes, - batches, - "Accept ownership of contracts", - cfg.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w, batches: %+v", err, batches) - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, - }, nil -} diff --git a/deployment/common/changeset/accept_ownership_test.go b/deployment/common/changeset/accept_ownership_test.go deleted file mode 100644 index fc2c296f2d8..00000000000 --- a/deployment/common/changeset/accept_ownership_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package changeset_test - -import ( - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink/deployment/common/changeset" -) - -func TestAcceptOwnershipConfig_Validate(t *testing.T) { - tests := []struct { - name string - config changeset.AcceptOwnershipConfig - wantErr bool - }{ - { - name: "valid config", - config: changeset.AcceptOwnershipConfig{ - OwnersPerChain: map[uint64]common.Address{ - 1: common.HexToAddress("0x1"), - }, - ProposerMCMSes: map[uint64]*gethwrappers.ManyChainMultiSig{ - 1: {}, - }, - Contracts: map[uint64][]changeset.OwnershipAcceptor{ - 1: {}, - }, - MinDelay: 3 * time.Hour, - }, - wantErr: false, - }, - { - name: "missing timelock", - config: changeset.AcceptOwnershipConfig{ - OwnersPerChain: map[uint64]common.Address{}, - ProposerMCMSes: map[uint64]*gethwrappers.ManyChainMultiSig{ - 1: {}, - }, - Contracts: map[uint64][]changeset.OwnershipAcceptor{ - 1: {}, - }, - MinDelay: 3 * time.Hour, - }, - wantErr: true, - }, - { - name: "missing proposer MCMS", - config: changeset.AcceptOwnershipConfig{ - OwnersPerChain: map[uint64]common.Address{ - 1: common.HexToAddress("0x1"), - }, - ProposerMCMSes: map[uint64]*gethwrappers.ManyChainMultiSig{}, - Contracts: map[uint64][]changeset.OwnershipAcceptor{ - 1: {}, - }, - MinDelay: 3 * time.Hour, - }, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := tt.config.Validate() - if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - }) - } -} diff --git a/deployment/common/changeset/deploy_link_token.go b/deployment/common/changeset/deploy_link_token.go index 5f88b410f67..5728e977c47 100644 --- a/deployment/common/changeset/deploy_link_token.go +++ b/deployment/common/changeset/deploy_link_token.go @@ -10,20 +10,24 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" ) -var _ deployment.ChangeSet[uint64] = DeployLinkToken +var _ deployment.ChangeSet[[]uint64] = DeployLinkToken // DeployLinkToken deploys a link token contract to the chain identified by the chainSelector. -func DeployLinkToken(e deployment.Environment, chainSelector uint64) (deployment.ChangesetOutput, error) { - c, ok := e.Chains[chainSelector] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") +func DeployLinkToken(e deployment.Environment, chains []uint64) (deployment.ChangesetOutput, error) { + for _, chain := range chains { + _, ok := e.Chains[chain] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") + } } newAddresses := deployment.NewMemoryAddressBook() - _, err := deployLinkTokenContract( - e.Logger, c, newAddresses, - ) - if err != nil { - return deployment.ChangesetOutput{AddressBook: newAddresses}, err + for _, chain := range chains { + _, err := deployLinkTokenContract( + e.Logger, e.Chains[chain], newAddresses, + ) + if err != nil { + return deployment.ChangesetOutput{AddressBook: newAddresses}, err + } } return deployment.ChangesetOutput{AddressBook: newAddresses}, nil } diff --git a/deployment/common/changeset/deploy_link_token_test.go b/deployment/common/changeset/deploy_link_token_test.go index a18e0181623..29a9ece1478 100644 --- a/deployment/common/changeset/deploy_link_token_test.go +++ b/deployment/common/changeset/deploy_link_token_test.go @@ -3,37 +3,37 @@ package changeset_test import ( "testing" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) func TestDeployLinkToken(t *testing.T) { t.Parallel() - - lggr := logger.Test(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - chainSelector := env.AllChainSelectors()[0] - - resp, err := changeset.DeployLinkToken(env, chainSelector) + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + }) + chain1 := e.AllChainSelectors()[0] + e, err := changeset.ApplyChangesets(t, e, nil, []changeset.ChangesetApplication{ + { + Changeset: changeset.WrapChangeSet(changeset.DeployLinkToken), + Config: []uint64{chain1}, + }, + }) require.NoError(t, err) - require.NotNil(t, resp) - - // LinkToken should be deployed on chain 0 - addrs, err := resp.AddressBook.AddressesForChain(chainSelector) + addrs, err := e.ExistingAddresses.AddressesForChain(chain1) require.NoError(t, err) - require.Len(t, addrs, 1) - - // nothing on chain 1 - require.NotEqual(t, chainSelector, env.AllChainSelectors()[1]) - oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) - assert.Len(t, oaddrs, 0) + state, err := changeset.LoadLinkTokenState(e.Chains[chain1], addrs) + require.NoError(t, err) + view, err := state.GenerateLinkView() + require.NoError(t, err) + assert.Equal(t, view.Owner, e.Chains[chain1].DeployerKey.From) + assert.Equal(t, view.TypeAndVersion, "LinkToken 1.0.0") + // Initially nothing minted. + assert.Equal(t, view.Supply.String(), "0") } diff --git a/deployment/common/changeset/state.go b/deployment/common/changeset/state.go index 38a1d02c044..f553e124a38 100644 --- a/deployment/common/changeset/state.go +++ b/deployment/common/changeset/state.go @@ -9,6 +9,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" ) // MCMSWithTimelockState holds the Go bindings @@ -97,3 +98,28 @@ func LoadMCMSWithTimelockState(chain deployment.Chain, addresses map[string]depl } return &state, nil } + +type LinkTokenState struct { + LinkToken *link_token.LinkToken +} + +func (s LinkTokenState) GenerateLinkView() (v1_0.LinkTokenView, error) { + if s.LinkToken == nil { + return v1_0.LinkTokenView{}, errors.New("link token not found") + } + return v1_0.GenerateLinkTokenView(s.LinkToken) +} + +func LoadLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*LinkTokenState, error) { + state := LinkTokenState{} + for address, tvStr := range addresses { + if tvStr.String() == deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0).String() { + lt, err := link_token.NewLinkToken(common.HexToAddress(address), chain.Client) + if err != nil { + return nil, err + } + state.LinkToken = lt + } + } + return &state, nil +} diff --git a/deployment/common/changeset/transfer_ownership.go b/deployment/common/changeset/transfer_ownership.go deleted file mode 100644 index 36fe2cbed78..00000000000 --- a/deployment/common/changeset/transfer_ownership.go +++ /dev/null @@ -1,71 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - - "github.com/smartcontractkit/chainlink/deployment" -) - -type OwnershipTransferrer interface { - TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*gethtypes.Transaction, error) - Owner(opts *bind.CallOpts) (common.Address, error) -} - -type TransferOwnershipConfig struct { - // OwnersPerChain is a mapping from chain selector to the owner's contract address on that chain. - OwnersPerChain map[uint64]common.Address - - // Contracts is a mapping from chain selector to the ownership transferrers on that chain. - Contracts map[uint64][]OwnershipTransferrer -} - -func (t TransferOwnershipConfig) Validate() error { - // check that we have owners for the chains in the Contracts field. - for chainSelector := range t.Contracts { - if _, ok := t.OwnersPerChain[chainSelector]; !ok { - return fmt.Errorf("missing owners for chain %d", chainSelector) - } - } - - return nil -} - -var _ deployment.ChangeSet[TransferOwnershipConfig] = NewTransferOwnershipChangeset - -// NewTransferOwnershipChangeset creates a changeset that transfers ownership of all the -// contracts in the provided configuration to correct owner on that chain. -// If the owner is already the provided address, no transaction is sent. -func NewTransferOwnershipChangeset( - e deployment.Environment, - cfg TransferOwnershipConfig, -) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(); err != nil { - return deployment.ChangesetOutput{}, err - } - - for chainSelector, contracts := range cfg.Contracts { - ownerAddress := cfg.OwnersPerChain[chainSelector] - for _, contract := range contracts { - owner, err := contract.Owner(nil) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get owner of contract %T: %v", contract, err) - } - if owner != ownerAddress { - tx, err := contract.TransferOwnership(e.Chains[chainSelector].DeployerKey, ownerAddress) - _, err = deployment.ConfirmIfNoError(e.Chains[chainSelector], tx, err) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %v", contract, err) - } - } - } - } - - // no new addresses or proposals or jobspecs, so changeset output is empty. - // NOTE: onchain state has technically changed for above contracts, maybe that should - // be captured? - return deployment.ChangesetOutput{}, nil -} diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock.go b/deployment/common/changeset/transfer_to_mcms_with_timelock.go new file mode 100644 index 00000000000..e48d29af92b --- /dev/null +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock.go @@ -0,0 +1,144 @@ +package changeset + +import ( + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + gethtypes "github.com/ethereum/go-ethereum/core/types" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" +) + +type TransferToMCMSWithTimelockConfig struct { + ContractsByChain map[uint64][]common.Address + // MinDelay is for the accept ownership proposal + MinDelay time.Duration +} + +type Ownable interface { + Owner(opts *bind.CallOpts) (common.Address, error) + TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*gethtypes.Transaction, error) + AcceptOwnership(opts *bind.TransactOpts) (*gethtypes.Transaction, error) + Address() common.Address +} + +func LoadOwnableContract(addr common.Address, client bind.ContractBackend) (common.Address, Ownable, error) { + // Just using the ownership interface from here. + c, err := burn_mint_erc677.NewBurnMintERC677(addr, client) + if err != nil { + return common.Address{}, nil, fmt.Errorf("failed to create contract: %v", err) + } + owner, err := c.Owner(nil) + if err != nil { + return common.Address{}, nil, fmt.Errorf("failed to get owner of contract: %v", err) + } + return owner, c, nil +} + +func (t TransferToMCMSWithTimelockConfig) Validate(e deployment.Environment) error { + for chainSelector, contracts := range t.ContractsByChain { + for _, contract := range contracts { + // Cannot transfer an unknown address. + // Note this also assures non-zero addresses. + if exists, err := deployment.AddressBookContains(e.ExistingAddresses, chainSelector, contract.String()); err != nil || !exists { + if err != nil { + return fmt.Errorf("failed to check address book: %v", err) + } + return fmt.Errorf("contract %s not found in address book", contract) + } + owner, _, err := LoadOwnableContract(contract, e.Chains[chainSelector].Client) + if err != nil { + return fmt.Errorf("failed to load ownable: %v", err) + } + if owner != e.Chains[chainSelector].DeployerKey.From { + return fmt.Errorf("contract %s is not owned by the deployer key", contract) + } + } + // If there is no timelock and mcms proposer on the chain, the transfer will fail. + if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.RBACTimelock); err != nil { + return fmt.Errorf("timelock not present on the chain %v", err) + } + if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.ProposerManyChainMultisig); err != nil { + return fmt.Errorf("mcms proposer not present on the chain %v", err) + } + } + + return nil +} + +var _ deployment.ChangeSet[TransferToMCMSWithTimelockConfig] = TransferToMCMSWithTimelock + +// TransferToMCMSWithTimelock creates a changeset that transfers ownership of all the +// contracts in the provided configuration to the timelock on the chain and generates +// a corresponding accept ownership proposal to complete the transfer. +// It assumes that DeployMCMSWithTimelock has already been run s.t. +// the timelock and mcmses exist on the chain and that the proposed addresses to transfer ownership +// are currently owned by the deployer key. +func TransferToMCMSWithTimelock( + e deployment.Environment, + cfg TransferToMCMSWithTimelockConfig, +) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(e); err != nil { + return deployment.ChangesetOutput{}, err + } + var batches []timelock.BatchChainOperation + timelocksByChain := make(map[uint64]common.Address) + proposersByChain := make(map[uint64]*owner_helpers.ManyChainMultiSig) + for chainSelector, contracts := range cfg.ContractsByChain { + // Already validated that the timelock/proposer exists. + timelockAddr, _ := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.RBACTimelock) + proposerAddr, _ := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.ProposerManyChainMultisig) + timelocksByChain[chainSelector] = common.HexToAddress(timelockAddr) + proposer, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(proposerAddr), e.Chains[chainSelector].Client) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create proposer mcms: %v", err) + } + proposersByChain[chainSelector] = proposer + + var ops []mcms.Operation + for _, contract := range contracts { + // Just using the ownership interface. + // Already validated is ownable. + owner, c, _ := LoadOwnableContract(contract, e.Chains[chainSelector].Client) + if owner.String() == timelockAddr { + // Already owned by timelock. + e.Logger.Infof("contract %s already owned by timelock", contract) + continue + } + tx, err := c.TransferOwnership(e.Chains[chainSelector].DeployerKey, common.HexToAddress(timelockAddr)) + _, err = deployment.ConfirmIfNoError(e.Chains[chainSelector], tx, err) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %v", contract, err) + } + tx, err = c.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate accept ownership calldata of %s: %w", contract, err) + } + ops = append(ops, mcms.Operation{ + To: contract, + Data: tx.Data(), + Value: big.NewInt(0), + }) + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chainSelector), + Batch: ops, + }) + } + proposal, err := proposalutils.BuildProposalFromBatches( + timelocksByChain, proposersByChain, batches, "Transfer ownership to timelock", cfg.MinDelay) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w, batches: %+v", err, batches) + } + + return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{*proposal}}, nil +} diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go new file mode 100644 index 00000000000..f1f24cb0b05 --- /dev/null +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go @@ -0,0 +1,69 @@ +package changeset + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/stretchr/testify/require" + + "math/big" + + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestTransferToMCMSWithTimelock(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ + Chains: 1, + Nodes: 1, + }) + chain1 := e.AllChainSelectors()[0] + e, err := ApplyChangesets(t, e, nil, []ChangesetApplication{ + { + Changeset: WrapChangeSet(DeployLinkToken), + Config: []uint64{chain1}, + }, + { + Changeset: WrapChangeSet(DeployMCMSWithTimelock), + Config: map[uint64]types.MCMSWithTimelockConfig{ + chain1: { + Canceller: SingleGroupMCMS(t), + Bypasser: SingleGroupMCMS(t), + Proposer: SingleGroupMCMS(t), + TimelockExecutors: e.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + }, + }, + }, + }) + require.NoError(t, err) + addrs, err := e.ExistingAddresses.AddressesForChain(chain1) + require.NoError(t, err) + state, err := LoadMCMSWithTimelockState(e.Chains[chain1], addrs) + require.NoError(t, err) + link, err := LoadLinkTokenState(e.Chains[chain1], addrs) + require.NoError(t, err) + e, err = ApplyChangesets(t, e, map[uint64]*owner_helpers.RBACTimelock{ + chain1: state.Timelock, + }, []ChangesetApplication{ + { + Changeset: WrapChangeSet(TransferToMCMSWithTimelock), + Config: TransferToMCMSWithTimelockConfig{ + ContractsByChain: map[uint64][]common.Address{ + chain1: {link.LinkToken.Address()}, + }, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) + // We expect now that the link token is owned by the MCMS timelock. + link, err = LoadLinkTokenState(e.Chains[chain1], addrs) + require.NoError(t, err) + o, err := link.LinkToken.Owner(nil) + require.NoError(t, err) + require.Equal(t, state.Timelock.Address(), o) +} diff --git a/deployment/common/proposalutils/propose.go b/deployment/common/proposalutils/propose.go index b4cb54af891..f525c0b6643 100644 --- a/deployment/common/proposalutils/propose.go +++ b/deployment/common/proposalutils/propose.go @@ -34,7 +34,7 @@ func buildProposalMetadata( return metaDataPerChain, nil } -// Given batches of operations, we build the metadata and timelock addresses of those opartions +// BuildProposalFromBatches Given batches of operations, we build the metadata and timelock addresses of those opartions // We then return a proposal that can be executed and signed func BuildProposalFromBatches( timelocksPerChain map[uint64]common.Address, diff --git a/deployment/common/view/v1_0/link_token.go b/deployment/common/view/v1_0/link_token.go new file mode 100644 index 00000000000..38649037592 --- /dev/null +++ b/deployment/common/view/v1_0/link_token.go @@ -0,0 +1,43 @@ +package v1_0 + +import ( + "math/big" + + "github.com/smartcontractkit/chainlink/deployment" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/common/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" +) + +type LinkTokenView struct { + types.ContractMetaData + Decimals uint8 `json:"decimals"` + Supply *big.Int `json:"supply"` +} + +func GenerateLinkTokenView(lt *link_token.LinkToken) (LinkTokenView, error) { + owner, err := lt.Owner(nil) + if err != nil { + return LinkTokenView{}, err + } + decimals, err := lt.Decimals(nil) + if err != nil { + return LinkTokenView{}, err + } + totalSupply, err := lt.TotalSupply(nil) + if err != nil { + return LinkTokenView{}, err + } + return LinkTokenView{ + ContractMetaData: types.ContractMetaData{ + TypeAndVersion: deployment.TypeAndVersion{ + commontypes.LinkToken, + deployment.Version1_0_0, + }.String(), + Address: lt.Address(), + Owner: owner, + }, + Decimals: decimals, + Supply: totalSupply, + }, nil +} diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index 83346a60602..f4692998d34 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -101,6 +101,9 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment.Chain, numNodes, numBootstraps int, registryConfig deployment.CapabilityRegistryConfig) map[string]Node { nodesByPeerID := make(map[string]Node) + if numNodes+numBootstraps == 0 { + return nodesByPeerID + } ports := freeport.GetN(t, numBootstraps+numNodes) // bootstrap nodes must be separate nodes from plugin nodes, // since we won't run a bootstrapper and a plugin oracle on the same diff --git a/deployment/keystone/changeset/accept_ownership.go b/deployment/keystone/changeset/accept_ownership.go index 8a4f3c60c53..7dffc5a70c4 100644 --- a/deployment/keystone/changeset/accept_ownership.go +++ b/deployment/keystone/changeset/accept_ownership.go @@ -5,20 +5,10 @@ import ( "github.com/ethereum/go-ethereum/common" - ccipowner "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset" ) -func toOwnershipAcceptors[T changeset.OwnershipAcceptor](items []T) []changeset.OwnershipAcceptor { - ownershipAcceptors := make([]changeset.OwnershipAcceptor, len(items)) - for i, item := range items { - ownershipAcceptors[i] = item - } - return ownershipAcceptors -} - type AcceptAllOwnershipRequest struct { ChainSelector uint64 MinDelay time.Duration @@ -33,11 +23,6 @@ func AcceptAllOwnershipsProposal(e deployment.Environment, req *AcceptAllOwnersh chain := e.Chains[chainSelector] addrBook := e.ExistingAddresses - // Fetch contracts from the address book. - timelocks, err := timelocksFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, err - } capRegs, err := capRegistriesFromAddrBook(addrBook, chain) if err != nil { return deployment.ChangesetOutput{}, err @@ -54,36 +39,27 @@ func AcceptAllOwnershipsProposal(e deployment.Environment, req *AcceptAllOwnersh if err != nil { return deployment.ChangesetOutput{}, err } - mcmsProposers, err := proposersFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, err + var addrsToTransfer []common.Address + for _, consumer := range consumers { + addrsToTransfer = append(addrsToTransfer, consumer.Address()) + } + for _, o := range ocr3 { + addrsToTransfer = append(addrsToTransfer, o.Address()) + } + for _, f := range forwarders { + addrsToTransfer = append(addrsToTransfer, f.Address()) + } + for _, c := range capRegs { + addrsToTransfer = append(addrsToTransfer, c.Address()) } - - // Initialize the OwnershipAcceptors slice - var ownershipAcceptors []changeset.OwnershipAcceptor - - // Append all contracts - ownershipAcceptors = append(ownershipAcceptors, toOwnershipAcceptors(capRegs)...) - ownershipAcceptors = append(ownershipAcceptors, toOwnershipAcceptors(ocr3)...) - ownershipAcceptors = append(ownershipAcceptors, toOwnershipAcceptors(forwarders)...) - ownershipAcceptors = append(ownershipAcceptors, toOwnershipAcceptors(consumers)...) - // Construct the configuration - cfg := changeset.AcceptOwnershipConfig{ - OwnersPerChain: map[uint64]common.Address{ - // Assuming there is only one timelock per chain. - chainSelector: timelocks[0].Address(), - }, - ProposerMCMSes: map[uint64]*ccipowner.ManyChainMultiSig{ - // Assuming there is only one MCMS proposer per chain. - chainSelector: mcmsProposers[0], - }, - Contracts: map[uint64][]changeset.OwnershipAcceptor{ - chainSelector: ownershipAcceptors, + cfg := changeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: map[uint64][]common.Address{ + chainSelector: addrsToTransfer, }, MinDelay: minDelay, } // Create and return the changeset - return changeset.NewAcceptOwnershipChangeset(e, cfg) + return changeset.TransferToMCMSWithTimelock(e, cfg) } diff --git a/deployment/keystone/changeset/accept_ownership_test.go b/deployment/keystone/changeset/accept_ownership_test.go index 996ff08c149..997f0b7e163 100644 --- a/deployment/keystone/changeset/accept_ownership_test.go +++ b/deployment/keystone/changeset/accept_ownership_test.go @@ -3,12 +3,13 @@ package changeset_test import ( "math/big" "testing" - "time" - "github.com/smartcontractkit/chainlink-common/pkg/logger" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -24,63 +25,52 @@ func TestAcceptAllOwnership(t *testing.T) { } env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) registrySel := env.AllChainSelectors()[0] - chCapReg, err := changeset.DeployCapabilityRegistry(env, registrySel) - require.NoError(t, err) - require.NotNil(t, chCapReg) - err = env.ExistingAddresses.Merge(chCapReg.AddressBook) - require.NoError(t, err) - - chOcr3, err := changeset.DeployOCR3(env, registrySel) - require.NoError(t, err) - require.NotNil(t, chOcr3) - err = env.ExistingAddresses.Merge(chOcr3.AddressBook) - require.NoError(t, err) - - chForwarder, err := changeset.DeployForwarder(env, registrySel) - require.NoError(t, err) - require.NotNil(t, chForwarder) - err = env.ExistingAddresses.Merge(chForwarder.AddressBook) - require.NoError(t, err) - - chConsumer, err := changeset.DeployFeedsConsumer(env, &changeset.DeployFeedsConsumerRequest{ - ChainSelector: registrySel, - }) - require.NoError(t, err) - require.NotNil(t, chConsumer) - err = env.ExistingAddresses.Merge(chConsumer.AddressBook) - require.NoError(t, err) - - chMcms, err := commonchangeset.DeployMCMSWithTimelock(env, map[uint64]types.MCMSWithTimelockConfig{ - registrySel: { - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), + env, err := commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployCapabilityRegistry), + Config: registrySel, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployOCR3), + Config: registrySel, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployForwarder), + Config: registrySel, + }, + { + Changeset: commonchangeset.WrapChangeSet(changeset.DeployFeedsConsumer), + Config: &changeset.DeployFeedsConsumerRequest{ChainSelector: registrySel}, + }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]types.MCMSWithTimelockConfig{ + registrySel: { + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + }, + }, }, }) - err = env.ExistingAddresses.Merge(chMcms.AddressBook) require.NoError(t, err) - + addrs, err := env.ExistingAddresses.AddressesForChain(registrySel) require.NoError(t, err) - require.NotNil(t, chMcms) - - resp, err := changeset.TransferAllOwnership(env, &changeset.TransferAllOwnershipRequest{ - ChainSelector: registrySel, - }) + timelock, err := commonchangeset.LoadMCMSWithTimelockState(env.Chains[registrySel], addrs) require.NoError(t, err) - require.NotNil(t, resp) - // Test the changeset - output, err := changeset.AcceptAllOwnershipsProposal(env, &changeset.AcceptAllOwnershipRequest{ - ChainSelector: registrySel, - MinDelay: time.Duration(0), + _, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*owner_helpers.RBACTimelock{ + registrySel: timelock.Timelock, + }, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.AcceptAllOwnershipsProposal), + Config: &changeset.AcceptAllOwnershipRequest{ + ChainSelector: registrySel, + MinDelay: 0, + }, + }, }) require.NoError(t, err) - require.NotNil(t, output) - require.Len(t, output.Proposals, 1) - proposal := output.Proposals[0] - require.Len(t, proposal.Transactions, 1) - txs := proposal.Transactions[0] - require.Len(t, txs.Batch, 4) } diff --git a/deployment/keystone/changeset/deploy_ocr3.go b/deployment/keystone/changeset/deploy_ocr3.go index a88fe4afa62..40d9e558584 100644 --- a/deployment/keystone/changeset/deploy_ocr3.go +++ b/deployment/keystone/changeset/deploy_ocr3.go @@ -9,12 +9,10 @@ import ( kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) -func DeployOCR3(env deployment.Environment, config interface{}) (deployment.ChangesetOutput, error) { +var _ deployment.ChangeSet[uint64] = DeployOCR3 + +func DeployOCR3(env deployment.Environment, registryChainSel uint64) (deployment.ChangesetOutput, error) { lggr := env.Logger - registryChainSel, ok := config.(uint64) - if !ok { - return deployment.ChangesetOutput{}, deployment.ErrInvalidConfig - } ab := deployment.NewMemoryAddressBook() // ocr3 only deployed on registry chain c, ok := env.Chains[registryChainSel] diff --git a/deployment/keystone/changeset/transfer_ownership.go b/deployment/keystone/changeset/transfer_ownership.go deleted file mode 100644 index 73af5d5bdb2..00000000000 --- a/deployment/keystone/changeset/transfer_ownership.go +++ /dev/null @@ -1,84 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" -) - -func toOwnershipTransferrer[T changeset.OwnershipTransferrer](items []T) []changeset.OwnershipTransferrer { - ownershipAcceptors := make([]changeset.OwnershipTransferrer, len(items)) - for i, item := range items { - ownershipAcceptors[i] = item - } - return ownershipAcceptors -} - -type TransferAllOwnershipRequest struct { - ChainSelector uint64 -} - -var _ deployment.ChangeSet[*TransferAllOwnershipRequest] = TransferAllOwnership - -// TransferAllOwnership transfers ownership of all Keystone contracts in the address book to the existing timelock. -func TransferAllOwnership(e deployment.Environment, req *TransferAllOwnershipRequest) (deployment.ChangesetOutput, error) { - chainSelector := req.ChainSelector - chain := e.Chains[chainSelector] - addrBook := e.ExistingAddresses - - // Fetch timelocks for the specified chain. - timelocks, err := timelocksFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to fetch timelocks: %w", err) - } - if len(timelocks) == 0 { - return deployment.ChangesetOutput{}, fmt.Errorf("no timelocks found for chain %d", chainSelector) - } - - // Fetch contracts from the address book. - capRegs, err := capRegistriesFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to fetch capabilities registries: %w", err) - } - - ocr3s, err := ocr3FromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to fetch OCR3 capabilities: %w", err) - } - - forwarders, err := forwardersFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to fetch forwarders: %w", err) - } - - consumers, err := feedsConsumersFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to fetch feeds consumers: %w", err) - } - - // Initialize the Contracts slice - var ownershipTransferrers []changeset.OwnershipTransferrer - - // Append all contracts - ownershipTransferrers = append(ownershipTransferrers, toOwnershipTransferrer(capRegs)...) - ownershipTransferrers = append(ownershipTransferrers, toOwnershipTransferrer(ocr3s)...) - ownershipTransferrers = append(ownershipTransferrers, toOwnershipTransferrer(forwarders)...) - ownershipTransferrers = append(ownershipTransferrers, toOwnershipTransferrer(consumers)...) - - // Construct the configuration - cfg := changeset.TransferOwnershipConfig{ - OwnersPerChain: map[uint64]common.Address{ - // Assuming there is only one timelock per chain. - chainSelector: timelocks[0].Address(), - }, - Contracts: map[uint64][]changeset.OwnershipTransferrer{ - chainSelector: ownershipTransferrers, - }, - } - - // Create and return the changeset - return changeset.NewTransferOwnershipChangeset(e, cfg) -} diff --git a/deployment/keystone/changeset/transfer_ownership_test.go b/deployment/keystone/changeset/transfer_ownership_test.go deleted file mode 100644 index dc5630076bd..00000000000 --- a/deployment/keystone/changeset/transfer_ownership_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package changeset_test - -import ( - "math/big" - "testing" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" -) - -func TestTransferAllOwnership(t *testing.T) { - t.Parallel() - lggr := logger.Test(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - registrySel := env.AllChainSelectors()[0] - chCapReg, err := changeset.DeployCapabilityRegistry(env, registrySel) - require.NoError(t, err) - require.NotNil(t, chCapReg) - err = env.ExistingAddresses.Merge(chCapReg.AddressBook) - require.NoError(t, err) - - chOcr3, err := changeset.DeployOCR3(env, registrySel) - require.NoError(t, err) - require.NotNil(t, chOcr3) - err = env.ExistingAddresses.Merge(chOcr3.AddressBook) - require.NoError(t, err) - - chForwarder, err := changeset.DeployForwarder(env, registrySel) - require.NoError(t, err) - require.NotNil(t, chForwarder) - err = env.ExistingAddresses.Merge(chForwarder.AddressBook) - require.NoError(t, err) - - chConsumer, err := changeset.DeployFeedsConsumer(env, &changeset.DeployFeedsConsumerRequest{ - ChainSelector: registrySel, - }) - require.NoError(t, err) - require.NotNil(t, chConsumer) - err = env.ExistingAddresses.Merge(chConsumer.AddressBook) - require.NoError(t, err) - - chMcms, err := commonchangeset.DeployMCMSWithTimelock(env, map[uint64]types.MCMSWithTimelockConfig{ - registrySel: { - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), - }, - }) - err = env.ExistingAddresses.Merge(chMcms.AddressBook) - require.NoError(t, err) - - require.NoError(t, err) - require.NotNil(t, chMcms) - - resp, err := changeset.TransferAllOwnership(env, &changeset.TransferAllOwnershipRequest{ - ChainSelector: registrySel, - }) - require.NoError(t, err) - require.NotNil(t, resp) -} diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/testsetups/ccip/test_helpers.go index fc9925372bc..4d51093d419 100644 --- a/integration-tests/testsetups/ccip/test_helpers.go +++ b/integration-tests/testsetups/ccip/test_helpers.go @@ -169,6 +169,10 @@ func NewLocalDevEnvironment( }, }, }, + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), + Config: allChains, + }, { Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisites), Config: changeset.DeployPrerequisiteConfig{ From 486f0ae2abca609c5c390407f2496d575d33fcb5 Mon Sep 17 00:00:00 2001 From: Street <5597260+MStreet3@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:18:02 +0200 Subject: [PATCH 10/55] fix(workflows/syncer): increase test timeout for flake (#15503) --- .../evm/capabilities/workflows/syncer/workflow_syncer_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go index 28c5a28b303..3bcf8164a7b 100644 --- a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go +++ b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go @@ -254,7 +254,7 @@ func Test_SecretsWorker(t *testing.T) { lggr.Debugf("got secrets %v", secrets) require.NoError(t, err) return secrets == wantContents - }, 5*time.Second, time.Second) + }, 15*time.Second, time.Second) } func updateAuthorizedAddress( From 5ef07c836b9deb38ccfdca04cbf7fd3d79f18aef Mon Sep 17 00:00:00 2001 From: nogo <110664798+0xnogo@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:45:48 +0400 Subject: [PATCH 11/55] Benchmark ccip_reader queries (#15363) * benchmarkCommitReports * adding more bench tests + lint * fix test * addressing comments * change with merge * refactor * addressing comments * add ContractNameToBind --- .../contracts/ccipreader_test.go | 695 ++++++++++++++---- 1 file changed, 545 insertions(+), 150 deletions(-) diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go index cec9564a30d..3028f4707a4 100644 --- a/integration-tests/contracts/ccipreader_test.go +++ b/integration-tests/contracts/ccipreader_test.go @@ -2,6 +2,7 @@ package contracts import ( "context" + "fmt" "math/big" "sort" "testing" @@ -12,10 +13,12 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" "github.com/smartcontractkit/chainlink-ccip/plugintypes" @@ -24,9 +27,11 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/utils/pgtest" readermocks "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/contractreader" + + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" @@ -45,6 +50,10 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + + evmchaintypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" ) const ( @@ -58,31 +67,19 @@ var ( defaultGasPrice = assets.GWei(10) ) -func setupGetCommitGTETimestampTest(ctx context.Context, t *testing.T, finalityDepth int64) (*testSetupData, int64, common.Address) { - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCommitReportAccepted}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCommitReportAccepted: { - ChainSpecificName: consts.EventNameCommitReportAccepted, - ReadType: evmtypes.Event, - }, - }, - }, - }, - } +var ( + onrampABI = evmchaintypes.MustGetABI(onramp.OnRampABI) + offrampABI = evmchaintypes.MustGetABI(offramp.OffRampABI) +) +func setupGetCommitGTETimestampTest(ctx context.Context, t testing.TB, finalityDepth int64, useHeavyDB bool) (*testSetupData, int64, common.Address) { sb, auth := setupSimulatedBackendAndAuth(t) onRampAddress := utils.RandomAddress() s := testSetup(ctx, t, testSetupParams{ ReaderChain: chainD, DestChain: chainD, OnChainSeqNums: nil, - Cfg: cfg, + Cfg: evmconfig.DestReaderConfig, ToMockBindings: map[cciptypes.ChainSelector][]types.BoundContract{ chainS1: { { @@ -91,15 +88,52 @@ func setupGetCommitGTETimestampTest(ctx context.Context, t *testing.T, finalityD }, }, }, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - FinalityDepth: finalityDepth, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, + FinalityDepth: finalityDepth, + UseHeavyDB: useHeavyDB, }) return s, finalityDepth, onRampAddress } +func setupExecutedMessageRangesTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { + sb, auth := setupSimulatedBackendAndAuth(t) + return testSetup(ctx, t, testSetupParams{ + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: evmconfig.DestReaderConfig, + // Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, + }) +} + +func setupMsgsBetweenSeqNumsTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { + sb, auth := setupSimulatedBackendAndAuth(t) + return testSetup(ctx, t, testSetupParams{ + ReaderChain: chainS1, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: evmconfig.SourceReaderConfig, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOnRamp, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, + }) +} + func emitCommitReports(ctx context.Context, t *testing.T, s *testSetupData, numReports int, tokenA common.Address, onRampAddress common.Address) uint64 { var firstReportTs uint64 for i := uint8(0); int(i) < numReports; i++ { @@ -138,7 +172,7 @@ func emitCommitReports(ctx context.Context, t *testing.T, s *testSetupData, numR }, }, }) - assert.NoError(t, err) + require.NoError(t, err) bh := s.sb.Commit() b, err := s.sb.Client().BlockByHash(ctx, bh) require.NoError(t, err) @@ -152,7 +186,7 @@ func emitCommitReports(ctx context.Context, t *testing.T, s *testSetupData, numR func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { t.Parallel() ctx := tests.Context(t) - s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, 0) + s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, 0, false) tokenA := common.HexToAddress("123") const numReports = 5 @@ -196,7 +230,7 @@ func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) { t.Parallel() ctx := tests.Context(t) var finalityDepth int64 = 10 - s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, finalityDepth) + s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, finalityDepth, false) tokenA := common.HexToAddress("123") const numReports = 5 @@ -258,46 +292,7 @@ func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) { func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { t.Parallel() ctx := tests.Context(t) - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameExecutionStateChanged}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameExecutionStateChanged: { - ChainSpecificName: consts.EventNameExecutionStateChanged, - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericTopicNames: map[string]string{ - "sourceChainSelector": consts.EventAttributeSourceChain, - "sequenceNumber": consts.EventAttributeSequenceNumber, - }, - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeState: { - Name: "state", - }, - }, - }, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - }) + s := setupExecutedMessageRangesTest(ctx, t, false) _, err := s.contract.EmitExecutionStateChanged( s.auth, uint64(chainS1), @@ -308,7 +303,7 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { []byte{1, 2, 3, 4}, big.NewInt(250_000), ) - assert.NoError(t, err) + require.NoError(t, err) s.sb.Commit() _, err = s.contract.EmitExecutionStateChanged( @@ -321,7 +316,7 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { []byte{1, 2, 3, 4, 5}, big.NewInt(350_000), ) - assert.NoError(t, err) + require.NoError(t, err) s.sb.Commit() // Need to replay as sometimes the logs are not picked up by the log poller (?) @@ -351,50 +346,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { t.Parallel() ctx := tests.Context(t) - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCCIPMessageSent}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCCIPMessageSent: { - ChainSpecificName: "CCIPMessageSent", - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeSourceChain: {Name: "message.header.sourceChainSelector"}, - consts.EventAttributeDestChain: {Name: "message.header.destChainSelector"}, - consts.EventAttributeSequenceNumber: {Name: "message.header.sequenceNumber"}, - }, - }, - OutputModifications: codec.ModifiersConfig{ - &codec.WrapperModifierConfig{Fields: map[string]string{ - "Message.FeeTokenAmount": "Int", - "Message.FeeValueJuels": "Int", - "Message.TokenAmounts.Amount": "Int", - }}, - }, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainS1, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - }) - + s := setupMsgsBetweenSeqNumsTest(ctx, t, false) _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ Header: ccip_reader_tester.InternalRampMessageHeader{ MessageId: [32]byte{1, 0, 0, 0, 0}, @@ -411,7 +363,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { FeeValueJuels: big.NewInt(2), TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(1)}, {Amount: big.NewInt(2)}}, }) - assert.NoError(t, err) + require.NoError(t, err) _, err = s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ Header: ccip_reader_tester.InternalRampMessageHeader{ @@ -429,7 +381,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { FeeValueJuels: big.NewInt(4), TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(3)}, {Amount: big.NewInt(4)}}, }) - assert.NoError(t, err) + require.NoError(t, err) s.sb.Commit() @@ -497,19 +449,20 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { sb, auth := setupSimulatedBackendAndAuth(t) s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: onChainSeqNums, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: onChainSeqNums, + Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, }) seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, seqNums, 3) assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) @@ -597,19 +550,20 @@ func TestCCIPReader_Nonces(t *testing.T) { sb, auth := setupSimulatedBackendAndAuth(t) s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - Cfg: cfg, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, + ReaderChain: chainD, + DestChain: chainD, + Cfg: cfg, + BindTester: true, + ContractNameToBind: consts.ContractNameNonceManager, + SimulatedBackend: sb, + Auth: auth, }) // Add some nonces. for chain, addrs := range nonces { for addr, nonce := range addrs { _, err := s.contract.SetInboundNonce(s.auth, uint64(chain), nonce, common.LeftPadBytes(addr.Bytes(), 32)) - assert.NoError(t, err) + require.NoError(t, err) } } s.sb.Commit() @@ -622,7 +576,7 @@ func TestCCIPReader_Nonces(t *testing.T) { addrQuery = append(addrQuery, utils.RandomAddress().String()) results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, results, len(addrQuery)) for addr, nonce := range addrs { assert.Equal(t, nonce, results[addr.String()]) @@ -836,7 +790,438 @@ func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { require.Equal(t, changeset.DefaultInitialPrices.WethPrice, prices[cciptypes.ChainSelector(chain1)].Int) } -func setupSimulatedBackendAndAuth(t *testing.T) (*simulated.Backend, *bind.TransactOpts) { +// Benchmark Results: +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 16948 67728 ns/op 30387 B/op 417 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1650 741741 ns/op 528334 B/op 9929 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 195 6096328 ns/op 4739856 B/op 92345 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 2 582712583 ns/op 454375304 B/op 8931990 allocs/op +func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { + tests := []struct { + logsInsertedFirst int + logsInsertedMatching int + }{ + {0, 0}, + {1, 10}, + {10, 100}, + {100, 10_000}, + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("FirstLogs_%d_MatchLogs_%d", tt.logsInsertedMatching, tt.logsInsertedFirst), func(b *testing.B) { + benchmarkCommitReports(b, tt.logsInsertedFirst, tt.logsInsertedMatching) + }) + } +} + +func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedMatching int) { + // Initialize test setup + ctx := tests.Context(b) + s, _, _ := setupGetCommitGTETimestampTest(ctx, b, 0, true) + + if logsInsertedFirst > 0 { + populateDatabaseForCommitReportAccepted(ctx, b, s, chainD, chainS1, logsInsertedFirst, 0) + } + + queryTimestamp := time.Now() + + if logsInsertedMatching > 0 { + populateDatabaseForCommitReportAccepted(ctx, b, s, chainD, chainS1, logsInsertedMatching, logsInsertedFirst) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + for i := 0; i < b.N; i++ { + reports, err := s.reader.CommitReportsGTETimestamp(ctx, chainD, queryTimestamp, logsInsertedFirst) + require.NoError(b, err) + require.Len(b, reports, logsInsertedFirst) + } +} + +func populateDatabaseForCommitReportAccepted( + ctx context.Context, + b *testing.B, + testEnv *testSetupData, + destChain cciptypes.ChainSelector, + sourceChain cciptypes.ChainSelector, + numOfReports int, + offset int, +) { + var logs []logpoller.Log + commitReportEvent, exists := offrampABI.Events[consts.EventNameCommitReportAccepted] + require.True(b, exists, "Event CommitReportAccepted not found in ABI") + + commitReportEventSig := commitReportEvent.ID + commitReportAddress := testEnv.contractAddr + + // Calculate timestamp based on whether these are the first logs or matching logs + var timestamp time.Time + if offset == 0 { + // For first set of logs, set timestamp to 1 hour ago + timestamp = time.Now().Add(-1 * time.Hour) + } else { + // For matching logs, use current time + timestamp = time.Now() + } + + for i := 0; i < numOfReports; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Simulate merkleRoots + merkleRoots := []offramp.InternalMerkleRoot{ + { + SourceChainSelector: uint64(sourceChain), + OnRampAddress: utils.RandomAddress().Bytes(), + // #nosec G115 + MinSeqNr: uint64(i * 100), + // #nosec G115 + MaxSeqNr: uint64(i*100 + 99), + MerkleRoot: utils.RandomBytes32(), + }, + } + + sourceToken := utils.RandomAddress() + + // Simulate priceUpdates + priceUpdates := offramp.InternalPriceUpdates{ + TokenPriceUpdates: []offramp.InternalTokenPriceUpdate{ + {SourceToken: sourceToken, UsdPerToken: big.NewInt(8)}, + }, + GasPriceUpdates: []offramp.InternalGasPriceUpdate{ + {DestChainSelector: uint64(1), UsdPerUnitGas: big.NewInt(10)}, + }, + } + + // Combine encoded data + encodedData, err := commitReportEvent.Inputs.Pack(merkleRoots, priceUpdates) + require.NoError(b, err) + + // Topics (first one is the event signature) + topics := [][]byte{ + commitReportEventSig[:], + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(new(big.Int).SetUint64(uint64(destChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: timestamp, + EventSig: commitReportEventSig, + Topics: topics, + Address: commitReportAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports), timestamp, int64(offset+numOfReports))) +} + +// Benchmark Results: +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13599 93414 ns/op 43389 B/op 654 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 13471 88392 ns/op 43011 B/op 651 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 2799 473396 ns/op 303737 B/op 4535 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 438 2724414 ns/op 2477573 B/op 37468 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 40 29118796 ns/op 12607995 B/op 179396 allocs/op +func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { + tests := []struct { + logsInserted int + startSeqNum cciptypes.SeqNum + endSeqNum cciptypes.SeqNum + }{ + {0, 0, 10}, // no logs + {10, 10, 20}, // out of bounds + {10, 0, 9}, // get all messages with 10 logs + {100, 0, 100}, // get all messages with 100 logs + {100_000, 100_000 - 256, 100_000}, // get the last 256 messages + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { + benchmarkExecutedMessageRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) + }) + } +} + +func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) { + // Initialize test setup + ctx := tests.Context(b) + s := setupExecutedMessageRangesTest(ctx, b, true) + expectedRangeLen := calculateExpectedRangeLen(logsInsertedFirst, startSeqNum, endSeqNum) + + // Insert logs in two phases based on parameters + if logsInsertedFirst > 0 { + populateDatabaseForExecutionStateChanged(ctx, b, s, chainS1, chainD, logsInsertedFirst, 0) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + for i := 0; i < b.N; i++ { + executedRanges, err := s.reader.ExecutedMessageRanges( + ctx, + chainS1, + chainD, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), + ) + require.NoError(b, err) + require.Len(b, executedRanges, expectedRangeLen) + } +} + +func populateDatabaseForExecutionStateChanged( + ctx context.Context, + b *testing.B, + testEnv *testSetupData, + sourceChain cciptypes.ChainSelector, + destChain cciptypes.ChainSelector, + numOfEvents int, + offset int, +) { + var logs []logpoller.Log + executionStateEvent, exists := offrampABI.Events[consts.EventNameExecutionStateChanged] + require.True(b, exists, "Event ExecutionStateChanged not found in ABI") + + executionStateEventSig := executionStateEvent.ID + executionStateEventAddress := testEnv.contractAddr + + for i := 0; i < numOfEvents; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Populate fields for the event + sourceChainSelector := uint64(sourceChain) + // #nosec G115 + sequenceNumber := uint64(offset + i) + messageID := utils.NewHash() + messageHash := utils.NewHash() + state := uint8(1) + returnData := []byte{0x01, 0x02} + gasUsed := big.NewInt(int64(10000 + i)) + + // Encode the non indexed event data + encodedData, err := executionStateEvent.Inputs.NonIndexed().Pack( + messageHash, + state, + returnData, + gasUsed, + ) + require.NoError(b, err) + + // Topics (event signature and indexed fields) + topics := [][]byte{ + executionStateEventSig[:], // Event signature + logpoller.EvmWord(sourceChainSelector).Bytes(), // Indexed sourceChainSelector + logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber + messageID[:], // Indexed messageId + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(destChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: time.Now(), + EventSig: executionStateEventSig, + Topics: topics, + Address: executionStateEventAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) +} + +// Benchmark Results: +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13729 85838 ns/op 43473 B/op 647 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 870 1405208 ns/op 1156315 B/op 21102 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 90 12129488 ns/op 10833395 B/op 201076 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 10 105741438 ns/op 49103282 B/op 796213 allocs/op +func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { + tests := []struct { + logsInserted int + startSeqNum cciptypes.SeqNum + endSeqNum cciptypes.SeqNum + }{ + {0, 0, 10}, // No logs + {10, 0, 9}, // Get all messages with 10 logs + {100, 0, 100}, // Get all messages with 100 logs + {100_000, 100_000 - 256, 100_000}, // Get the last 256 messages + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { + benchmarkMessageSentRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) + }) + } +} + +func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, endSeqNum cciptypes.SeqNum) { + // Initialize test setup + ctx := tests.Context(b) + s := setupMsgsBetweenSeqNumsTest(ctx, b, true) + expectedRangeLen := calculateExpectedRangeLen(logsInserted, startSeqNum, endSeqNum) + + err := s.extendedCR.Bind(ctx, []types.BoundContract{ + { + Address: s.contractAddr.String(), + Name: consts.ContractNameOnRamp, + }, + }) + require.NoError(b, err) + + // Insert logs if needed + if logsInserted > 0 { + populateDatabaseForMessageSent(ctx, b, s, chainS1, chainD, logsInserted, 0) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + for i := 0; i < b.N; i++ { + msgs, err := s.reader.MsgsBetweenSeqNums( + ctx, + chainS1, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), + ) + require.NoError(b, err) + require.Len(b, msgs, expectedRangeLen) + } +} + +func populateDatabaseForMessageSent( + ctx context.Context, + b *testing.B, + testEnv *testSetupData, + sourceChain cciptypes.ChainSelector, + destChain cciptypes.ChainSelector, + numOfEvents int, + offset int, +) { + var logs []logpoller.Log + messageSentEvent, exists := onrampABI.Events[consts.EventNameCCIPMessageSent] + require.True(b, exists, "Event CCIPMessageSent not found in ABI") + + messageSentEventSig := messageSentEvent.ID + messageSentEventAddress := testEnv.contractAddr + + for i := 0; i < numOfEvents; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Populate fields for the event + destChainSelector := uint64(destChain) + // #nosec G115 + sequenceNumber := uint64(offset + i) + + // Create InternalRampMessageHeader struct + header := onramp.InternalRampMessageHeader{ + MessageId: utils.NewHash(), + SourceChainSelector: uint64(sourceChain), + DestChainSelector: destChainSelector, + SequenceNumber: sequenceNumber, + // #nosec G115 + Nonce: uint64(i), + } + + // Create InternalEVM2AnyTokenTransfer slice + tokenTransfers := []onramp.InternalEVM2AnyTokenTransfer{ + { + SourcePoolAddress: utils.RandomAddress(), + DestTokenAddress: []byte{0x01, 0x02}, + ExtraData: []byte{0x03}, + // #nosec G115 + Amount: big.NewInt(1000 + int64(i)), + DestExecData: []byte{}, + }, + } + + // Create InternalEVM2AnyRampMessage struct + message := onramp.InternalEVM2AnyRampMessage{ + Header: header, + Sender: utils.RandomAddress(), + Data: []byte{0x04, 0x05}, + Receiver: []byte{0x06, 0x07}, + ExtraArgs: []byte{0x08}, + FeeToken: utils.RandomAddress(), + // #nosec G115 + FeeTokenAmount: big.NewInt(2000 + int64(i)), + // #nosec G115 + + FeeValueJuels: big.NewInt(3000 + int64(i)), + TokenAmounts: tokenTransfers, + } + + // Encode the non-indexed event data + encodedData, err := messageSentEvent.Inputs.NonIndexed().Pack( + message, + ) + require.NoError(b, err) + + // Topics (event signature and indexed fields) + topics := [][]byte{ + messageSentEventSig[:], // Event signature + logpoller.EvmWord(destChainSelector).Bytes(), // Indexed destChainSelector + logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(sourceChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: time.Now(), + EventSig: messageSentEventSig, + Topics: topics, + Address: messageSentEventAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) +} + +func calculateExpectedRangeLen(logsInserted int, startSeq, endSeq cciptypes.SeqNum) int { + if logsInserted == 0 { + return 0 + } + start := uint64(startSeq) + end := uint64(endSeq) + // #nosec G115 + logs := uint64(logsInserted) + + if start >= logs { + return 0 + } + + if end >= logs { + end = logs - 1 + } + + // #nosec G115 + return int(end - start + 1) +} + +func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.TransactOpts) { privateKey, err := crypto.GenerateKey() require.NoError(t, err) @@ -933,7 +1318,7 @@ func testSetupRealContracts( func testSetup( ctx context.Context, - t *testing.T, + t testing.TB, params testSetupParams, ) *testSetupData { address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(params.Auth, params.SimulatedBackend.Client()) @@ -946,7 +1331,13 @@ func testSetup( lggr := logger.TestLogger(t) lggr.SetLogLevel(zapcore.ErrorLevel) - db := pgtest.NewSqlxDB(t) + // Parameterize database selection + var db *sqlx.DB + if params.UseHeavyDB { + _, db = heavyweight.FullTestDBV2(t, nil) // Heavyweight database for benchmarks + } else { + db = pgtest.NewSqlxDB(t) // Simple in-memory DB for tests + } lpOpts := logpoller.Opts{ PollPeriod: time.Millisecond, FinalityDepth: params.FinalityDepth, @@ -956,7 +1347,9 @@ func testSetup( } cl := client.NewSimulatedBackendClient(t, params.SimulatedBackend, big.NewInt(0).SetUint64(uint64(params.ReaderChain))) headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(params.ReaderChain)), db, lggr), + orm := logpoller.NewORM(big.NewInt(0).SetUint64(uint64(params.ReaderChain)), db, lggr) + lp := logpoller.NewLogPoller( + orm, cl, lggr, headTracker, @@ -977,8 +1370,6 @@ func testSetup( assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) } - contractNames := maps.Keys(params.Cfg.Contracts) - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, params.Cfg) require.NoError(t, err) @@ -988,7 +1379,7 @@ func testSetup( err = extendedCr.Bind(ctx, []types.BoundContract{ { Address: address.String(), - Name: contractNames[0], + Name: params.ContractNameToBind, }, }) require.NoError(t, err) @@ -1048,6 +1439,7 @@ func testSetup( contract: contract, sb: params.SimulatedBackend, auth: params.Auth, + orm: orm, lp: lp, cl: cl, reader: reader, @@ -1056,16 +1448,18 @@ func testSetup( } type testSetupParams struct { - ReaderChain cciptypes.ChainSelector - DestChain cciptypes.ChainSelector - OnChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum - Cfg evmtypes.ChainReaderConfig - ToBindContracts map[cciptypes.ChainSelector][]types.BoundContract - ToMockBindings map[cciptypes.ChainSelector][]types.BoundContract - BindTester bool - SimulatedBackend *simulated.Backend - Auth *bind.TransactOpts - FinalityDepth int64 + ReaderChain cciptypes.ChainSelector + DestChain cciptypes.ChainSelector + OnChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum + Cfg evmtypes.ChainReaderConfig + ToBindContracts map[cciptypes.ChainSelector][]types.BoundContract + ToMockBindings map[cciptypes.ChainSelector][]types.BoundContract + BindTester bool + ContractNameToBind string + SimulatedBackend *simulated.Backend + Auth *bind.TransactOpts + FinalityDepth int64 + UseHeavyDB bool } type testSetupData struct { @@ -1073,6 +1467,7 @@ type testSetupData struct { contract *ccip_reader_tester.CCIPReaderTester sb *simulated.Backend auth *bind.TransactOpts + orm logpoller.ORM lp logpoller.LogPoller cl client.Client reader ccipreaderpkg.CCIPReader From a0d9eb501ada5fb00e44badfaa58f4d56236dd27 Mon Sep 17 00:00:00 2001 From: dimitris Date: Thu, 5 Dec 2024 14:23:56 +0200 Subject: [PATCH 12/55] ccip - fix ocr3 keyring adapter, transmitter, evm keyring lib (#15500) * fix ocr3 keyring adapter * update transmitter * export func * fix onchain reportContext length * changeset onchain * fix liq man * use cw compatible types * fix RawReportContext3 * gen snap --------- Co-authored-by: Rens Rooimans --- contracts/.changeset/rude-badgers-tickle.md | 5 + contracts/gas-snapshots/ccip.gas-snapshot | 280 +++++++++--------- contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol | 5 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 4 +- .../ccip/test/helpers/MultiOCR3Helper.sol | 6 +- .../MultiOCR3Base.transmit.t.sol | 34 +-- .../MultiOCR3Base/MultiOCR3BaseSetup.t.sol | 2 +- .../test/offRamp/OffRamp/OffRamp.commit.t.sol | 7 +- .../offRamp/OffRamp/OffRamp.execute.t.sol | 10 +- .../test/offRamp/OffRamp/OffRampSetup.t.sol | 4 +- .../ccip/ocrimpls/contract_transmitter.go | 40 +-- core/capabilities/ccip/ocrimpls/keyring.go | 51 ++-- .../multi_ocr3_helper/multi_ocr3_helper.go | 20 +- .../ccip/generated/offramp/offramp.go | 20 +- ...rapper-dependency-versions-do-not-edit.txt | 4 +- .../keystore/keys/ocr2key/evm_keyring.go | 2 +- .../keystore/keys/ocr2key/evm_keyring_test.go | 64 ++++ 17 files changed, 307 insertions(+), 251 deletions(-) create mode 100644 contracts/.changeset/rude-badgers-tickle.md diff --git a/contracts/.changeset/rude-badgers-tickle.md b/contracts/.changeset/rude-badgers-tickle.md new file mode 100644 index 00000000000..4dddf8d430e --- /dev/null +++ b/contracts/.changeset/rude-badgers-tickle.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +reduce length of reportContext in OCR3 diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index ab4adc29a08..955000e016f 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -68,7 +68,7 @@ CCIPHome_setCandidate:test_setCandidate_success() (gas: 1365439) CCIPHome_supportsInterface:test_supportsInterface_success() (gas: 9885) DefensiveExampleTest:test_HappyPath_Success() (gas: 200540) DefensiveExampleTest:test_Recovery() (gas: 425013) -E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512389) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512127) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96980) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49812) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17479) @@ -333,30 +333,30 @@ MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112357) MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254293) MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861787) MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 476186) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42957) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48640) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 77185) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65925) -MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33494) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79889) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33686) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47188) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25711) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18722) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24299) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61298) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39952) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33026) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42765) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48348) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76893) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65621) +MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33387) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79597) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33589) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47082) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25583) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18615) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24193) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 60994) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39824) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32920) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37956) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23706) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38778) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71901) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 185776) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 189229) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 252250) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 220615) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 185810) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 189263) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 252318) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 220605) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 60497) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152941) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152975) NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 166167) NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 195938) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 139164) @@ -369,132 +369,132 @@ NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllow NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate_success() (gas: 66889) NonceManager_applyPreviousRampsUpdates:test_ZeroInput_success() (gas: 12213) NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9705) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5887669) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 626160) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 166527) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5872422) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 626094) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 166505) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 16719) -OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 274713) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 274389) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 168604) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 181059) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 181037) OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13441) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72724) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) -OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed_success() (gas: 285041) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177470) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 333296) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276562) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168408) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187974) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 156406) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545037) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10600) -OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92766) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63432) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 69993) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 66119) -OffRamp_commit:test_InvalidRootRevert() (gas: 65214) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6648811) -OffRamp_commit:test_NoConfig_Revert() (gas: 6232229) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113007) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121197) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112939) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355298) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164285) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141269) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 148268) -OffRamp_commit:test_RootWithRMNDisabled_success() (gas: 153986) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 61681) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232398) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125252) -OffRamp_commit:test_Unhealthy_Revert() (gas: 60482) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206844) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 53621) -OffRamp_constructor:test_Constructor_Success() (gas: 6194282) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136585) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103622) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101471) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 162065) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101388) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101392) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) -OffRamp_execute:test_LargeBatch_Success() (gas: 3376243) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 371146) -OffRamp_execute:test_MultipleReports_Success() (gas: 298685) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7056957) -OffRamp_execute:test_NoConfig_Revert() (gas: 6281427) -OffRamp_execute:test_NonArray_Revert() (gas: 27680) -OffRamp_execute:test_SingleReport_Success() (gas: 175664) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147820) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6948599) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 56135) -OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20463) -OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 237997) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 91972) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 268069) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28703) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 15574) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 474583) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48340) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34145) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28868) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187644) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197820) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40731) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 404990) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248718) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192362) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212388) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 243698) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141476) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 402512) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58286) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73856) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 574072) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 522623) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 26839) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 540743) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 540690) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 451736) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135241) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164902) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3888846) +OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed_success() (gas: 284695) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177591) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 333573) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276839) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168529) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188173) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 156527) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545255) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10643) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92450) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63117) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 69655) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 65803) +OffRamp_commit:test_InvalidRootRevert() (gas: 64898) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6633259) +OffRamp_commit:test_NoConfig_Revert() (gas: 6216677) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112728) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120561) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112660) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354785) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 163983) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 140923) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 147631) +OffRamp_commit:test_RootWithRMNDisabled_success() (gas: 153596) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 61365) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231709) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125027) +OffRamp_commit:test_Unhealthy_Revert() (gas: 60177) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206221) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 53305) +OffRamp_constructor:test_Constructor_Success() (gas: 6179080) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136555) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103592) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101441) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 162036) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101358) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101362) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17532) +OffRamp_execute:test_LargeBatch_Success() (gas: 3378447) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 371209) +OffRamp_execute:test_MultipleReports_Success() (gas: 298806) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7041684) +OffRamp_execute:test_NoConfig_Revert() (gas: 6266154) +OffRamp_execute:test_NonArray_Revert() (gas: 27572) +OffRamp_execute:test_SingleReport_Success() (gas: 175631) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147790) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6933352) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17248) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 56213) +OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20508) +OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 238042) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 91994) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 268135) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28659) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 15530) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 474650) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48296) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34101) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28824) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187677) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197809) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40687) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 405023) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248786) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192430) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212456) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 243699) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141510) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 402534) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58242) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73812) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 574160) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 522711) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 26795) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 540787) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 540734) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 451824) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135231) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164892) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3905742) OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 121048) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89561) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81514) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74194) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172517) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 213009) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27203) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165665) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27740) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55317) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 489426) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 314585) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2224632) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165207) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 225918) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226458) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 773856) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344327) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37676) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 101487) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36812) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91452) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 83540) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 168762) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenInvalidDataLengthReturnData() (gas: 62844) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenPoolDoesNotSupportDest() (gas: 78448) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 170632) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 181871) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11509) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14019) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 47579) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 25552) -OffRamp_trialExecute:test_trialExecute() (gas: 271705) -OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 127412) -OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 138722) -OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 289256) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89737) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81694) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74284) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172639) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 213251) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27248) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165935) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27774) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55362) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 489669) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 314861) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2224794) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165330) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 226161) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226701) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 774719) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344726) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37632) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 101465) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36790) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91430) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 83518) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 168784) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenInvalidDataLengthReturnData() (gas: 62822) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenPoolDoesNotSupportDest() (gas: 78426) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 170654) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 181893) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11465) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13975) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 47491) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 25464) +OffRamp_trialExecute:test_trialExecute() (gas: 271771) +OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 127457) +OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 138767) +OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 289412) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 251706) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17227) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Revert() (gas: 67101) diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index 5d8cc7f69d1..b6741f78fbe 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -101,7 +101,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { /// @notice Constant length component for transmit functions with no signatures. /// The signatures are expected to match transmitPlugin(reportContext, report). uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES = 4 // function selector. - + 3 * 32 // 3 words containing reportContext. + + 2 * 32 // 2 words containing reportContext. + 32 // word containing start location of abiencoded report value. + 32; // word containing length of report. @@ -230,7 +230,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { uint8 ocrPluginType, // NOTE: If these parameters are changed, expectedMsgDataLength and/or TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT // need to be changed accordingly. - bytes32[3] calldata reportContext, + bytes32[2] calldata reportContext, bytes calldata report, bytes32[] memory rs, bytes32[] memory ss, @@ -239,7 +239,6 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { // reportContext consists of: // reportContext[0]: ConfigDigest. // reportContext[1]: 24 byte padding, 8 byte sequence number. - // reportContext[2]: ExtraHash. ConfigInfo memory configInfo = s_ocrConfigs[ocrPluginType].configInfo; bytes32 configDigest = reportContext[0]; diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 4937373d653..d276ce26a96 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -322,7 +322,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Transmit function for execution reports. The function takes no signatures, and expects the exec plugin /// type to be configured with no signatures. /// @param report serialized execution report. - function execute(bytes32[3] calldata reportContext, bytes calldata report) external { + function execute(bytes32[2] calldata reportContext, bytes calldata report) external { _batchExecute(abi.decode(report, (Internal.ExecutionReport[])), new GasLimitOverride[][](0)); bytes32[] memory emptySigs = new bytes32[](0); @@ -773,7 +773,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// price updates is submitted, we are OK to revert to preserve the invariant that we always revert on invalid /// sequence number ranges. If that happens, prices will be updated in later rounds. function commit( - bytes32[3] calldata reportContext, + bytes32[2] calldata reportContext, bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol index e760b79935d..68347d153fa 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol @@ -7,7 +7,7 @@ contract MultiOCR3Helper is MultiOCR3Base { event AfterConfigSet(uint8 ocrPluginType); /// @dev OCR plugin type used for transmit. - /// Defined in storage since it cannot be passed as calldata due to strict transmit checks + /// Defined in storage since it cannot be passed as calldata due to strict transmit checks uint8 internal s_transmitOcrPluginType; function setTransmitOcrPluginType( @@ -18,7 +18,7 @@ contract MultiOCR3Helper is MultiOCR3Base { /// @dev transmit function with signatures function transmitWithSignatures( - bytes32[3] calldata reportContext, + bytes32[2] calldata reportContext, bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, @@ -28,7 +28,7 @@ contract MultiOCR3Helper is MultiOCR3Base { } /// @dev transmit function with no signatures - function transmitWithoutSignatures(bytes32[3] calldata reportContext, bytes calldata report) external { + function transmitWithoutSignatures(bytes32[2] calldata reportContext, bytes calldata report) external { bytes32[] memory emptySigs = new bytes32[](0); _transmit(s_transmitOcrPluginType, reportContext, report, emptySigs, emptySigs, bytes32("")); } diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol index c6d948a70c2..2855b47eeea 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol @@ -47,7 +47,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_TransmitSigners_gas_Success() public { vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // F = 2, need 2 signatures (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -65,7 +65,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_TransmitWithoutSignatureVerification_gas_Success() public { vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest3, s_configDigest3, s_configDigest3]; + bytes32[2] memory reportContext = [s_configDigest3, s_configDigest3]; s_multiOCR3.setTransmitOcrPluginType(2); @@ -115,7 +115,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // Randomise picked transmitter with random offset vm.startPrank(transmitters[randomAddressOffset % signersLength]); - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // condition: matches signature expectation for transmit uint8 numSignatures = F + 1; @@ -138,7 +138,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // Reverts function test_ForkedChain_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -155,7 +155,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_ZeroSignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -165,7 +165,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_TooManySignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // 1 signature too many (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -179,7 +179,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_InsufficientSignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; // Missing 1 signature for unique report (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -194,7 +194,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_ConfigDigestMismatch_Revert() public { bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + bytes32[2] memory reportContext = [configDigest, configDigest]; (,,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -205,7 +205,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_SignatureOutOfRegistration_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](1); @@ -218,7 +218,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_UnAuthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); @@ -229,7 +229,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_NonUniqueSignature_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -247,7 +247,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_UnauthorizedSigner_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -264,7 +264,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { function test_UnconfiguredPlugin_Revert() public { bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + bytes32[2] memory reportContext = [configDigest, configDigest]; s_multiOCR3.setTransmitOcrPluginType(42); @@ -273,7 +273,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_TransmitWithLessCalldataArgs_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -281,7 +281,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { vm.startPrank(s_validTransmitters[1]); // report length + function selector + report length + abiencoded location of report value + report context words - uint256 receivedLength = REPORT.length + 4 + 5 * 32; + uint256 receivedLength = REPORT.length + 4 + 4 * 32; vm.expectRevert( abi.encodeWithSelector( MultiOCR3Base.WrongMessageLength.selector, @@ -294,7 +294,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } function test_TransmitWithExtraCalldataArgs_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); @@ -305,7 +305,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // dynamic length + function selector + report length + abiencoded location of report value + report context words // rawVs value, lengths of rs, ss, and start locations of rs & ss -> 5 words - uint256 receivedLength = REPORT.length + 4 + (5 * 32) + (5 * 32) + (2 * 32) + (2 * 32); + uint256 receivedLength = REPORT.length + 4 + (4 * 32) + (5 * 32) + (2 * 32) + (2 * 32); vm.expectRevert( abi.encodeWithSelector( MultiOCR3Base.WrongMessageLength.selector, diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol index f949017d588..8418aa54cf1 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol @@ -95,7 +95,7 @@ contract MultiOCR3BaseSetup is BaseTest { function _getSignaturesForDigest( uint256[] memory signerPrivateKeys, bytes memory report, - bytes32[3] memory reportContext, + bytes32[2] memory reportContext, uint8 signatureCount ) internal pure returns (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) { rs = new bytes32[](signatureCount); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol index a942b98cc1e..7cfb9cd36b7 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol @@ -285,8 +285,7 @@ contract OffRamp_commit is OffRampSetup { function test_UnauthorizedTransmitter_Revert() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = - [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber)), s_configDigestCommit]; + bytes32[2] memory reportContext = [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber))]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -300,7 +299,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -325,7 +324,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol index 9fd2499ef28..f12ca7b4609 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol @@ -198,7 +198,7 @@ contract OffRamp_execute is OffRampSetup { // Reverts function test_UnauthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -216,7 +216,7 @@ contract OffRamp_execute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestExec]; vm.startPrank(s_validTransmitters[0]); vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); @@ -242,7 +242,7 @@ contract OffRamp_execute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [bytes32(""), s_configDigestExec]; vm.startPrank(s_validTransmitters[0]); vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); @@ -277,7 +277,7 @@ contract OffRamp_execute is OffRampSetup { } function test_IncorrectArrayType_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; uint256[] memory wrongData = new uint256[](2); wrongData[0] = 1; @@ -288,7 +288,7 @@ contract OffRamp_execute is OffRampSetup { } function test_NonArray_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol index 5cf007641cd..858ee9e4a45 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol @@ -371,7 +371,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { } function _commit(OffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { - bytes32[3] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber)), s_configDigestCommit]; + bytes32[2] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber))]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -383,7 +383,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { function _execute( Internal.ExecutionReport[] memory reports ) internal { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; vm.startPrank(s_validTransmitters[0]); s_offRamp.execute(reportContext, abi.encode(reports)); diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 7bb64d99eb6..e89acac7baa 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -13,18 +13,23 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) -type ToCalldataFunc func(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any +type ToCalldataFunc func(rawReportCtx [2][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any -func ToCommitCalldata(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any { +func ToCommitCalldata(rawReportCtx [2][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag // for that field. + + // WARNING: Be careful if you change the data types. + // Using a different type e.g. `type Foo [32]byte` instead of `[32]byte` + // will trigger undefined chainWriter behavior, e.g. transactions submitted with wrong arguments. return struct { - ReportContext [3][32]byte + ReportContext [2][32]byte Report []byte Rs [][32]byte Ss [][32]byte @@ -38,14 +43,18 @@ func ToCommitCalldata(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte } } -func ToExecCalldata(rawReportCtx [3][32]byte, report []byte, _, _ [][32]byte, _ [32]byte) any { +func ToExecCalldata(rawReportCtx [2][32]byte, report []byte, _, _ [][32]byte, _ [32]byte) any { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag // for that field. + + // WARNING: Be careful if you change the data types. + // Using a different type e.g. `type Foo [32]byte` instead of `[32]byte` + // will trigger undefined chainWriter behavior, e.g. transactions submitted with wrong arguments. return struct { - ReportContext [3][32]byte + ReportContext [2][32]byte Report []byte }{ ReportContext: rawReportCtx, @@ -144,22 +153,7 @@ func (c *commitTransmitter[RI]) Transmit( // report ctx for OCR3 consists of the following // reportContext[0]: ConfigDigest // reportContext[1]: 24 byte padding, 8 byte sequence number - // reportContext[2]: unused - // convert seqNum, which is a uint64, into a uint32 epoch and uint8 round - // while this does truncate the sequence number, it is not a problem because - // it still gives us 2^40 - 1 possible sequence numbers. - // assuming a sequence number is generated every second, this gives us - // 1099511627775 seconds, or approximately 34,865 years, before we run out - // of sequence numbers. - epoch, round := uint64ToUint32AndUint8(seqNr) - rawReportCtx := evmutil.RawReportContext(ocrtypes.ReportContext{ - ReportTimestamp: ocrtypes.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - // ExtraData not used in OCR3 - }) + rawReportCtx := ocr2key.RawReportContext3(configDigest, seqNr) if c.toCalldataFn == nil { return errors.New("toCalldataFn is nil") @@ -182,7 +176,3 @@ func (c *commitTransmitter[RI]) Transmit( return nil } - -func uint64ToUint32AndUint8(x uint64) (uint32, uint8) { - return uint32(x >> 32), uint8(x) -} diff --git a/core/capabilities/ccip/ocrimpls/keyring.go b/core/capabilities/ccip/ocrimpls/keyring.go index 4b15c75b09a..cd753810341 100644 --- a/core/capabilities/ccip/ocrimpls/keyring.go +++ b/core/capabilities/ccip/ocrimpls/keyring.go @@ -6,16 +6,26 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) +// OCR3SignerVerifierExtra is an extension of OCR3SignerVerifier that +// also exposes the public key and max signature length which are required by the ocr3Keyring adapter. +type OCR3SignerVerifierExtra interface { + ocr2key.OCR3SignerVerifier + PublicKey() types.OnchainPublicKey + MaxSignatureLength() int +} + var _ ocr3types.OnchainKeyring[[]byte] = &ocr3Keyring[[]byte]{} +// ocr3Keyring is an adapter that exposes ocr3 onchain keyring. type ocr3Keyring[RI any] struct { - core types.OnchainKeyring + core OCR3SignerVerifierExtra lggr logger.Logger } -func NewOnchainKeyring[RI any](keyring types.OnchainKeyring, lggr logger.Logger) *ocr3Keyring[RI] { +func NewOnchainKeyring[RI any](keyring OCR3SignerVerifierExtra, lggr logger.Logger) *ocr3Keyring[RI] { return &ocr3Keyring[RI]{ core: keyring, lggr: lggr.Named("OCR3Keyring"), @@ -31,31 +41,20 @@ func (w *ocr3Keyring[RI]) MaxSignatureLength() int { } func (w *ocr3Keyring[RI]) Sign(configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI]) (signature []byte, err error) { - epoch, round := uint64ToUint32AndUint8(seqNr) - rCtx := types.ReportContext{ - ReportTimestamp: types.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - } - - w.lggr.Debugw("signing report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) - - return w.core.Sign(rCtx, r.Report) + w.lggr.Debugw( + "signing report", + "configDigest", configDigest.Hex(), + "seqNr", seqNr, + "report", hexutil.Encode(r.Report), + ) + return w.core.Sign3(configDigest, seqNr, r.Report) } func (w *ocr3Keyring[RI]) Verify(key types.OnchainPublicKey, configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI], signature []byte) bool { - epoch, round := uint64ToUint32AndUint8(seqNr) - rCtx := types.ReportContext{ - ReportTimestamp: types.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - } - - w.lggr.Debugw("verifying report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) - - return w.core.Verify(key, rCtx, r.Report, signature) + w.lggr.Debugw("verifying report", + "configDigest", configDigest.Hex(), + "seqNr", seqNr, + "report", hexutil.Encode(r.Report), + ) + return w.core.Verify3(key, configDigest, seqNr, r.Report, signature) } diff --git a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go index 0fc23b619f7..3d43d16d520 100644 --- a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go +++ b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go @@ -58,8 +58,8 @@ type MultiOCR3BaseOracle struct { } var MultiOCR3HelperMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615610062576100628161006d565b5050466080526100e6565b336001600160a01b0382160361009657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d256200010960003960008181610edd0152610f290152611d256000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020820152905161010291906114ca565b60405180910390f35b61011e610119366004611591565b61020b565b005b61013361012e36600461161f565b61023a565b6040516101029190611681565b61011e61014e3660046116f4565b6102ca565b61011e61034d565b61011e6101693660046117a7565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d33660046117a7565b61041b565b604051610102919061181b565b61011e6101f33660046118ae565b610593565b61011e610206366004611a1a565b6105a7565b604080516000808252602082019092526004549091506102349060ff16858585858060006105e9565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611652565b60028111156102be576102be611652565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a92506105e9915050565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61045e6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561051457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116104e9575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561058357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610558575b5050505050815250509050919050565b61059b610972565b6105a4816109c5565b50565b6105af610972565b60005b81518110156105e5576105dd8282815181106105d0576105d0611b83565b6020026020010151610a89565b6001016105b2565b5050565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906106488760a4611be1565b9050826060015115610690578451610661906020611bf4565b865161066e906020611bf4565b6106799060a0611be1565b6106839190611be1565b61068d9082611be1565b90505b3681146106d7576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044015b60405180910390fd5b508151811461071f5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106ce565b610727610eda565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561077557610775611652565b600281111561078657610786611652565b90525090506002816020015160028111156107a3576107a3611652565b1480156108045750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106107df576107df611b83565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61083a576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561091c576020820151610855906001611c0b565b60ff16855114610891576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108cc576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087876040516108de929190611c24565b6040519081900381206108f5918b90602001611c34565b60405160208183030381529060405280519060200120905061091a8a82888888610f5b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109c3576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b3373ffffffffffffffffffffffffffffffffffffffff821603610a14576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610acd5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610b3a57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610b8f565b6060840151600182015460ff6201000090910416151590151514610b8f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106ce565b60a084015180516101001015610bd45760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b8051600003610c125760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b610c858484600301805480602002602001604051908101604052809291908181526020018280548015610c7b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c50575b505050505061116b565b846060015115610e2a57610d008484600201805480602002602001604051908101604052809291908181526020018280548015610c7b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c5057505050505061116b565b608085015180516101001015610d455760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b6040860151610d55906003611c62565b60ff16815111610d945760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b815181511015610dd35760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e1b906002860190602084019061142b565b50610e2885826001611203565b505b610e3684826002611203565b8051610e4b906003850190602084019061142b565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ec29389939260028a01929190611c85565b60405180910390a1610ed3846113f2565b5050505050565b467f0000000000000000000000000000000000000000000000000000000000000000146109c3576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106ce565b8251600090815b81811015610343576000600188868460208110610f8157610f81611b83565b610f8e91901a601b611c0b565b898581518110610fa057610fa0611b83565b6020026020010151898681518110610fba57610fba611b83565b602002602001015160405160008152602001604052604051610ff8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561101a573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110a6576110a6611652565b60028111156110b7576110b7611652565b90525090506001816020015160028111156110d4576110d4611652565b1461110b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b85161561114e576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f62565b60005b81518110156111fe5760ff8316600090815260036020526040812083519091908490849081106111a0576111a0611b83565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161116e565b505050565b60005b825181101561023457600083828151811061122357611223611b83565b602002602001015190506000600281111561124057611240611652565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561128c5761128c611652565b146112c65760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b73ffffffffffffffffffffffffffffffffffffffff8116611313576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561133957611339611652565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113de576113de611652565b021790555090505050806001019050611206565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114a5579160200282015b828111156114a557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061144b565b506114b19291506114b5565b5090565b5b808211156114b157600081556001016114b6565b60006020808352835180602085015260005b818110156114f8578581018301518582016040015282016114dc565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f84011261155a57600080fd5b50813567ffffffffffffffff81111561157257600080fd5b60208301915083602082850101111561158a57600080fd5b9250929050565b6000806000608084860312156115a657600080fd5b6115b08585611537565b9250606084013567ffffffffffffffff8111156115cc57600080fd5b6115d886828701611548565b9497909650939450505050565b803560ff811681146115f657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146115f657600080fd5b6000806040838503121561163257600080fd5b61163b836115e5565b9150611649602084016115fb565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116a2576116a2611652565b8060208401525092915050565b60008083601f8401126116c157600080fd5b50813567ffffffffffffffff8111156116d957600080fd5b6020830191508360208260051b850101111561158a57600080fd5b60008060008060008060008060e0898b03121561171057600080fd5b61171a8a8a611537565b9750606089013567ffffffffffffffff8082111561173757600080fd5b6117438c838d01611548565b909950975060808b013591508082111561175c57600080fd5b6117688c838d016116af565b909750955060a08b013591508082111561178157600080fd5b5061178e8b828c016116af565b999c989b50969995989497949560c00135949350505050565b6000602082840312156117b957600080fd5b6117c2826115e5565b9392505050565b60008151808452602080850194506020840160005b8381101561181057815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117de565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261186a60e08401826117c9565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118a582826117c9565b95945050505050565b6000602082840312156118c057600080fd5b6117c2826115fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561191b5761191b6118c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611968576119686118c9565b604052919050565b600067ffffffffffffffff82111561198a5761198a6118c9565b5060051b60200190565b803580151581146115f657600080fd5b600082601f8301126119b557600080fd5b813560206119ca6119c583611970565b611921565b8083825260208201915060208460051b8701019350868411156119ec57600080fd5b602086015b84811015611a0f57611a02816115fb565b83529183019183016119f1565b509695505050505050565b60006020808385031215611a2d57600080fd5b823567ffffffffffffffff80821115611a4557600080fd5b818501915085601f830112611a5957600080fd5b8135611a676119c582611970565b81815260059190911b83018401908481019088831115611a8657600080fd5b8585015b83811015611b7657803585811115611aa157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ad65760008081fd5b611ade6118f8565b8882013581526040611af18184016115e5565b8a8301526060611b028185016115e5565b8284015260809150611b15828501611994565b9083015260a08381013589811115611b2d5760008081fd5b611b3b8f8d838801016119a4565b838501525060c0840135915088821115611b555760008081fd5b611b638e8c848701016119a4565b9083015250845250918601918601611a8a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bb2565b80820281158282048414176102c4576102c4611bb2565b60ff81811683821601908111156102c4576102c4611bb2565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160068310611c5c57611c5c611652565b91905290565b60ff8181168382160290811690818114611c7e57611c7e611bb2565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cec57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cba565b50508481036060860152611d0081886117c9565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x60a060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615610062576100628161006d565b5050466080526100e6565b336001600160a01b0382160361009657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d256200010960003960008181610edd0152610f290152611d256000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e146101205780633ecdb95b1461014057806379ba50971461015357600080fd5b806310061068146100c3578063181f5a77146100d8575b600080fd5b6100d66100d1366004611524565b61020b565b005b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e3000000000000000602082015290516101179190611578565b60405180910390f35b61013361012e36600461161f565b61023a565b6040516101179190611681565b6100d661014e3660046116f4565b6102ca565b6100d661034d565b6100d66101693660046117a7565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b6101d86101d33660046117a7565b61041b565b604051610117919061181b565b6100d66101f33660046118ae565b610593565b6100d6610206366004611a1a565b6105a7565b604080516000808252602082019092526004549091506102349060ff16858585858060006105e9565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611652565b60028111156102be576102be611652565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a92506105e9915050565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61045e6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561051457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116104e9575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561058357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610558575b5050505050815250509050919050565b61059b610972565b6105a4816109c5565b50565b6105af610972565b60005b81518110156105e5576105dd8282815181106105d0576105d0611b83565b6020026020010151610a89565b6001016105b2565b5050565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590610648876084611be1565b9050826060015115610690578451610661906020611bf4565b865161066e906020611bf4565b6106799060a0611be1565b6106839190611be1565b61068d9082611be1565b90505b3681146106d7576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044015b60405180910390fd5b508151811461071f5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106ce565b610727610eda565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561077557610775611652565b600281111561078657610786611652565b90525090506002816020015160028111156107a3576107a3611652565b1480156108045750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106107df576107df611b83565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61083a576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561091c576020820151610855906001611c0b565b60ff16855114610891576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108cc576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087876040516108de929190611c24565b6040519081900381206108f5918b90602001611c34565b60405160208183030381529060405280519060200120905061091a8a82888888610f5b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109c3576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b3373ffffffffffffffffffffffffffffffffffffffff821603610a14576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610acd5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610b3a57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610b8f565b6060840151600182015460ff6201000090910416151590151514610b8f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106ce565b60a084015180516101001015610bd45760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b8051600003610c125760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b610c858484600301805480602002602001604051908101604052809291908181526020018280548015610c7b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c50575b505050505061116b565b846060015115610e2a57610d008484600201805480602002602001604051908101604052809291908181526020018280548015610c7b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c5057505050505061116b565b608085015180516101001015610d455760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b6040860151610d55906003611c62565b60ff16815111610d945760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b815181511015610dd35760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e1b906002860190602084019061142b565b50610e2885826001611203565b505b610e3684826002611203565b8051610e4b906003850190602084019061142b565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ec29389939260028a01929190611c85565b60405180910390a1610ed3846113f2565b5050505050565b467f0000000000000000000000000000000000000000000000000000000000000000146109c3576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106ce565b8251600090815b81811015610343576000600188868460208110610f8157610f81611b83565b610f8e91901a601b611c0b565b898581518110610fa057610fa0611b83565b6020026020010151898681518110610fba57610fba611b83565b602002602001015160405160008152602001604052604051610ff8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561101a573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110a6576110a6611652565b60028111156110b7576110b7611652565b90525090506001816020015160028111156110d4576110d4611652565b1461110b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b85161561114e576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f62565b60005b81518110156111fe5760ff8316600090815260036020526040812083519091908490849081106111a0576111a0611b83565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161116e565b505050565b60005b825181101561023457600083828151811061122357611223611b83565b602002602001015190506000600281111561124057611240611652565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561128c5761128c611652565b146112c65760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b73ffffffffffffffffffffffffffffffffffffffff8116611313576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561133957611339611652565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113de576113de611652565b021790555090505050806001019050611206565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114a5579160200282015b828111156114a557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061144b565b506114b19291506114b5565b5090565b5b808211156114b157600081556001016114b6565b80604081018310156102c457600080fd5b60008083601f8401126114ed57600080fd5b50813567ffffffffffffffff81111561150557600080fd5b60208301915083602082850101111561151d57600080fd5b9250929050565b60008060006060848603121561153957600080fd5b61154385856114ca565b9250604084013567ffffffffffffffff81111561155f57600080fd5b61156b868287016114db565b9497909650939450505050565b60006020808352835180602085015260005b818110156115a65785810183015185820160400152820161158a565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803560ff811681146115f657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146115f657600080fd5b6000806040838503121561163257600080fd5b61163b836115e5565b9150611649602084016115fb565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116a2576116a2611652565b8060208401525092915050565b60008083601f8401126116c157600080fd5b50813567ffffffffffffffff8111156116d957600080fd5b6020830191508360208260051b850101111561151d57600080fd5b60008060008060008060008060c0898b03121561171057600080fd5b61171a8a8a6114ca565b9750604089013567ffffffffffffffff8082111561173757600080fd5b6117438c838d016114db565b909950975060608b013591508082111561175c57600080fd5b6117688c838d016116af565b909750955060808b013591508082111561178157600080fd5b5061178e8b828c016116af565b999c989b50969995989497949560a00135949350505050565b6000602082840312156117b957600080fd5b6117c2826115e5565b9392505050565b60008151808452602080850194506020840160005b8381101561181057815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117de565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261186a60e08401826117c9565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118a582826117c9565b95945050505050565b6000602082840312156118c057600080fd5b6117c2826115fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561191b5761191b6118c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611968576119686118c9565b604052919050565b600067ffffffffffffffff82111561198a5761198a6118c9565b5060051b60200190565b803580151581146115f657600080fd5b600082601f8301126119b557600080fd5b813560206119ca6119c583611970565b611921565b8083825260208201915060208460051b8701019350868411156119ec57600080fd5b602086015b84811015611a0f57611a02816115fb565b83529183019183016119f1565b509695505050505050565b60006020808385031215611a2d57600080fd5b823567ffffffffffffffff80821115611a4557600080fd5b818501915085601f830112611a5957600080fd5b8135611a676119c582611970565b81815260059190911b83018401908481019088831115611a8657600080fd5b8585015b83811015611b7657803585811115611aa157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ad65760008081fd5b611ade6118f8565b8882013581526040611af18184016115e5565b8a8301526060611b028185016115e5565b8284015260809150611b15828501611994565b9083015260a08381013589811115611b2d5760008081fd5b611b3b8f8d838801016119a4565b838501525060c0840135915088821115611b555760008081fd5b611b638e8c848701016119a4565b9083015250845250918601918601611a8a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bb2565b80820281158282048414176102c4576102c4611bb2565b60ff81811683821601908111156102c4576102c4611bb2565b8183823760009101908152919050565b828152604082602083013760600192915050565b6020810160068310611c5c57611c5c611652565b91905290565b60ff8181168382160290811690818114611c7e57611c7e611bb2565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cec57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cba565b50508481036060860152611d0081886117c9565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", } var MultiOCR3HelperABI = MultiOCR3HelperMetaData.ABI @@ -334,27 +334,27 @@ func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransferOwnership(to c return _MultiOCR3Helper.Contract.TransferOwnership(&_MultiOCR3Helper.TransactOpts, to) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.contract.Transact(opts, "transmitWithSignatures", reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithSignatures(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithSignatures(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithSignatures(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithSignatures(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.contract.Transact(opts, "transmitWithoutSignatures", reportContext, report) } -func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithoutSignatures(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithoutSignatures(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithoutSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithoutSignatures(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithoutSignatures(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithoutSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report) } @@ -1056,9 +1056,9 @@ type MultiOCR3HelperInterface interface { TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - TransmitWithSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + TransmitWithSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) + TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) FilterAfterConfigSet(opts *bind.FilterOpts) (*MultiOCR3HelperAfterConfigSetIterator, error) diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 8f90b5de6df..b582b60cff6 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -155,8 +155,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyBatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllSourceChainConfigs\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006bed38038062006bed833981016040819052620000359162000880565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001c4565b50504660805260208301516001600160a01b03161580620000b6575060408301516001600160a01b0316155b80620000cd575060608301516001600160a01b0316155b15620000ec576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b0316600003620001185760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001b0826200023e565b620001bb816200032c565b50505062000c72565b336001600160a01b03821603620001ee57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b031662000267576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889166001600160c01b03199097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b60005b8151811015620005c1576000828281518110620003505762000350620009aa565b60200260200101519050600081602001519050806001600160401b03166000036200038e5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526008602052604090206060830151600182018054620003e590620009c0565b905060000362000448578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004b9565b8154600160a81b90046001600160401b03166001148015906200048b57508051602082012060405162000480906001850190620009fc565b604051809103902014155b15620004b957604051632105803760e11b81526001600160401b038416600482015260240160405180910390fd5b80511580620004ef5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200050e576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200051e828262000acf565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b0319909116171782556200056d60066001600160401b038516620005c5565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b83604051620005a9919062000b9b565b60405180910390a2505050508060010190506200032f565b5050565b6000620005d38383620005dc565b90505b92915050565b60008181526001830160205260408120546200062557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005d6565b506000620005d6565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200066957620006696200062e565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200069a576200069a6200062e565b604052919050565b80516001600160401b0381168114620006ba57600080fd5b919050565b6001600160a01b0381168114620006d557600080fd5b50565b80518015158114620006ba57600080fd5b6000601f83601f840112620006fd57600080fd5b825160206001600160401b03808311156200071c576200071c6200062e565b8260051b6200072d8382016200066f565b93845286810183019383810190898611156200074857600080fd5b84890192505b858310156200087357825184811115620007685760008081fd5b89016080601f19828d038101821315620007825760008081fd5b6200078c62000644565b888401516200079b81620006bf565b81526040620007ac858201620006a2565b8a8301526060620007bf818701620006d8565b83830152938501519389851115620007d75760008081fd5b84860195508f603f870112620007ef57600094508485fd5b8a8601519450898511156200080857620008086200062e565b620008198b858f880116016200066f565b93508484528f82868801011115620008315760008081fd5b60005b8581101562000851578681018301518582018d01528b0162000834565b5060009484018b0194909452509182015283525091840191908401906200074e565b9998505050505050505050565b60008060008385036101208112156200089857600080fd5b6080811215620008a757600080fd5b620008b162000644565b620008bc86620006a2565b81526020860151620008ce81620006bf565b60208201526040860151620008e381620006bf565b60408201526060860151620008f881620006bf565b606082015293506080607f19820112156200091257600080fd5b506200091d62000644565b60808501516200092d81620006bf565b815260a085015163ffffffff811681146200094757600080fd5b60208201526200095a60c08601620006d8565b604082015260e08501516200096f81620006bf565b60608201526101008501519092506001600160401b038111156200099257600080fd5b620009a086828701620006e9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009d557607f821691505b602082108103620009f657634e487b7160e01b600052602260045260246000fd5b50919050565b600080835462000a0c81620009c0565b6001828116801562000a27576001811462000a3d5762000a6e565b60ff198416875282151583028701945062000a6e565b8760005260208060002060005b8581101562000a655781548a82015290840190820162000a4a565b50505082870194505b50929695505050505050565b601f82111562000aca576000816000526020600020601f850160051c8101602086101562000aa55750805b601f850160051c820191505b8181101562000ac65782815560010162000ab1565b5050505b505050565b81516001600160401b0381111562000aeb5762000aeb6200062e565b62000b038162000afc8454620009c0565b8462000a7a565b602080601f83116001811462000b3b576000841562000b225750858301515b600019600386901b1c1916600185901b17855562000ac6565b600085815260208120601f198616915b8281101562000b6c5788860151825594840194600190910190840162000b4b565b508582101562000b8b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000bf081620009c0565b8060a089015260c0600183166000811462000c14576001811462000c315762000c63565b60ff19841660c08b015260c083151560051b8b0101945062000c63565b85600052602060002060005b8481101562000c5a5781548c820185015290880190890162000c3d565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615efe62000cef600039600081816102070152612be30152600081816101d80152612eab0152600081816101a9015281816105820152818161073201526125e301526000818161017a0152818161278e0152612845015260008181611d120152611d450152615efe6000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637437ff9f116100ad578063c673e58411610071578063c673e58414610474578063ccd37ba314610494578063e9d68a8e146104d8578063f2fde38b146104f8578063f716f99f1461050b57600080fd5b80637437ff9f1461037357806379ba5097146104305780637edf52f41461043857806385572ffb1461044b5780638da5cb5b1461045957600080fd5b80633f4b04aa116100f45780633f4b04aa146102fc5780635215505b146103175780635e36480c1461032d5780635e7bb0081461034d57806360987c201461036057600080fd5b806304666f9c1461013157806306285c6914610146578063181f5a771461028d5780632d04ab76146102d6578063311cd513146102e9575b600080fd5b61014461013f366004613e22565b61051e565b005b61023760408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b604051610284919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102c96040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102849190613f90565b6101446102e4366004614040565b610532565b6101446102f73660046140f2565b610a46565b600b546040516001600160401b039091168152602001610284565b61031f610aaf565b60405161028492919061418c565b61034061033b36600461422d565b610d0a565b604051610284919061428a565b61014461035b3660046147f3565b610d5f565b61014461036e366004614a37565b610fee565b6103e960408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526004546001600160a01b038082168352600160a01b820463ffffffff166020840152600160c01b90910460ff16151592820192909252600554909116606082015290565b604051610284919081516001600160a01b03908116825260208084015163ffffffff1690830152604080840151151590830152606092830151169181019190915260800190565b6101446112a5565b610144610446366004614acb565b611328565b61014461012c366004614b30565b6001546040516001600160a01b039091168152602001610284565b610487610482366004614b7b565b611339565b6040516102849190614bdb565b6104ca6104a2366004614c50565b6001600160401b03919091166000908152600a60209081526040808320938352929052205490565b604051908152602001610284565b6104eb6104e6366004614c7a565b611497565b6040516102849190614c95565b610144610506366004614ca8565b6115a3565b610144610519366004614d2d565b6115b4565b6105266115f6565b61052f81611623565b50565b600061054087890189615082565b6004805491925090600160c01b900460ff166105ea57602082015151156105ea5760208201516040808401519051633854844f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926370a9089e926105b992309291906004016152aa565b60006040518083038186803b1580156105d157600080fd5b505afa1580156105e5573d6000803e3d6000fd5b505050505b8151515115158061060057508151602001515115155b156106cb57600b5460208b0135906001600160401b03808316911610156106a357600b805467ffffffffffffffff19166001600160401b03831617905581548351604051633937306f60e01b81526001600160a01b0390921691633937306f9161066c916004016153df565b600060405180830381600087803b15801561068657600080fd5b505af115801561069a573d6000803e3d6000fd5b505050506106c9565b8260200151516000036106c957604051632261116760e01b815260040160405180910390fd5b505b60005b826020015151811015610986576000836020015182815181106106f3576106f361530d565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079d91906153f2565b156107cb57604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107d6826118ac565b9050806001016040516107e99190615449565b6040518091039020836020015180519060200120146108265782602001518160010160405163b80d8fa960e01b81526004016107c292919061553c565b60408301518154600160a81b90046001600160401b039081169116141580610867575082606001516001600160401b031683604001516001600160401b0316115b156108ac57825160408085015160608601519151636af0786b60e11b81526001600160401b0393841660048201529083166024820152911660448201526064016107c2565b6080830151806108cf5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600a60209081526040808320848452909152902054156109275783516040516332cf0cbf60e01b81526001600160401b039091166004820152602481018290526044016107c2565b6060840151610937906001615577565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600a6020908152604080832094835293905291909120429055506001016106ce565b50602082015182516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926109be92909161559e565b60405180910390a1610a3a60008b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c92506118f8915050565b50505050505050505050565b610a86610a55828401846155c3565b6040805160008082526020820190925290610a80565b6060815260200190600190039081610a6b5790505b50611bf1565b604080516000808252602082019092529050610aa96001858585858660006118f8565b50505050565b6060806000610abe6006611cb4565b6001600160401b03811115610ad557610ad5613c42565b604051908082528060200260200182016040528015610b2657816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610af35790505b5090506000610b356006611cb4565b6001600160401b03811115610b4c57610b4c613c42565b604051908082528060200260200182016040528015610b75578160200160208202803683370190505b50905060005b610b856006611cb4565b811015610d0157610b97600682611cbe565b828281518110610ba957610ba961530d565b60200260200101906001600160401b031690816001600160401b03168152505060086000838381518110610bdf57610bdf61530d565b6020908102919091018101516001600160401b039081168352828201939093526040918201600020825160808101845281546001600160a01b038116825260ff600160a01b820416151593820193909352600160a81b90920490931691810191909152600182018054919291606084019190610c5a9061540f565b80601f0160208091040260200160405190810160405280929190818152602001828054610c869061540f565b8015610cd35780601f10610ca857610100808354040283529160200191610cd3565b820191906000526020600020905b815481529060010190602001808311610cb657829003601f168201915b505050505081525050838281518110610cee57610cee61530d565b6020908102919091010152600101610b7b565b50939092509050565b6000610d18600160046155f7565b6002610d25608085615620565b6001600160401b0316610d389190615646565b610d428585611cca565b901c166003811115610d5657610d56614260565b90505b92915050565b610d67611d0f565b815181518114610d8a576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610fde576000848281518110610da957610da961530d565b60200260200101519050600081602001515190506000858481518110610dd157610dd161530d565b6020026020010151905080518214610dfc576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610fcf576000828281518110610e1b57610e1b61530d565b6020026020010151600001519050600085602001518381518110610e4157610e4161530d565b6020026020010151905081600014610e95578060800151821015610e95578551815151604051633a98d46360e11b81526001600160401b0390921660048301526024820152604481018390526064016107c2565b838381518110610ea757610ea761530d565b602002602001015160200151518160a001515114610ef457805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b031660248201526044016107c2565b60005b8160a0015151811015610fc1576000858581518110610f1857610f1861530d565b6020026020010151602001518281518110610f3557610f3561530d565b602002602001015163ffffffff16905080600014610fb85760008360a001518381518110610f6557610f6561530d565b60200260200101516040015163ffffffff16905080821015610fb6578351516040516348e617b360e01b815260048101919091526024810184905260448101829052606481018390526084016107c2565b505b50600101610ef7565b505050806001019050610dff565b50505050806001019050610d8d565b50610fe98383611bf1565b505050565b33301461100e576040516306e34e6560e31b815260040160405180910390fd5b604080516000808252602082019092528161104b565b60408051808201909152600080825260208201528152602001906001900390816110245790505b5060a087015151909150156110815761107e8660a001518760200151886060015189600001516020015189898989611d77565b90505b6040805160a081018252875151815287516020908101516001600160401b03168183015288015181830152908701516060820152608081018290526005546001600160a01b03168015611174576040516308d450a160e01b81526001600160a01b038216906308d450a1906110fa9085906004016156fe565b600060405180830381600087803b15801561111457600080fd5b505af1925050508015611125575060015b611174573d808015611153576040519150601f19603f3d011682016040523d82523d6000602084013e611158565b606091505b50806040516309c2532560e01b81526004016107c29190613f90565b60408801515115801561118957506080880151155b806111a0575060608801516001600160a01b03163b155b806111c7575060608801516111c5906001600160a01b03166385572ffb60e01b611f28565b155b156111d45750505061129e565b87516020908101516001600160401b03166000908152600890915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf97983926112329289926113889291600401615711565b6000604051808303816000875af1158015611251573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611279919081019061574d565b509150915081610a3a57806040516302a35ba360e21b81526004016107c29190613f90565b5050505050565b6000546001600160a01b031633146112d05760405163015aa1e360e11b815260040160405180910390fd5b600180546001600160a01b0319808216339081179093556000805490911681556040516001600160a01b03909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113306115f6565b61052f81611f44565b61137c6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561142557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611407575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561148757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611469575b5050505050815250509050919050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260088352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916115239061540f565b80601f016020809104026020016040519081016040528092919081815260200182805461154f9061540f565b80156114875780601f1061157157610100808354040283529160200191611487565b820191906000526020600020905b81548152906001019060200180831161157f57505050919092525091949350505050565b6115ab6115f6565b61052f81612049565b6115bc6115f6565b60005b81518110156115f2576115ea8282815181106115dd576115dd61530d565b60200260200101516120c2565b6001016115bf565b5050565b6001546001600160a01b03163314611621576040516315ae3a6f60e11b815260040160405180910390fd5b565b60005b81518110156115f25760008282815181106116435761164361530d565b60200260200101519050600081602001519050806001600160401b03166000036116805760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166116a8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260086020526040902060608301516001820180546116d49061540f565b905060000361173657815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161179f565b8154600160a81b90046001600160401b031660011480159061177657508051602082012060405161176b906001850190615449565b604051809103902014155b1561179f57604051632105803760e11b81526001600160401b03841660048201526024016107c2565b805115806117d45750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156117f2576040516342bcdf7f60e11b815260040160405180910390fd5b600182016118008282615832565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b029290921674ffffffffffffffffffffffffffffffffffffffffff199091161717825561185b60066001600160401b0385166123ec565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b8360405161189591906158f1565b60405180910390a250505050806001019050611626565b6001600160401b03811660009081526008602052604081208054600160a01b900460ff16610d595760405163ed053c5960e01b81526001600160401b03841660048201526024016107c2565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119578760a461593f565b905082606001511561199f578451611970906020615646565b865161197d906020615646565b6119889060a061593f565b611992919061593f565b61199c908261593f565b90505b3681146119c857604051638e1192e160e01b8152600481018290523660248201526044016107c2565b50815181146119f75781516040516324f7d61360e21b81526004810191909152602481018290526044016107c2565b6119ff611d0f565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611a4d57611a4d614260565b6002811115611a5e57611a5e614260565b9052509050600281602001516002811115611a7b57611a7b614260565b148015611acf5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611ab757611ab761530d565b6000918252602090912001546001600160a01b031633145b611aec57604051631b41e11d60e31b815260040160405180910390fd5b50816060015115611b9c576020820151611b07906001615952565b60ff16855114611b2a576040516371253a2560e01b815260040160405180910390fd5b8351855114611b4c5760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611b5e92919061596b565b604051908190038120611b75918b9060200161597b565b604051602081830303815290604052805190602001209050611b9a8a828888886123f8565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611c135760405163c2e5347d60e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611c56565b604080518082019091526000815260606020820152815260200190600190039081611c2e5790505b50905060005b845181101561129e57611cac858281518110611c7a57611c7a61530d565b602002602001015184611ca657858381518110611c9957611c9961530d565b60200260200101516125b5565b836125b5565b600101611c5c565b6000610d59825490565b6000610d568383612e46565b6001600160401b038216600090815260096020526040812081611cee60808561598f565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461162157604051630f01ce8560e01b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107c2565b606088516001600160401b03811115611d9257611d92613c42565b604051908082528060200260200182016040528015611dd757816020015b6040805180820190915260008082526020820152815260200190600190039081611db05790505b509050811560005b8a51811015611f1a5781611e7757848482818110611dff57611dff61530d565b9050602002016020810190611e1491906159b5565b63ffffffff1615611e7757848482818110611e3157611e3161530d565b9050602002016020810190611e4691906159b5565b8b8281518110611e5857611e5861530d565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611ef58b8281518110611e8c57611e8c61530d565b60200260200101518b8b8b8b8b87818110611ea957611ea961530d565b9050602002810190611ebb91906159d0565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e7092505050565b838281518110611f0757611f0761530d565b6020908102919091010152600101611ddf565b505098975050505050505050565b6000611f3383613152565b8015610d565750610d568383613185565b80516001600160a01b0316611f6c576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889167fffffffffffffffff0000000000000000000000000000000000000000000000009097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b336001600160a01b0382160361207257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120ed576000604051631b3fab5160e11b81526004016107c29190615a16565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361213e576060840151600182018054911515620100000262ff00001990921691909117905561217a565b6060840151600182015460ff620100009091041615159015151461217a576040516321fd80df60e21b815260ff841660048201526024016107c2565b60a0840151805161010010156121a6576001604051631b3fab5160e11b81526004016107c29190615a16565b80516000036121cb576005604051631b3fab5160e11b81526004016107c29190615a16565b612231848460030180548060200260200160405190810160405280929190818152602001828054801561222757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612209575b505050505061320f565b8460600151156123615761229f8484600201805480602002602001604051908101604052809291908181526020018280548015612227576020028201919060005260206000209081546001600160a01b0316815260019091019060200180831161220957505050505061320f565b6080850151805161010010156122cb576002604051631b3fab5160e11b81526004016107c29190615a16565b60408601516122db906003615a30565b60ff16815111612301576003604051631b3fab5160e11b81526004016107c29190615a16565b815181511015612327576001604051631b3fab5160e11b81526004016107c29190615a16565b805160018401805461ff00191661010060ff8416021790556123529060028601906020840190613bc8565b5061235f85826001613278565b505b61236d84826002613278565b80516123829060038501906020840190613bc8565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123db9389939260028a01929190615a4c565b60405180910390a161129e846133d3565b6000610d568383613456565b8251600090815b818110156125ab57600060018886846020811061241e5761241e61530d565b61242b91901a601b615952565b89858151811061243d5761243d61530d565b60200260200101518986815181106124575761245761530d565b602002602001015160405160008152602001604052604051612495949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156124b7573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561251857612518614260565b600281111561252957612529614260565b905250905060018160200151600281111561254657612546614260565b1461256457604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561258e57604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506123ff565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612632573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265691906153f2565b156126c757801561268557604051637edeb53960e11b81526001600160401b03831660048201526024016107c2565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60208401515160008190036126fd57845160405163676cf24b60e11b81526001600160401b0390911660048201526024016107c2565b8460400151518114612722576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561273c5761273c613c42565b604051908082528060200260200182016040528015612765578160200160208202803683370190505b50905060007f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f857f00000000000000000000000000000000000000000000000000000000000000006127b6886118ac565b6001016040516127c69190615449565b6040519081900381206127fe949392916020019384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120905060005b83811015612934576000886020015182815181106128395761283961530d565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146128b05780516040908101519051631c21951160e11b81526001600160401b0390911660048201526024016107c2565b866001600160401b03168160000151602001516001600160401b03161461290457805160200151604051636c95f1eb60e01b81526001600160401b03808a16600483015290911660248201526044016107c2565b61290e81846134a5565b8483815181106129205761292061530d565b602090810291909101015250600101612819565b5050600061294c858389606001518a608001516135ad565b90508060000361297a57604051633ee8bd3f60e11b81526001600160401b03861660048201526024016107c2565b60005b838110156125ab5760005a90506000896020015183815181106129a2576129a261530d565b6020026020010151905060006129c089836000015160600151610d0a565b905060008160038111156129d6576129d6614260565b14806129f3575060038160038111156129f1576129f1614260565b145b612a4957815160600151604080516001600160401b03808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612e3e565b60608815612b28578a8581518110612a6357612a6361530d565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff16612a9188426155f7565b1190508080612ab157506003836003811115612aaf57612aaf614260565b145b612ad9576040516354e7e43160e11b81526001600160401b038c1660048201526024016107c2565b8b8681518110612aeb57612aeb61530d565b602002602001015160000151600014612b22578b8681518110612b1057612b1061530d565b60209081029190910101515160808501525b50612b94565b6000826003811115612b3c57612b3c614260565b14612b9457825160600151604080516001600160401b03808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612e3e565b8251608001516001600160401b031615612c6a576000826003811115612bbc57612bbc614260565b03612c6a5782516080015160208401516040516370701e5760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c1a928f929190600401615afe565b6020604051808303816000875af1158015612c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5d91906153f2565b612c6a5750505050612e3e565b60008c604001518681518110612c8257612c8261530d565b6020026020010151905080518460a001515114612ccc57835160600151604051631cfe6d8b60e01b81526001600160401b03808e16600483015290911660248201526044016107c2565b612ce08b85600001516060015160016135ea565b600080612cee86848661368f565b91509150612d058d876000015160600151846135ea565b8b15612d5c576003826003811115612d1f57612d1f614260565b03612d5c576000856003811115612d3857612d38614260565b14612d5c57855151604051632b11b8d960e01b81526107c291908390600401615b2a565b6002826003811115612d7057612d70614260565b14612db1576003826003811115612d8957612d89614260565b14612db1578551606001516040516349362d1f60e11b81526107c2918f918590600401615b43565b8560000151600001518660000151606001516001600160401b03168e6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612e0957612e0961530d565b602002602001015186865a612e1e908f6155f7565b604051612e2e9493929190615b68565b60405180910390a4505050505050505b60010161297d565b6000826000018281548110612e5d57612e5d61530d565b9060005260206000200154905092915050565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f189190615b9f565b90506001600160a01b0381161580612f475750612f456001600160a01b03821663aff2afbf60e01b611f28565b155b15612f705760405163ae9b4ce960e01b81526001600160a01b03821660048201526024016107c2565b600080612f8888858c6040015163ffffffff16613743565b91509150600080600061303b6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b8152506040516024016130059190615bbc565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613828565b92509250925082613063578582604051634ff17cad60e11b81526004016107c2929190615c88565b8151602014613092578151604051631e3be00960e21b81526020600482015260248101919091526044016107c2565b6000828060200190518101906130a89190615caa565b9050866001600160a01b03168c6001600160a01b0316146131245760006130d98d8a6130d4868a6155f7565b613743565b509050868110806130f35750816130f088836155f7565b14155b156131225760405163a966e21f60e01b81526004810183905260248101889052604481018290526064016107c2565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613165826301ffc9a760e01b613185565b8015610d59575061317e826001600160e01b0319613185565b1592915050565b6040516001600160e01b031982166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d915060005190508280156131f8575060208210155b80156132045750600081115b979650505050505050565b60005b8151811015610fe95760ff8316600090815260036020526040812083519091908490849081106132445761324461530d565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613212565b60005b8251811015610aa95760008382815181106132985761329861530d565b60200260200101519050600060028111156132b5576132b5614260565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156132f4576132f4614260565b14613315576004604051631b3fab5160e11b81526004016107c29190615a16565b6001600160a01b03811661333c5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561336257613362614260565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156133bf576133bf614260565b02179055509050505080600101905061327b565b60ff8181166000818152600260205260409020600101546201000090049091169061342b5780613416576040516317bd8dd160e11b815260040160405180910390fd5b600b805467ffffffffffffffff191690555050565b60001960ff8316016115f25780156115f2576040516307b8c74d60e51b815260040160405180910390fd5b600081815260018301602052604081205461349d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d59565b506000610d59565b81518051606080850151908301516080808701519401516040516000958695889561350995919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a0015160405160200161354c9190615d64565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b6000806135bb858585613902565b6001600160401b0387166000908152600a6020908152604080832093835292905220549150505b949350505050565b600060026135f9608085615620565b6001600160401b031661360c9190615646565b9050600061361a8585611cca565b905081613629600160046155f7565b901b19168183600381111561364057613640614260565b6001600160401b03871660009081526009602052604081209190921b9290921791829161366e60808861598f565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c20906136bc90889088908890600401615dfb565b600060405180830381600087803b1580156136d657600080fd5b505af19250505080156136e7575060015b613726573d808015613715576040519150601f19603f3d011682016040523d82523d6000602084013e61371a565b606091505b5060039250905061373b565b50506040805160208101909152600081526002905b935093915050565b60008060008060006137a48860405160240161376e91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613828565b925092509250826137cc578682604051634ff17cad60e11b81526004016107c2929190615c88565b60208251146137fb578151604051631e3be00960e21b81526020600482015260248101919091526044016107c2565b8180602001905181019061380f9190615caa565b61381982886155f7565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561384a5761384a613c42565b6040519080825280601f01601f191660200182016040528015613874576020820181803683370190505b509150863b61388e5763030ed58f60e21b60005260046000fd5b5a858110156138a857632be8ca8b60e21b60005260046000fd5b85900360408104810387106138c8576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156138eb5750835b808352806000602085013e50955095509592505050565b825182516000919081830361392a57604051630469ac9960e21b815260040160405180910390fd5b610101821180159061393e57506101018111155b61395b576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613985576040516309bde33960e01b815260040160405180910390fd5b806000036139b257866000815181106139a0576139a061530d565b60200260200101519350505050613b80565b6000816001600160401b038111156139cc576139cc613c42565b6040519080825280602002602001820160405280156139f5578160200160208202803683370190505b50905060008080805b85811015613b1f5760006001821b8b811603613a595788851015613a42578c5160018601958e918110613a3357613a3361530d565b60200260200101519050613a7b565b8551600185019487918110613a3357613a3361530d565b8b5160018401938d918110613a7057613a7061530d565b602002602001015190505b600089861015613aab578d5160018701968f918110613a9c57613a9c61530d565b60200260200101519050613acd565b8651600186019588918110613ac257613ac261530d565b602002602001015190505b82851115613aee576040516309bde33960e01b815260040160405180910390fd5b613af88282613b87565b878481518110613b0a57613b0a61530d565b602090810291909101015250506001016139fe565b506001850382148015613b3157508683145b8015613b3c57508581145b613b59576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613b6e57613b6e61530d565b60200260200101519750505050505050505b9392505050565b6000818310613b9f57613b9a8284613ba5565b610d56565b610d5683835b60408051600160208201529081018390526060810182905260009060800161358f565b828054828255906000526020600020908101928215613c1d579160200282015b82811115613c1d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613be8565b50613c29929150613c2d565b5090565b5b80821115613c295760008155600101613c2e565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613c7a57613c7a613c42565b60405290565b60405160a081016001600160401b0381118282101715613c7a57613c7a613c42565b60405160c081016001600160401b0381118282101715613c7a57613c7a613c42565b604080519081016001600160401b0381118282101715613c7a57613c7a613c42565b604051606081016001600160401b0381118282101715613c7a57613c7a613c42565b604051601f8201601f191681016001600160401b0381118282101715613d3057613d30613c42565b604052919050565b60006001600160401b03821115613d5157613d51613c42565b5060051b60200190565b6001600160a01b038116811461052f57600080fd5b80356001600160401b0381168114613d8757600080fd5b919050565b801515811461052f57600080fd5b8035613d8781613d8c565b60006001600160401b03821115613dbe57613dbe613c42565b50601f01601f191660200190565b600082601f830112613ddd57600080fd5b8135613df0613deb82613da5565b613d08565b818152846020838601011115613e0557600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613e3557600080fd5b82356001600160401b0380821115613e4c57600080fd5b818501915085601f830112613e6057600080fd5b8135613e6e613deb82613d38565b81815260059190911b83018401908481019088831115613e8d57600080fd5b8585015b83811015613f3357803585811115613ea95760008081fd5b86016080818c03601f1901811315613ec15760008081fd5b613ec9613c58565b89830135613ed681613d5b565b81526040613ee5848201613d70565b8b830152606080850135613ef881613d8c565b83830152928401359289841115613f1157600091508182fd5b613f1f8f8d86880101613dcc565b908301525085525050918601918601613e91565b5098975050505050505050565b60005b83811015613f5b578181015183820152602001613f43565b50506000910152565b60008151808452613f7c816020860160208601613f40565b601f01601f19169290920160200192915050565b602081526000610d566020830184613f64565b8060608101831015610d5957600080fd5b60008083601f840112613fc657600080fd5b5081356001600160401b03811115613fdd57600080fd5b602083019150836020828501011115613ff557600080fd5b9250929050565b60008083601f84011261400e57600080fd5b5081356001600160401b0381111561402557600080fd5b6020830191508360208260051b8501011115613ff557600080fd5b60008060008060008060008060e0898b03121561405c57600080fd5b6140668a8a613fa3565b975060608901356001600160401b038082111561408257600080fd5b61408e8c838d01613fb4565b909950975060808b01359150808211156140a757600080fd5b6140b38c838d01613ffc565b909750955060a08b01359150808211156140cc57600080fd5b506140d98b828c01613ffc565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561410757600080fd5b6141118585613fa3565b925060608401356001600160401b0381111561412c57600080fd5b61413886828701613fb4565b9497909650939450505050565b6001600160a01b0381511682526020810151151560208301526001600160401b03604082015116604083015260006060820151608060608501526135e26080850182613f64565b604080825283519082018190526000906020906060840190828701845b828110156141ce5781516001600160401b0316845292840192908401906001016141a9565b50505083810382850152845180825282820190600581901b8301840187850160005b8381101561421e57601f1986840301855261420c838351614145565b948701949250908601906001016141f0565b50909998505050505050505050565b6000806040838503121561424057600080fd5b61424983613d70565b915061425760208401613d70565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b6004811061428657614286614260565b9052565b60208101610d598284614276565b600060a082840312156142aa57600080fd5b6142b2613c80565b9050813581526142c460208301613d70565b60208201526142d560408301613d70565b60408201526142e660608301613d70565b60608201526142f760808301613d70565b608082015292915050565b8035613d8781613d5b565b803563ffffffff81168114613d8757600080fd5b600082601f83011261433257600080fd5b81356020614342613deb83613d38565b82815260059290921b8401810191818101908684111561436157600080fd5b8286015b848110156144315780356001600160401b03808211156143855760008081fd5b9088019060a0828b03601f190181131561439f5760008081fd5b6143a7613c80565b87840135838111156143b95760008081fd5b6143c78d8a83880101613dcc565b8252506040808501356143d981613d5b565b828a015260606143ea86820161430d565b828401526080915081860135858111156144045760008081fd5b6144128f8c838a0101613dcc565b9184019190915250919093013590830152508352918301918301614365565b509695505050505050565b6000610140828403121561444f57600080fd5b614457613ca2565b90506144638383614298565b815260a08201356001600160401b038082111561447f57600080fd5b61448b85838601613dcc565b602084015260c08401359150808211156144a457600080fd5b6144b085838601613dcc565b60408401526144c160e08501614302565b606084015261010084013560808401526101208401359150808211156144e657600080fd5b506144f384828501614321565b60a08301525092915050565b600082601f83011261451057600080fd5b81356020614520613deb83613d38565b82815260059290921b8401810191818101908684111561453f57600080fd5b8286015b848110156144315780356001600160401b038111156145625760008081fd5b6145708986838b010161443c565b845250918301918301614543565b600082601f83011261458f57600080fd5b8135602061459f613deb83613d38565b82815260059290921b840181019181810190868411156145be57600080fd5b8286015b848110156144315780356001600160401b03808211156145e157600080fd5b818901915089603f8301126145f557600080fd5b85820135614605613deb82613d38565b81815260059190911b830160400190878101908c83111561462557600080fd5b604085015b8381101561465e5780358581111561464157600080fd5b6146508f6040838a0101613dcc565b84525091890191890161462a565b508752505050928401925083016145c2565b600082601f83011261468157600080fd5b81356020614691613deb83613d38565b8083825260208201915060208460051b8701019350868411156146b357600080fd5b602086015b8481101561443157803583529183019183016146b8565b600082601f8301126146e057600080fd5b813560206146f0613deb83613d38565b82815260059290921b8401810191818101908684111561470f57600080fd5b8286015b848110156144315780356001600160401b03808211156147335760008081fd5b9088019060a0828b03601f190181131561474d5760008081fd5b614755613c80565b614760888501613d70565b8152604080850135848111156147765760008081fd5b6147848e8b838901016144ff565b8a840152506060808601358581111561479d5760008081fd5b6147ab8f8c838a010161457e565b83850152506080915081860135858111156147c65760008081fd5b6147d48f8c838a0101614670565b9184019190915250919093013590830152508352918301918301614713565b6000806040838503121561480657600080fd5b6001600160401b038335111561481b57600080fd5b61482884843585016146cf565b91506001600160401b036020840135111561484257600080fd5b6020830135830184601f82011261485857600080fd5b614865613deb8235613d38565b81358082526020808301929160051b84010187101561488357600080fd5b602083015b6020843560051b850101811015614a29576001600160401b03813511156148ae57600080fd5b87603f8235860101126148c057600080fd5b6148d3613deb6020833587010135613d38565b81358501602081810135808452908301929160059190911b016040018a10156148fb57600080fd5b604083358701015b83358701602081013560051b01604001811015614a19576001600160401b038135111561492f57600080fd5b833587018135016040818d03603f1901121561494a57600080fd5b614952613cc4565b604082013581526001600160401b036060830135111561497157600080fd5b8c605f60608401358401011261498657600080fd5b604060608301358301013561499d613deb82613d38565b808282526020820191508f60608460051b60608801358801010111156149c257600080fd5b6060808601358601015b60608460051b6060880135880101018110156149f9576149eb8161430d565b8352602092830192016149cc565b508060208501525050508085525050602083019250602081019050614903565b5084525060209283019201614888565b508093505050509250929050565b600080600080600060608688031215614a4f57600080fd5b85356001600160401b0380821115614a6657600080fd5b614a7289838a0161443c565b96506020880135915080821115614a8857600080fd5b614a9489838a01613ffc565b90965094506040880135915080821115614aad57600080fd5b50614aba88828901613ffc565b969995985093965092949392505050565b600060808284031215614add57600080fd5b614ae5613c58565b8235614af081613d5b565b8152614afe6020840161430d565b60208201526040830135614b1181613d8c565b60408201526060830135614b2481613d5b565b60608201529392505050565b600060208284031215614b4257600080fd5b81356001600160401b03811115614b5857600080fd5b820160a08185031215613b8057600080fd5b803560ff81168114613d8757600080fd5b600060208284031215614b8d57600080fd5b610d5682614b6a565b60008151808452602080850194506020840160005b83811015614bd05781516001600160a01b031687529582019590820190600101614bab565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c2a60e0840182614b96565b90506040840151601f198483030160c0850152614c478282614b96565b95945050505050565b60008060408385031215614c6357600080fd5b614c6c83613d70565b946020939093013593505050565b600060208284031215614c8c57600080fd5b610d5682613d70565b602081526000610d566020830184614145565b600060208284031215614cba57600080fd5b8135613b8081613d5b565b600082601f830112614cd657600080fd5b81356020614ce6613deb83613d38565b8083825260208201915060208460051b870101935086841115614d0857600080fd5b602086015b84811015614431578035614d2081613d5b565b8352918301918301614d0d565b60006020808385031215614d4057600080fd5b82356001600160401b0380821115614d5757600080fd5b818501915085601f830112614d6b57600080fd5b8135614d79613deb82613d38565b81815260059190911b83018401908481019088831115614d9857600080fd5b8585015b83811015613f3357803585811115614db357600080fd5b860160c0818c03601f19011215614dca5760008081fd5b614dd2613ca2565b8882013581526040614de5818401614b6a565b8a8301526060614df6818501614b6a565b8284015260809150614e09828501613d9a565b9083015260a08381013589811115614e215760008081fd5b614e2f8f8d83880101614cc5565b838501525060c0840135915088821115614e495760008081fd5b614e578e8c84870101614cc5565b9083015250845250918601918601614d9c565b80356001600160e01b0381168114613d8757600080fd5b600082601f830112614e9257600080fd5b81356020614ea2613deb83613d38565b82815260069290921b84018101918181019086841115614ec157600080fd5b8286015b848110156144315760408189031215614ede5760008081fd5b614ee6613cc4565b614eef82613d70565b8152614efc858301614e6a565b81860152835291830191604001614ec5565b600082601f830112614f1f57600080fd5b81356020614f2f613deb83613d38565b82815260059290921b84018101918181019086841115614f4e57600080fd5b8286015b848110156144315780356001600160401b0380821115614f725760008081fd5b9088019060a0828b03601f1901811315614f8c5760008081fd5b614f94613c80565b614f9f888501613d70565b815260408085013584811115614fb55760008081fd5b614fc38e8b83890101613dcc565b8a8401525060609350614fd7848601613d70565b908201526080614fe8858201613d70565b93820193909352920135908201528352918301918301614f52565b600082601f83011261501457600080fd5b81356020615024613deb83613d38565b82815260069290921b8401810191818101908684111561504357600080fd5b8286015b8481101561443157604081890312156150605760008081fd5b615068613cc4565b813581528482013585820152835291830191604001615047565b6000602080838503121561509557600080fd5b82356001600160401b03808211156150ac57600080fd5b90840190606082870312156150c057600080fd5b6150c8613ce6565b8235828111156150d757600080fd5b830160408189038113156150ea57600080fd5b6150f2613cc4565b82358581111561510157600080fd5b8301601f81018b1361511257600080fd5b8035615120613deb82613d38565b81815260069190911b8201890190898101908d83111561513f57600080fd5b928a01925b8284101561518f5785848f03121561515c5760008081fd5b615164613cc4565b843561516f81613d5b565b815261517c858d01614e6a565b818d0152825292850192908a0190615144565b8452505050828701359150848211156151a757600080fd5b6151b38a838501614e81565b818801528352505082840135828111156151cc57600080fd5b6151d888828601614f0e565b858301525060408301359350818411156151f157600080fd5b6151fd87858501615003565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561529d57601f19868403018952815160a06001600160401b0380835116865286830151828888015261526183880182613f64565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615229565b5090979650505050505050565b6001600160a01b0384168152600060206060818401526152cd606084018661520c565b83810360408581019190915285518083528387019284019060005b8181101561421e578451805184528601518684015293850193918301916001016152e8565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561537a57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615343565b50508583015187820388850152805180835290840192506000918401905b808310156153d357835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615398565b50979650505050505050565b602081526000610d566020830184615323565b60006020828403121561540457600080fd5b8151613b8081613d8c565b600181811c9082168061542357607f821691505b60208210810361544357634e487b7160e01b600052602260045260246000fd5b50919050565b60008083546154578161540f565b6001828116801561546f5760018114615484576154b3565b60ff19841687528215158302870194506154b3565b8760005260208060002060005b858110156154aa5781548a820152908401908201615491565b50505082870194505b50929695505050505050565b600081546154cc8161540f565b8085526020600183811680156154e9576001811461550357615531565b60ff1985168884015283151560051b880183019550615531565b866000528260002060005b858110156155295781548a820186015290830190840161550e565b890184019650505b505050505092915050565b60408152600061554f6040830185613f64565b8281036020840152614c4781856154bf565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561559757615597615561565b5092915050565b6040815260006155b1604083018561520c565b8281036020840152614c478185615323565b6000602082840312156155d557600080fd5b81356001600160401b038111156155eb57600080fd5b6135e2848285016146cf565b81810381811115610d5957610d59615561565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061563a5761563a61560a565b92169190910692915050565b8082028115828204841417610d5957610d59615561565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261569060a0870182613f64565b9050606085015186820360608801526156a98282613f64565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156153d357835180516001600160a01b03168352860151868301529285019260019290920191908401906156cc565b602081526000610d56602083018461565d565b608081526000615724608083018761565d565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561576257600080fd5b835161576d81613d8c565b60208501519093506001600160401b0381111561578957600080fd5b8401601f8101861361579a57600080fd5b80516157a8613deb82613da5565b8181528760208385010111156157bd57600080fd5b6157ce826020830160208601613f40565b809450505050604084015190509250925092565b601f821115610fe9576000816000526020600020601f850160051c8101602086101561580b5750805b601f850160051c820191505b8181101561582a57828155600101615817565b505050505050565b81516001600160401b0381111561584b5761584b613c42565b61585f81615859845461540f565b846157e2565b602080601f831160018114615894576000841561587c5750858301515b600019600386901b1c1916600185901b17855561582a565b600085815260208120601f198616915b828110156158c3578886015182559484019460019091019084016158a4565b50858210156158e15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610d5660a08301600185016154bf565b80820180821115610d5957610d59615561565b60ff8181168382160190811115610d5957610d59615561565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806159a9576159a961560a565b92169190910492915050565b6000602082840312156159c757600080fd5b610d568261430d565b6000808335601e198436030181126159e757600080fd5b8301803591506001600160401b03821115615a0157600080fd5b602001915036819003821315613ff557600080fd5b6020810160068310615a2a57615a2a614260565b91905290565b60ff818116838216029081169081811461559757615597615561565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615aa45784546001600160a01b031683526001948501949284019201615a7f565b50508481036060860152865180825290820192508187019060005b81811015615ae45782516001600160a01b031685529383019391830191600101615abf565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b03808616835280851660208401525060606040830152614c476060830184613f64565b8281526040602082015260006135e26040830184613f64565b6001600160401b03848116825283166020820152606081016135e26040830184614276565b848152615b786020820185614276565b608060408201526000615b8e6080830185613f64565b905082606083015295945050505050565b600060208284031215615bb157600080fd5b8151613b8081613d5b565b6020815260008251610100806020850152615bdb610120850183613f64565b91506020850151615bf760408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c3160a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c4e8483613f64565b935060c08701519150808685030160e0870152615c6b8483613f64565b935060e0870151915080868503018387015250615af48382613f64565b6001600160a01b03831681526040602082015260006135e26040830184613f64565b600060208284031215615cbc57600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561529d57601f19868403018952815160a08151818652615d0682870182613f64565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615d428382613f64565b6080948501519790940196909652505098840198925090830190600101615ce0565b602081526000610d566020830184615cc3565b60008282518085526020808601955060208260051b8401016020860160005b8481101561529d57601f19868403018952615db2838351613f64565b98840198925090830190600101615d96565b60008151808452602080850194506020840160005b83811015614bd057815163ffffffff1687529582019590820190600101615dd9565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615e636101a0850183613f64565b91506040870151605f198086850301610120870152615e828483613f64565b935060608901519150615e9f838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615ec88282615cc3565b9150508281036020840152615edd8186615d77565b90508281036040840152615af48185615dc456fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyBatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"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[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllSourceChainConfigs\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006be738038062006be7833981016040819052620000359162000880565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001c4565b50504660805260208301516001600160a01b03161580620000b6575060408301516001600160a01b0316155b80620000cd575060608301516001600160a01b0316155b15620000ec576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b0316600003620001185760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001b0826200023e565b620001bb816200032c565b50505062000c72565b336001600160a01b03821603620001ee57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b031662000267576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889166001600160c01b03199097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b60005b8151811015620005c1576000828281518110620003505762000350620009aa565b60200260200101519050600081602001519050806001600160401b03166000036200038e5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526008602052604090206060830151600182018054620003e590620009c0565b905060000362000448578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004b9565b8154600160a81b90046001600160401b03166001148015906200048b57508051602082012060405162000480906001850190620009fc565b604051809103902014155b15620004b957604051632105803760e11b81526001600160401b038416600482015260240160405180910390fd5b80511580620004ef5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200050e576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200051e828262000acf565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b0319909116171782556200056d60066001600160401b038516620005c5565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b83604051620005a9919062000b9b565b60405180910390a2505050508060010190506200032f565b5050565b6000620005d38383620005dc565b90505b92915050565b60008181526001830160205260408120546200062557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005d6565b506000620005d6565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200066957620006696200062e565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200069a576200069a6200062e565b604052919050565b80516001600160401b0381168114620006ba57600080fd5b919050565b6001600160a01b0381168114620006d557600080fd5b50565b80518015158114620006ba57600080fd5b6000601f83601f840112620006fd57600080fd5b825160206001600160401b03808311156200071c576200071c6200062e565b8260051b6200072d8382016200066f565b93845286810183019383810190898611156200074857600080fd5b84890192505b858310156200087357825184811115620007685760008081fd5b89016080601f19828d038101821315620007825760008081fd5b6200078c62000644565b888401516200079b81620006bf565b81526040620007ac858201620006a2565b8a8301526060620007bf818701620006d8565b83830152938501519389851115620007d75760008081fd5b84860195508f603f870112620007ef57600094508485fd5b8a8601519450898511156200080857620008086200062e565b620008198b858f880116016200066f565b93508484528f82868801011115620008315760008081fd5b60005b8581101562000851578681018301518582018d01528b0162000834565b5060009484018b0194909452509182015283525091840191908401906200074e565b9998505050505050505050565b60008060008385036101208112156200089857600080fd5b6080811215620008a757600080fd5b620008b162000644565b620008bc86620006a2565b81526020860151620008ce81620006bf565b60208201526040860151620008e381620006bf565b60408201526060860151620008f881620006bf565b606082015293506080607f19820112156200091257600080fd5b506200091d62000644565b60808501516200092d81620006bf565b815260a085015163ffffffff811681146200094757600080fd5b60208201526200095a60c08601620006d8565b604082015260e08501516200096f81620006bf565b60608201526101008501519092506001600160401b038111156200099257600080fd5b620009a086828701620006e9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009d557607f821691505b602082108103620009f657634e487b7160e01b600052602260045260246000fd5b50919050565b600080835462000a0c81620009c0565b6001828116801562000a27576001811462000a3d5762000a6e565b60ff198416875282151583028701945062000a6e565b8760005260208060002060005b8581101562000a655781548a82015290840190820162000a4a565b50505082870194505b50929695505050505050565b601f82111562000aca576000816000526020600020601f850160051c8101602086101562000aa55750805b601f850160051c820191505b8181101562000ac65782815560010162000ab1565b5050505b505050565b81516001600160401b0381111562000aeb5762000aeb6200062e565b62000b038162000afc8454620009c0565b8462000a7a565b602080601f83116001811462000b3b576000841562000b225750858301515b600019600386901b1c1916600185901b17855562000ac6565b600085815260208120601f198616915b8281101562000b6c5788860151825594840194600190910190840162000b4b565b508582101562000b8b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000bf081620009c0565b8060a089015260c0600183166000811462000c14576001811462000c315762000c63565b60ff19841660c08b015260c083151560051b8b0101945062000c63565b85600052602060002060005b8481101562000c5a5781548c820185015290880190890162000c3d565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ef862000cef600039600081816102070152612a4a0152600081816101d80152612cf20152600081816101a901528181610f7501528181611125015261244a01526000818161017a015281816125f501526126ac01526000818161190401526119370152615ef86000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637edf52f4116100ad578063de5e0b9a11610071578063de5e0b9a146104b2578063e9d68a8e146104c5578063f2fde38b146104e5578063f58e03fc146104f8578063f716f99f1461050b57600080fd5b80637edf52f41461041257806385572ffb146104255780638da5cb5b14610433578063c673e5841461044e578063ccd37ba31461046e57600080fd5b80635e36480c116100f45780635e36480c146103075780635e7bb0081461032757806360987c201461033a5780637437ff9f1461034d57806379ba50971461040a57600080fd5b806304666f9c1461013157806306285c6914610146578063181f5a771461028d5780633f4b04aa146102d65780635215505b146102f1575b600080fd5b61014461013f366004613e1c565b61051e565b005b61023760408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b604051610284919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102c96040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102849190613f8a565b600b546040516001600160401b039091168152602001610284565b6102f9610532565b604051610284929190613fe4565b61031a610315366004614085565b61078d565b60405161028491906140e2565b61014461033536600461464b565b6107e2565b6101446103483660046148da565b610a76565b6103c360408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526004546001600160a01b038082168352600160a01b820463ffffffff166020840152600160c01b90910460ff16151592820192909252600554909116606082015290565b604051610284919081516001600160a01b03908116825260208084015163ffffffff1690830152604080840151151590830152606092830151169181019190915260800190565b610144610d33565b61014461042036600461496e565b610db6565b61014461012c3660046149d3565b6001546040516001600160a01b039091168152602001610284565b61046161045c366004614a1e565b610dc7565b6040516102849190614a7e565b6104a461047c366004614af3565b6001600160401b03919091166000908152600a60209081526040808320938352929052205490565b604051908152602001610284565b6101446104c0366004614b6f565b610f25565b6104d86104d3366004614c21565b611428565b6040516102849190614c3c565b6101446104f3366004614c4f565b611534565b610144610506366004614c6c565b611545565b610144610519366004614d27565b6115ae565b6105266115f0565b61052f8161161d565b50565b606080600061054160066118a6565b6001600160401b0381111561055857610558613c3c565b6040519080825280602002602001820160405280156105a957816020015b60408051608081018252600080825260208083018290529282015260608082015282526000199092019101816105765790505b50905060006105b860066118a6565b6001600160401b038111156105cf576105cf613c3c565b6040519080825280602002602001820160405280156105f8578160200160208202803683370190505b50905060005b61060860066118a6565b8110156107845761061a6006826118b0565b82828151811061062c5761062c614e64565b60200260200101906001600160401b031690816001600160401b0316815250506008600083838151811061066257610662614e64565b6020908102919091018101516001600160401b039081168352828201939093526040918201600020825160808101845281546001600160a01b038116825260ff600160a01b820416151593820193909352600160a81b909204909316918101919091526001820180549192916060840191906106dd90614e7a565b80601f016020809104026020016040519081016040528092919081815260200182805461070990614e7a565b80156107565780601f1061072b57610100808354040283529160200191610756565b820191906000526020600020905b81548152906001019060200180831161073957829003601f168201915b50505050508152505083828151811061077157610771614e64565b60209081029190910101526001016105fe565b50939092509050565b600061079b60016004614eca565b60026107a8608085614ef3565b6001600160401b03166107bb9190614f19565b6107c585856118bc565b901c1660038111156107d9576107d96140b8565b90505b92915050565b6107ea611901565b81518151811461080d576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610a6657600084828151811061082c5761082c614e64565b6020026020010151905060008160200151519050600085848151811061085457610854614e64565b602002602001015190508051821461087f576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610a5757600082828151811061089e5761089e614e64565b60200260200101516000015190506000856020015183815181106108c4576108c4614e64565b602002602001015190508160001461091d57806080015182101561091d578551815151604051633a98d46360e11b81526001600160401b0390921660048301526024820152604481018390526064015b60405180910390fd5b83838151811061092f5761092f614e64565b602002602001015160200151518160a00151511461097c57805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b03166024820152604401610914565b60005b8160a0015151811015610a495760008585815181106109a0576109a0614e64565b60200260200101516020015182815181106109bd576109bd614e64565b602002602001015163ffffffff16905080600014610a405760008360a0015183815181106109ed576109ed614e64565b60200260200101516040015163ffffffff16905080821015610a3e578351516040516348e617b360e01b81526004810191909152602481018490526044810182905260648101839052608401610914565b505b5060010161097f565b505050806001019050610882565b50505050806001019050610810565b50610a718383611969565b505050565b333014610a96576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610ad3565b6040805180820190915260008082526020820152815260200190600190039081610aac5790505b5060a08701515190915015610b0957610b068660a001518760200151886060015189600001516020015189898989611a2c565b90505b6040805160a081018252875151815287516020908101516001600160401b03168183015288015181830152908701516060820152608081018290526005546001600160a01b03168015610bfc576040516308d450a160e01b81526001600160a01b038216906308d450a190610b82908590600401614fdd565b600060405180830381600087803b158015610b9c57600080fd5b505af1925050508015610bad575060015b610bfc573d808015610bdb576040519150601f19603f3d011682016040523d82523d6000602084013e610be0565b606091505b50806040516309c2532560e01b81526004016109149190613f8a565b604088015151158015610c1157506080880151155b80610c28575060608801516001600160a01b03163b155b80610c4f57506060880151610c4d906001600160a01b03166385572ffb60e01b611bdd565b155b15610c5c57505050610d2c565b87516020908101516001600160401b03166000908152600890915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610cba9289926113889291600401614ff0565b6000604051808303816000875af1158015610cd9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d01919081019061502c565b509150915081610d2657806040516302a35ba360e21b81526004016109149190613f8a565b50505050505b5050505050565b6000546001600160a01b03163314610d5e5760405163015aa1e360e11b815260040160405180910390fd5b600180546001600160a01b0319808216339081179093556000805490911681556040516001600160a01b03909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610dbe6115f0565b61052f81611bf9565b610e0a6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610eb357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e95575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610f1557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ef7575b5050505050815250509050919050565b6000610f33878901896152d9565b6004805491925090600160c01b900460ff16610fdd5760208201515115610fdd5760208201516040808401519051633854844f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926370a9089e92610fac9230929190600401615501565b60006040518083038186803b158015610fc457600080fd5b505afa158015610fd8573d6000803e3d6000fd5b505050505b81515151151580610ff357508151602001515115155b156110be57600b5460208b0135906001600160401b038083169116101561109657600b805467ffffffffffffffff19166001600160401b03831617905581548351604051633937306f60e01b81526001600160a01b0390921691633937306f9161105f91600401615614565b600060405180830381600087803b15801561107957600080fd5b505af115801561108d573d6000803e3d6000fd5b505050506110bc565b8260200151516000036110bc57604051632261116760e01b815260040160405180910390fd5b505b60005b826020015151811015611374576000836020015182815181106110e6576110e6614e64565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561116c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111909190615627565b156111b957604051637edeb53960e11b81526001600160401b0382166004820152602401610914565b60006111c482611cfe565b9050806001016040516111d79190615644565b6040518091039020836020015180519060200120146112145782602001518160010160405163b80d8fa960e01b8152600401610914929190615737565b60408301518154600160a81b90046001600160401b039081169116141580611255575082606001516001600160401b031683604001516001600160401b0316115b1561129a57825160408085015160608601519151636af0786b60e11b81526001600160401b039384166004820152908316602482015291166044820152606401610914565b6080830151806112bd5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600a60209081526040808320848452909152902054156113155783516040516332cf0cbf60e01b81526001600160401b03909116600482015260248101829052604401610914565b606084015161132590600161575c565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600a6020908152604080832094835293905291909120429055506001016110c1565b50602082015182516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926113ac929091615783565b60405180910390a1610d2660008b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c9250611d4a915050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260088352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916114b490614e7a565b80601f01602080910402602001604051908101604052809291908181526020018280546114e090614e7a565b8015610f155780601f1061150257610100808354040283529160200191610f15565b820191906000526020600020905b81548152906001019060200180831161151057505050919092525091949350505050565b61153c6115f0565b61052f81612043565b611585611554828401846157a8565b604080516000808252602082019092529061157f565b606081526020019060019003908161156a5790505b50611969565b6040805160008082526020820190925290506115a8600185858585866000611d4a565b50505050565b6115b66115f0565b60005b81518110156115ec576115e48282815181106115d7576115d7614e64565b60200260200101516120bc565b6001016115b9565b5050565b6001546001600160a01b0316331461161b576040516315ae3a6f60e11b815260040160405180910390fd5b565b60005b81518110156115ec57600082828151811061163d5761163d614e64565b60200260200101519050600081602001519050806001600160401b031660000361167a5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166116a2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260086020526040902060608301516001820180546116ce90614e7a565b905060000361173057815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611799565b8154600160a81b90046001600160401b0316600114801590611770575080516020820120604051611765906001850190615644565b604051809103902014155b1561179957604051632105803760e11b81526001600160401b0384166004820152602401610914565b805115806117ce5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156117ec576040516342bcdf7f60e11b815260040160405180910390fd5b600182016117fa828261582c565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b029290921674ffffffffffffffffffffffffffffffffffffffffff199091161717825561185560066001600160401b0385166123e6565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b8360405161188f91906158eb565b60405180910390a250505050806001019050611620565b60006107dc825490565b60006107d983836123f2565b6001600160401b0382166000908152600960205260408120816118e0608085615939565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461161b57604051630f01ce8560e01b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610914565b815160000361198b5760405163c2e5347d60e01b815260040160405180910390fd5b805160408051600080825260208201909252911591816119ce565b6040805180820190915260008152606060208201528152602001906001900390816119a65790505b50905060005b8451811015610d2c57611a248582815181106119f2576119f2614e64565b602002602001015184611a1e57858381518110611a1157611a11614e64565b602002602001015161241c565b8361241c565b6001016119d4565b606088516001600160401b03811115611a4757611a47613c3c565b604051908082528060200260200182016040528015611a8c57816020015b6040805180820190915260008082526020820152815260200190600190039081611a655790505b509050811560005b8a51811015611bcf5781611b2c57848482818110611ab457611ab4614e64565b9050602002016020810190611ac9919061595f565b63ffffffff1615611b2c57848482818110611ae657611ae6614e64565b9050602002016020810190611afb919061595f565b8b8281518110611b0d57611b0d614e64565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611baa8b8281518110611b4157611b41614e64565b60200260200101518b8b8b8b8b87818110611b5e57611b5e614e64565b9050602002810190611b70919061597a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cb792505050565b838281518110611bbc57611bbc614e64565b6020908102919091010152600101611a94565b505098975050505050505050565b6000611be883612f99565b80156107d957506107d98383612fcc565b80516001600160a01b0316611c21576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889167fffffffffffffffff0000000000000000000000000000000000000000000000009097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b6001600160401b03811660009081526008602052604081208054600160a01b900460ff166107dc5760405163ed053c5960e01b81526001600160401b0384166004820152602401610914565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611da98760846159c0565b9050826060015115611df1578451611dc2906020614f19565b8651611dcf906020614f19565b611dda9060a06159c0565b611de491906159c0565b611dee90826159c0565b90505b368114611e1a57604051638e1192e160e01b815260048101829052366024820152604401610914565b5081518114611e495781516040516324f7d61360e21b8152600481019190915260248101829052604401610914565b611e51611901565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611e9f57611e9f6140b8565b6002811115611eb057611eb06140b8565b9052509050600281602001516002811115611ecd57611ecd6140b8565b148015611f215750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611f0957611f09614e64565b6000918252602090912001546001600160a01b031633145b611f3e57604051631b41e11d60e31b815260040160405180910390fd5b50816060015115611fee576020820151611f599060016159d3565b60ff16855114611f7c576040516371253a2560e01b815260040160405180910390fd5b8351855114611f9e5760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611fb09291906159ec565b604051908190038120611fc7918b906020016159fc565b604051602081830303815290604052805190602001209050611fec8a82888888613056565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b336001600160a01b0382160361206c57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120e7576000604051631b3fab5160e11b81526004016109149190615a10565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003612138576060840151600182018054911515620100000262ff000019909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040516321fd80df60e21b815260ff84166004820152602401610914565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016109149190615a10565b80516000036121c5576005604051631b3fab5160e11b81526004016109149190615a10565b61222b848460030180548060200260200160405190810160405280929190818152602001828054801561222157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612203575b5050505050613209565b84606001511561235b576122998484600201805480602002602001604051908101604052809291908181526020018280548015612221576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311612203575050505050613209565b6080850151805161010010156122c5576002604051631b3fab5160e11b81526004016109149190615a10565b60408601516122d5906003615a2a565b60ff168151116122fb576003604051631b3fab5160e11b81526004016109149190615a10565b815181511015612321576001604051631b3fab5160e11b81526004016109149190615a10565b805160018401805461ff00191661010060ff84160217905561234c9060028601906020840190613bc2565b5061235985826001613272565b505b61236784826002613272565b805161237c9060038501906020840190613bc2565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123d59389939260028a01929190615a46565b60405180910390a1610d2c846133cd565b60006107d98383613450565b600082600001828154811061240957612409614e64565b9060005260206000200154905092915050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124bd9190615627565b1561252e5780156124ec57604051637edeb53960e11b81526001600160401b0383166004820152602401610914565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b602084015151600081900361256457845160405163676cf24b60e11b81526001600160401b039091166004820152602401610914565b8460400151518114612589576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b038111156125a3576125a3613c3c565b6040519080825280602002602001820160405280156125cc578160200160208202803683370190505b50905060007f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f857f000000000000000000000000000000000000000000000000000000000000000061261d88611cfe565b60010160405161262d9190615644565b604051908190038120612665949392916020019384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120905060005b8381101561279b576000886020015182815181106126a0576126a0614e64565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146127175780516040908101519051631c21951160e11b81526001600160401b039091166004820152602401610914565b866001600160401b03168160000151602001516001600160401b03161461276b57805160200151604051636c95f1eb60e01b81526001600160401b03808a1660048301529091166024820152604401610914565b612775818461349f565b84838151811061278757612787614e64565b602090810291909101015250600101612680565b505060006127b3858389606001518a608001516135a7565b9050806000036127e157604051633ee8bd3f60e11b81526001600160401b0386166004820152602401610914565b60005b83811015612cad5760005a905060008960200151838151811061280957612809614e64565b6020026020010151905060006128278983600001516060015161078d565b9050600081600381111561283d5761283d6140b8565b148061285a57506003816003811115612858576128586140b8565b145b6128b057815160600151604080516001600160401b03808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612ca5565b6060881561298f578a85815181106128ca576128ca614e64565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166128f88842614eca565b119050808061291857506003836003811115612916576129166140b8565b145b612940576040516354e7e43160e11b81526001600160401b038c166004820152602401610914565b8b868151811061295257612952614e64565b602002602001015160000151600014612989578b868151811061297757612977614e64565b60209081029190910101515160808501525b506129fb565b60008260038111156129a3576129a36140b8565b146129fb57825160600151604080516001600160401b03808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612ca5565b8251608001516001600160401b031615612ad1576000826003811115612a2357612a236140b8565b03612ad15782516080015160208401516040516370701e5760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a81928f929190600401615af8565b6020604051808303816000875af1158015612aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac49190615627565b612ad15750505050612ca5565b60008c604001518681518110612ae957612ae9614e64565b6020026020010151905080518460a001515114612b3357835160600151604051631cfe6d8b60e01b81526001600160401b03808e1660048301529091166024820152604401610914565b612b478b85600001516060015160016135e4565b600080612b55868486613689565b91509150612b6c8d876000015160600151846135e4565b8b15612bc3576003826003811115612b8657612b866140b8565b03612bc3576000856003811115612b9f57612b9f6140b8565b14612bc357855151604051632b11b8d960e01b815261091491908390600401615b24565b6002826003811115612bd757612bd76140b8565b14612c18576003826003811115612bf057612bf06140b8565b14612c18578551606001516040516349362d1f60e11b8152610914918f918590600401615b3d565b8560000151600001518660000151606001516001600160401b03168e6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612c7057612c70614e64565b602002602001015186865a612c85908f614eca565b604051612c959493929190615b62565b60405180910390a4505050505050505b6001016127e4565b5050505050505050565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5f9190615b99565b90506001600160a01b0381161580612d8e5750612d8c6001600160a01b03821663aff2afbf60e01b611bdd565b155b15612db75760405163ae9b4ce960e01b81526001600160a01b0382166004820152602401610914565b600080612dcf88858c6040015163ffffffff1661373d565b915091506000806000612e826040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b815250604051602401612e4c9190615bb6565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613822565b92509250925082612eaa578582604051634ff17cad60e11b8152600401610914929190615c82565b8151602014612ed9578151604051631e3be00960e21b8152602060048201526024810191909152604401610914565b600082806020019051810190612eef9190615ca4565b9050866001600160a01b03168c6001600160a01b031614612f6b576000612f208d8a612f1b868a614eca565b61373d565b50905086811080612f3a575081612f378883614eca565b14155b15612f695760405163a966e21f60e01b8152600481018390526024810188905260448101829052606401610914565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612fac826301ffc9a760e01b612fcc565b80156107dc5750612fc5826001600160e01b0319612fcc565b1592915050565b6040516001600160e01b031982166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d9150600051905082801561303f575060208210155b801561304b5750600081115b979650505050505050565b8251600090815b81811015612cad57600060018886846020811061307c5761307c614e64565b61308991901a601b6159d3565b89858151811061309b5761309b614e64565b60200260200101518986815181106130b5576130b5614e64565b6020026020010151604051600081526020016040526040516130f3949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015613115573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115613176576131766140b8565b6002811115613187576131876140b8565b90525090506001816020015160028111156131a4576131a46140b8565b146131c257604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b8516156131ec57604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b85179450505080600101905061305d565b60005b8151811015610a715760ff83166000908152600360205260408120835190919084908490811061323e5761323e614e64565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161320c565b60005b82518110156115a857600083828151811061329257613292614e64565b60200260200101519050600060028111156132af576132af6140b8565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156132ee576132ee6140b8565b1461330f576004604051631b3fab5160e11b81526004016109149190615a10565b6001600160a01b0381166133365760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561335c5761335c6140b8565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156133b9576133b96140b8565b021790555090505050806001019050613275565b60ff818116600081815260026020526040902060010154620100009004909116906134255780613410576040516317bd8dd160e11b815260040160405180910390fd5b600b805467ffffffffffffffff191690555050565b60001960ff8316016115ec5780156115ec576040516307b8c74d60e51b815260040160405180910390fd5b6000818152600183016020526040812054613497575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107dc565b5060006107dc565b81518051606080850151908301516080808701519401516040516000958695889561350395919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016135469190615d5e565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b6000806135b58585856138fc565b6001600160401b0387166000908152600a6020908152604080832093835292905220549150505b949350505050565b600060026135f3608085614ef3565b6001600160401b03166136069190614f19565b9050600061361485856118bc565b90508161362360016004614eca565b901b19168183600381111561363a5761363a6140b8565b6001600160401b03871660009081526009602052604081209190921b92909217918291613668608088615939565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c20906136b690889088908890600401615df5565b600060405180830381600087803b1580156136d057600080fd5b505af19250505080156136e1575060015b613720573d80801561370f576040519150601f19603f3d011682016040523d82523d6000602084013e613714565b606091505b50600392509050613735565b50506040805160208101909152600081526002905b935093915050565b600080600080600061379e8860405160240161376891906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613822565b925092509250826137c6578682604051634ff17cad60e11b8152600401610914929190615c82565b60208251146137f5578151604051631e3be00960e21b8152602060048201526024810191909152604401610914565b818060200190518101906138099190615ca4565b6138138288614eca565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561384457613844613c3c565b6040519080825280601f01601f19166020018201604052801561386e576020820181803683370190505b509150863b6138885763030ed58f60e21b60005260046000fd5b5a858110156138a257632be8ca8b60e21b60005260046000fd5b85900360408104810387106138c2576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156138e55750835b808352806000602085013e50955095509592505050565b825182516000919081830361392457604051630469ac9960e21b815260040160405180910390fd5b610101821180159061393857506101018111155b613955576040516309bde33960e01b815260040160405180910390fd5b6000198282010161010081111561397f576040516309bde33960e01b815260040160405180910390fd5b806000036139ac578660008151811061399a5761399a614e64565b60200260200101519350505050613b7a565b6000816001600160401b038111156139c6576139c6613c3c565b6040519080825280602002602001820160405280156139ef578160200160208202803683370190505b50905060008080805b85811015613b195760006001821b8b811603613a535788851015613a3c578c5160018601958e918110613a2d57613a2d614e64565b60200260200101519050613a75565b8551600185019487918110613a2d57613a2d614e64565b8b5160018401938d918110613a6a57613a6a614e64565b602002602001015190505b600089861015613aa5578d5160018701968f918110613a9657613a96614e64565b60200260200101519050613ac7565b8651600186019588918110613abc57613abc614e64565b602002602001015190505b82851115613ae8576040516309bde33960e01b815260040160405180910390fd5b613af28282613b81565b878481518110613b0457613b04614e64565b602090810291909101015250506001016139f8565b506001850382148015613b2b57508683145b8015613b3657508581145b613b53576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613b6857613b68614e64565b60200260200101519750505050505050505b9392505050565b6000818310613b9957613b948284613b9f565b6107d9565b6107d983835b604080516001602082015290810183905260608101829052600090608001613589565b828054828255906000526020600020908101928215613c17579160200282015b82811115613c1757825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613be2565b50613c23929150613c27565b5090565b5b80821115613c235760008155600101613c28565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613c7457613c74613c3c565b60405290565b60405160a081016001600160401b0381118282101715613c7457613c74613c3c565b60405160c081016001600160401b0381118282101715613c7457613c74613c3c565b604080519081016001600160401b0381118282101715613c7457613c74613c3c565b604051606081016001600160401b0381118282101715613c7457613c74613c3c565b604051601f8201601f191681016001600160401b0381118282101715613d2a57613d2a613c3c565b604052919050565b60006001600160401b03821115613d4b57613d4b613c3c565b5060051b60200190565b6001600160a01b038116811461052f57600080fd5b80356001600160401b0381168114613d8157600080fd5b919050565b801515811461052f57600080fd5b8035613d8181613d86565b60006001600160401b03821115613db857613db8613c3c565b50601f01601f191660200190565b600082601f830112613dd757600080fd5b8135613dea613de582613d9f565b613d02565b818152846020838601011115613dff57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613e2f57600080fd5b82356001600160401b0380821115613e4657600080fd5b818501915085601f830112613e5a57600080fd5b8135613e68613de582613d32565b81815260059190911b83018401908481019088831115613e8757600080fd5b8585015b83811015613f2d57803585811115613ea35760008081fd5b86016080818c03601f1901811315613ebb5760008081fd5b613ec3613c52565b89830135613ed081613d55565b81526040613edf848201613d6a565b8b830152606080850135613ef281613d86565b83830152928401359289841115613f0b57600091508182fd5b613f198f8d86880101613dc6565b908301525085525050918601918601613e8b565b5098975050505050505050565b60005b83811015613f55578181015183820152602001613f3d565b50506000910152565b60008151808452613f76816020860160208601613f3a565b601f01601f19169290920160200192915050565b6020815260006107d96020830184613f5e565b6001600160a01b0381511682526020810151151560208301526001600160401b03604082015116604083015260006060820151608060608501526135dc6080850182613f5e565b604080825283519082018190526000906020906060840190828701845b828110156140265781516001600160401b031684529284019290840190600101614001565b50505083810382850152845180825282820190600581901b8301840187850160005b8381101561407657601f19868403018552614064838351613f9d565b94870194925090860190600101614048565b50909998505050505050505050565b6000806040838503121561409857600080fd5b6140a183613d6a565b91506140af60208401613d6a565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106140de576140de6140b8565b9052565b602081016107dc82846140ce565b600060a0828403121561410257600080fd5b61410a613c7a565b90508135815261411c60208301613d6a565b602082015261412d60408301613d6a565b604082015261413e60608301613d6a565b606082015261414f60808301613d6a565b608082015292915050565b8035613d8181613d55565b803563ffffffff81168114613d8157600080fd5b600082601f83011261418a57600080fd5b8135602061419a613de583613d32565b82815260059290921b840181019181810190868411156141b957600080fd5b8286015b848110156142895780356001600160401b03808211156141dd5760008081fd5b9088019060a0828b03601f19018113156141f75760008081fd5b6141ff613c7a565b87840135838111156142115760008081fd5b61421f8d8a83880101613dc6565b82525060408085013561423181613d55565b828a01526060614242868201614165565b8284015260809150818601358581111561425c5760008081fd5b61426a8f8c838a0101613dc6565b91840191909152509190930135908301525083529183019183016141bd565b509695505050505050565b600061014082840312156142a757600080fd5b6142af613c9c565b90506142bb83836140f0565b815260a08201356001600160401b03808211156142d757600080fd5b6142e385838601613dc6565b602084015260c08401359150808211156142fc57600080fd5b61430885838601613dc6565b604084015261431960e0850161415a565b6060840152610100840135608084015261012084013591508082111561433e57600080fd5b5061434b84828501614179565b60a08301525092915050565b600082601f83011261436857600080fd5b81356020614378613de583613d32565b82815260059290921b8401810191818101908684111561439757600080fd5b8286015b848110156142895780356001600160401b038111156143ba5760008081fd5b6143c88986838b0101614294565b84525091830191830161439b565b600082601f8301126143e757600080fd5b813560206143f7613de583613d32565b82815260059290921b8401810191818101908684111561441657600080fd5b8286015b848110156142895780356001600160401b038082111561443957600080fd5b818901915089603f83011261444d57600080fd5b8582013561445d613de582613d32565b81815260059190911b830160400190878101908c83111561447d57600080fd5b604085015b838110156144b65780358581111561449957600080fd5b6144a88f6040838a0101613dc6565b845250918901918901614482565b5087525050509284019250830161441a565b600082601f8301126144d957600080fd5b813560206144e9613de583613d32565b8083825260208201915060208460051b87010193508684111561450b57600080fd5b602086015b848110156142895780358352918301918301614510565b600082601f83011261453857600080fd5b81356020614548613de583613d32565b82815260059290921b8401810191818101908684111561456757600080fd5b8286015b848110156142895780356001600160401b038082111561458b5760008081fd5b9088019060a0828b03601f19018113156145a55760008081fd5b6145ad613c7a565b6145b8888501613d6a565b8152604080850135848111156145ce5760008081fd5b6145dc8e8b83890101614357565b8a84015250606080860135858111156145f55760008081fd5b6146038f8c838a01016143d6565b838501525060809150818601358581111561461e5760008081fd5b61462c8f8c838a01016144c8565b918401919091525091909301359083015250835291830191830161456b565b6000806040838503121561465e57600080fd5b6001600160401b038335111561467357600080fd5b6146808484358501614527565b91506001600160401b036020840135111561469a57600080fd5b6020830135830184601f8201126146b057600080fd5b6146bd613de58235613d32565b81358082526020808301929160051b8401018710156146db57600080fd5b602083015b6020843560051b850101811015614881576001600160401b038135111561470657600080fd5b87603f82358601011261471857600080fd5b61472b613de56020833587010135613d32565b81358501602081810135808452908301929160059190911b016040018a101561475357600080fd5b604083358701015b83358701602081013560051b01604001811015614871576001600160401b038135111561478757600080fd5b833587018135016040818d03603f190112156147a257600080fd5b6147aa613cbe565b604082013581526001600160401b03606083013511156147c957600080fd5b8c605f6060840135840101126147de57600080fd5b60406060830135830101356147f5613de582613d32565b808282526020820191508f60608460051b606088013588010101111561481a57600080fd5b6060808601358601015b60608460051b6060880135880101018110156148515761484381614165565b835260209283019201614824565b50806020850152505050808552505060208301925060208101905061475b565b50845250602092830192016146e0565b508093505050509250929050565b60008083601f8401126148a157600080fd5b5081356001600160401b038111156148b857600080fd5b6020830191508360208260051b85010111156148d357600080fd5b9250929050565b6000806000806000606086880312156148f257600080fd5b85356001600160401b038082111561490957600080fd5b61491589838a01614294565b9650602088013591508082111561492b57600080fd5b61493789838a0161488f565b9096509450604088013591508082111561495057600080fd5b5061495d8882890161488f565b969995985093965092949392505050565b60006080828403121561498057600080fd5b614988613c52565b823561499381613d55565b81526149a160208401614165565b602082015260408301356149b481613d86565b604082015260608301356149c781613d55565b60608201529392505050565b6000602082840312156149e557600080fd5b81356001600160401b038111156149fb57600080fd5b820160a08185031215613b7a57600080fd5b803560ff81168114613d8157600080fd5b600060208284031215614a3057600080fd5b6107d982614a0d565b60008151808452602080850194506020840160005b83811015614a735781516001600160a01b031687529582019590820190600101614a4e565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614acd60e0840182614a39565b90506040840151601f198483030160c0850152614aea8282614a39565b95945050505050565b60008060408385031215614b0657600080fd5b614b0f83613d6a565b946020939093013593505050565b80604081018310156107dc57600080fd5b60008083601f840112614b4057600080fd5b5081356001600160401b03811115614b5757600080fd5b6020830191508360208285010111156148d357600080fd5b60008060008060008060008060c0898b031215614b8b57600080fd5b614b958a8a614b1d565b975060408901356001600160401b0380821115614bb157600080fd5b614bbd8c838d01614b2e565b909950975060608b0135915080821115614bd657600080fd5b614be28c838d0161488f565b909750955060808b0135915080821115614bfb57600080fd5b50614c088b828c0161488f565b999c989b50969995989497949560a00135949350505050565b600060208284031215614c3357600080fd5b6107d982613d6a565b6020815260006107d96020830184613f9d565b600060208284031215614c6157600080fd5b8135613b7a81613d55565b600080600060608486031215614c8157600080fd5b614c8b8585614b1d565b925060408401356001600160401b03811115614ca657600080fd5b614cb286828701614b2e565b9497909650939450505050565b600082601f830112614cd057600080fd5b81356020614ce0613de583613d32565b8083825260208201915060208460051b870101935086841115614d0257600080fd5b602086015b84811015614289578035614d1a81613d55565b8352918301918301614d07565b60006020808385031215614d3a57600080fd5b82356001600160401b0380821115614d5157600080fd5b818501915085601f830112614d6557600080fd5b8135614d73613de582613d32565b81815260059190911b83018401908481019088831115614d9257600080fd5b8585015b83811015613f2d57803585811115614dad57600080fd5b860160c0818c03601f19011215614dc45760008081fd5b614dcc613c9c565b8882013581526040614ddf818401614a0d565b8a8301526060614df0818501614a0d565b8284015260809150614e03828501613d94565b9083015260a08381013589811115614e1b5760008081fd5b614e298f8d83880101614cbf565b838501525060c0840135915088821115614e435760008081fd5b614e518e8c84870101614cbf565b9083015250845250918601918601614d96565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614e8e57607f821691505b602082108103614eae57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156107dc576107dc614eb4565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b0380841680614f0d57614f0d614edd565b92169190910692915050565b80820281158282048414176107dc576107dc614eb4565b80518252600060206001600160401b0381840151168185015260408084015160a06040870152614f6360a0870182613f5e565b905060608501518682036060880152614f7c8282613f5e565b608087810151898303918a01919091528051808352908601935060009250908501905b80831015614fd157835180516001600160a01b0316835286015186830152928501926001929092019190840190614f9f565b50979650505050505050565b6020815260006107d96020830184614f30565b6080815260006150036080830187614f30565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561504157600080fd5b835161504c81613d86565b60208501519093506001600160401b0381111561506857600080fd5b8401601f8101861361507957600080fd5b8051615087613de582613d9f565b81815287602083850101111561509c57600080fd5b6150ad826020830160208601613f3a565b809450505050604084015190509250925092565b80356001600160e01b0381168114613d8157600080fd5b600082601f8301126150e957600080fd5b813560206150f9613de583613d32565b82815260069290921b8401810191818101908684111561511857600080fd5b8286015b8481101561428957604081890312156151355760008081fd5b61513d613cbe565b61514682613d6a565b81526151538583016150c1565b8186015283529183019160400161511c565b600082601f83011261517657600080fd5b81356020615186613de583613d32565b82815260059290921b840181019181810190868411156151a557600080fd5b8286015b848110156142895780356001600160401b03808211156151c95760008081fd5b9088019060a0828b03601f19018113156151e35760008081fd5b6151eb613c7a565b6151f6888501613d6a565b81526040808501358481111561520c5760008081fd5b61521a8e8b83890101613dc6565b8a840152506060935061522e848601613d6a565b90820152608061523f858201613d6a565b938201939093529201359082015283529183019183016151a9565b600082601f83011261526b57600080fd5b8135602061527b613de583613d32565b82815260069290921b8401810191818101908684111561529a57600080fd5b8286015b8481101561428957604081890312156152b75760008081fd5b6152bf613cbe565b81358152848201358582015283529183019160400161529e565b600060208083850312156152ec57600080fd5b82356001600160401b038082111561530357600080fd5b908401906060828703121561531757600080fd5b61531f613ce0565b82358281111561532e57600080fd5b8301604081890381131561534157600080fd5b615349613cbe565b82358581111561535857600080fd5b8301601f81018b1361536957600080fd5b8035615377613de582613d32565b81815260069190911b8201890190898101908d83111561539657600080fd5b928a01925b828410156153e65785848f0312156153b35760008081fd5b6153bb613cbe565b84356153c681613d55565b81526153d3858d016150c1565b818d0152825292850192908a019061539b565b8452505050828701359150848211156153fe57600080fd5b61540a8a8385016150d8565b8188015283525050828401358281111561542357600080fd5b61542f88828601615165565b8583015250604083013593508184111561544857600080fd5b6154548785850161525a565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156154f457601f19868403018952815160a06001600160401b038083511686528683015182888801526154b883880182613f5e565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615480565b5090979650505050505050565b6001600160a01b0384168152600060206060818401526155246060840186615463565b83810360408581019190915285518083528387019284019060005b818110156140765784518051845286015186840152938501939183019160010161553f565b805160408084528151848201819052600092602091908201906060870190855b818110156155bb57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615584565b50508583015187820388850152805180835290840192506000918401905b80831015614fd157835180516001600160401b031683528501516001600160e01b0316858301529284019260019290920191908501906155d9565b6020815260006107d96020830184615564565b60006020828403121561563957600080fd5b8151613b7a81613d86565b600080835461565281614e7a565b6001828116801561566a576001811461567f576156ae565b60ff19841687528215158302870194506156ae565b8760005260208060002060005b858110156156a55781548a82015290840190820161568c565b50505082870194505b50929695505050505050565b600081546156c781614e7a565b8085526020600183811680156156e457600181146156fe5761572c565b60ff1985168884015283151560051b88018301955061572c565b866000528260002060005b858110156157245781548a8201860152908301908401615709565b890184019650505b505050505092915050565b60408152600061574a6040830185613f5e565b8281036020840152614aea81856156ba565b6001600160401b0381811683821601908082111561577c5761577c614eb4565b5092915050565b6040815260006157966040830185615463565b8281036020840152614aea8185615564565b6000602082840312156157ba57600080fd5b81356001600160401b038111156157d057600080fd5b6135dc84828501614527565b601f821115610a71576000816000526020600020601f850160051c810160208610156158055750805b601f850160051c820191505b8181101561582457828155600101615811565b505050505050565b81516001600160401b0381111561584557615845613c3c565b615859816158538454614e7a565b846157dc565b602080601f83116001811461588e57600084156158765750858301515b600019600386901b1c1916600185901b178555615824565b600085815260208120601f198616915b828110156158bd5788860151825594840194600190910190840161589e565b50858210156158db5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c166060840152506080808301526107d960a08301600185016156ba565b60006001600160401b038084168061595357615953614edd565b92169190910492915050565b60006020828403121561597157600080fd5b6107d982614165565b6000808335601e1984360301811261599157600080fd5b8301803591506001600160401b038211156159ab57600080fd5b6020019150368190038213156148d357600080fd5b808201808211156107dc576107dc614eb4565b60ff81811683821601908111156107dc576107dc614eb4565b8183823760009101908152919050565b828152604082602083013760600192915050565b6020810160068310615a2457615a246140b8565b91905290565b60ff818116838216029081169081811461577c5761577c614eb4565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a9e5784546001600160a01b031683526001948501949284019201615a79565b50508481036060860152865180825290820192508187019060005b81811015615ade5782516001600160a01b031685529383019391830191600101615ab9565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b03808616835280851660208401525060606040830152614aea6060830184613f5e565b8281526040602082015260006135dc6040830184613f5e565b6001600160401b03848116825283166020820152606081016135dc60408301846140ce565b848152615b7260208201856140ce565b608060408201526000615b886080830185613f5e565b905082606083015295945050505050565b600060208284031215615bab57600080fd5b8151613b7a81613d55565b6020815260008251610100806020850152615bd5610120850183613f5e565b91506020850151615bf160408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c2b60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c488483613f5e565b935060c08701519150808685030160e0870152615c658483613f5e565b935060e0870151915080868503018387015250615aee8382613f5e565b6001600160a01b03831681526040602082015260006135dc6040830184613f5e565b600060208284031215615cb657600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b848110156154f457601f19868403018952815160a08151818652615d0082870182613f5e565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615d3c8382613f5e565b6080948501519790940196909652505098840198925090830190600101615cda565b6020815260006107d96020830184615cbd565b60008282518085526020808601955060208260051b8401016020860160005b848110156154f457601f19868403018952615dac838351613f5e565b98840198925090830190600101615d90565b60008151808452602080850194506020840160005b83811015614a7357815163ffffffff1687529582019590820190600101615dd3565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615e5d6101a0850183613f5e565b91506040870151605f198086850301610120870152615e7c8483613f5e565b935060608901519150615e99838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615ec28282615cbd565b9150508281036020840152615ed78186615d71565b90508281036040840152615aee8185615dbe56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -560,27 +560,27 @@ func (_OffRamp *OffRampTransactorSession) ApplySourceChainConfigUpdates(sourceCh return _OffRamp.Contract.ApplySourceChainConfigUpdates(&_OffRamp.TransactOpts, sourceChainConfigUpdates) } -func (_OffRamp *OffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "commit", reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampSession) Commit(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampTransactorSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactorSession) Commit(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "execute", reportContext, report) } -func (_OffRamp *OffRampSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampSession) Execute(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) } -func (_OffRamp *OffRampTransactorSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactorSession) Execute(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) } @@ -2505,9 +2505,9 @@ type OffRampInterface interface { ApplySourceChainConfigUpdates(opts *bind.TransactOpts, sourceChainConfigUpdates []OffRampSourceChainConfigArgs) (*types.Transaction, error) - Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + Commit(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) + Execute(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index ded2c5431da..dd2799ba810 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 @@ -14,9 +14,9 @@ mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMesse mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin c3cac2010c2815b484055bf981363a2bd04e7fbe7bb502dc8fd29a16165d221c -multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 79bfbd1f7d3c2aeee6301ae1275c39924a0b41f16b051d1c0046d3fc4265093d +multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin a523e11ea4c069d7d61b309c156951cc6834aff0f352bd1ac37c3a838ff2588f nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin e6008490d916826cefd1903612db39621d51617300fc9bb42b68c6c117958198 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin bcfd30c5dae4bd5b064822ada47efef8f7364b1ea60e622549aed5cb97ee1f70 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 7c65e586181c5099a6ecb5353f60043bb6add9ebad941ddf7ef9998c7ee008ea onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 2bf74188a997218502031f177cb2df505b272d66b25fd341a741289e77380c59 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 24b4415a883a470d65c484be0fa20714a46b1c9262db205f1c958017820307b2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 0fc277a0b512db4e20b5a32a775b94ed2c0d342d8237511de78c94f7dacad428 diff --git a/core/services/keystore/keys/ocr2key/evm_keyring.go b/core/services/keystore/keys/ocr2key/evm_keyring.go index 5d937e36a6e..554d655443d 100644 --- a/core/services/keystore/keys/ocr2key/evm_keyring.go +++ b/core/services/keystore/keys/ocr2key/evm_keyring.go @@ -60,7 +60,7 @@ func (ekr *evmKeyring) reportToSigData3(digest types.ConfigDigest, seqNr uint64, func RawReportContext3(digest types.ConfigDigest, seqNr uint64) [2][32]byte { seqNrBytes := [32]byte{} - binary.BigEndian.PutUint64(seqNrBytes[:], seqNr) + binary.BigEndian.PutUint64(seqNrBytes[24:], seqNr) return [2][32]byte{ digest, seqNrBytes, diff --git a/core/services/keystore/keys/ocr2key/evm_keyring_test.go b/core/services/keystore/keys/ocr2key/evm_keyring_test.go index 20ac197159a..85dad74eb88 100644 --- a/core/services/keystore/keys/ocr2key/evm_keyring_test.go +++ b/core/services/keystore/keys/ocr2key/evm_keyring_test.go @@ -3,6 +3,7 @@ package ocr2key import ( "bytes" cryptorand "crypto/rand" + "math" "math/rand" "testing" @@ -96,3 +97,66 @@ func TestEVMKeyring_Marshalling(t *testing.T) { // Invalid seed size should error assert.Error(t, kr2.Unmarshal([]byte{0x01})) } + +func TestRawReportContext3(t *testing.T) { + testCases := []struct { + name string + digest [32]byte + seqNr uint64 + expected [2][32]byte + }{ + { + name: "zero values", + digest: [32]byte{}, + seqNr: 0, + expected: [2][32]byte{ + {}, + {}, + }, + }, + { + name: "some digest", + digest: [32]byte{1, 2, 3}, + seqNr: 0, + expected: [2][32]byte{ + {1, 2, 3}, + {}, + }, + }, + { + name: "sequence number set to 1", + digest: [32]byte{}, + seqNr: 1, + expected: [2][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, 1, + }, + }, + }, + { + name: "sequence number set to max uint64", + digest: [32]byte{1, 2, 3}, + seqNr: math.MaxUint64, + expected: [2][32]byte{ + {1, 2, 3}, + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := RawReportContext3(tc.digest, tc.seqNr) + assert.Equal(t, tc.expected, actual, "unexpected result") + }) + } +} From 35c2f05853ea1ba28be2c74941674289943b2fe6 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Thu, 5 Dec 2024 06:46:32 -0600 Subject: [PATCH 13/55] follow up the chain selector refactor for CCIP plugin, fix potential bug in CR/CW config (#15482) * fix chain family logic * add changeset --- .changeset/breezy-kings-clean.md | 5 +++++ core/capabilities/ccip/oraclecreator/plugin.go | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 .changeset/breezy-kings-clean.md diff --git a/.changeset/breezy-kings-clean.md b/.changeset/breezy-kings-clean.md new file mode 100644 index 00000000000..b72a0689019 --- /dev/null +++ b/.changeset/breezy-kings-clean.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Potential bug introduced from chain selector refactor, not causing issue now since only EVM is used, but need to fix #bugfix diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 6b63491f8e6..f8868b5d9b9 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -299,7 +299,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( pluginType cctypes.PluginType, config cctypes.OCR3ConfigWithMeta, publicCfg ocr3confighelper.PublicConfig, - chainFamily string, + destChainFamily string, ) ( map[cciptypes.ChainSelector]types.ContractReader, map[cciptypes.ChainSelector]types.ContractWriter, @@ -328,8 +328,8 @@ func (i *pluginOracleCreator) createReadersAndWriters( chainWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) for relayID, relayer := range i.relayers { chainID := relayID.ChainID - - chainSelector, err1 := i.getChainSelector(chainID, chainFamily) + relayChainFamily := relayID.Network + chainSelector, err1 := i.getChainSelector(chainID, relayChainFamily) if err1 != nil { return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s: %w", chainID, err1) } @@ -344,7 +344,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } - if chainID == destChainID { + if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddressHex := common.BytesToAddress(config.Config.OfframpAddress).Hex() err2 := cr.Bind(ctx, []types.BoundContract{ { @@ -367,7 +367,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( relayer, i.transmitters, execBatchGasLimit, - chainFamily) + relayChainFamily) if err1 != nil { return nil, nil, err1 } From 98c46becc2870bbb58c89b722e213c0271152622 Mon Sep 17 00:00:00 2001 From: Pablo Estrada <139084212+ecPablo@users.noreply.github.com> Date: Thu, 5 Dec 2024 07:15:44 -0600 Subject: [PATCH 14/55] chore: add deployment automation team as code owner of the deployment/ module (#15522) --- .github/CODEOWNERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 210709443be..ef1c0f98913 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -139,8 +139,7 @@ core/scripts/gateway @smartcontractkit/dev-services /integration-tests/**/*ccip* @smartcontractkit/ccip-offchain @smartcontractkit/core # Deployment tooling -# Initially the common structures owned by CCIP -/deployment @smartcontractkit/ccip @smartcontractkit/keystone @smartcontractkit/core +/deployment @smartcontractkit/ccip @smartcontractkit/keystone @smartcontractkit/core @smartcontractkit/deployment-automation /deployment/ccip @smartcontractkit/ccip @smartcontractkit/core /deployment/keystone @smartcontractkit/keystone @smartcontractkit/core # TODO: As more products add their deployment logic here, add the team as an owner From d2cb377507b5133f0294ed584dd460bfcb8ed970 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Thu, 5 Dec 2024 15:18:04 +0100 Subject: [PATCH 15/55] [TT-1806] apply chain.link label changes (#15484) * apply chain.link label changes * gomodtidy * fix lint * fix load's go.mod --- .github/workflows/automation-benchmark-tests.yml | 7 ++++++- .github/workflows/automation-load-tests.yml | 9 +++++++-- .github/workflows/automation-ondemand-tests.yml | 9 +++++++-- .github/workflows/ccip-chaos-tests.yml | 9 ++++++++- .github/workflows/ccip-load-tests.yml | 10 ++++++++-- .github/workflows/integration-tests.yml | 6 ++++-- .github/workflows/on-demand-ocr-soak-test.yml | 9 +++++++-- integration-tests/.tool-versions | 2 +- integration-tests/benchmark/automation_test.go | 14 +++++++++++--- integration-tests/ccip-tests/testsetups/ccip.go | 11 +++++++++++ integration-tests/chaos/automation_chaos_test.go | 9 +++++++++ integration-tests/chaos/ocr_chaos_test.go | 11 ++++++++++- integration-tests/example.env | 2 ++ integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- .../load/automationv2_1/automationv2_1_test.go | 9 +++++++++ integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- integration-tests/testsetups/ocr.go | 10 ++++++++++ 19 files changed, 116 insertions(+), 23 deletions(-) diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml index 9a4a127dede..3a826f523a0 100644 --- a/.github/workflows/automation-benchmark-tests.yml +++ b/.github/workflows/automation-benchmark-tests.yml @@ -20,17 +20,22 @@ on: required: true default: benchmark type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_ids: '${{ inputs.testType }}/automation_test.go:TestAutomationBenchmark' test_config_override_path: ${{ inputs.test_config_override_path }} SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index 24c7017ee9a..c11e353a7db 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -14,18 +14,23 @@ on: description: Notifies test results (Not your @) required: true default: U02Q14G80TY - type: string + type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_ids: 'load/automationv2_1/automationv2_1_test.go:TestLogTrigger' test_config_override_path: ${{ inputs.test_config_override_path }} SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index c72715bf9db..eef02dcddb2 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -38,7 +38,11 @@ on: with_existing_remote_runner_version: description: 'Tag of the existing remote runner version to use (Leave empty to build from head/ref)' required: false - type: string + type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: # Set tests to run based on the workflow inputs @@ -153,7 +157,7 @@ jobs: call-run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_list: ${{ needs.set-tests-to-run.outputs.test_list }} @@ -161,6 +165,7 @@ jobs: with_existing_remote_runner_version: ${{ github.event.inputs.with_existing_remote_runner_version }} test_log_upload_on_failure: true test_log_upload_retention_days: 7 + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/ccip-chaos-tests.yml b/.github/workflows/ccip-chaos-tests.yml index 36c99410c37..51e6c6f027a 100644 --- a/.github/workflows/ccip-chaos-tests.yml +++ b/.github/workflows/ccip-chaos-tests.yml @@ -6,6 +6,12 @@ on: # types: [ completed ] # branches: [ develop ] workflow_dispatch: + inputs: + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + default: "ccip" + type: string # Only run 1 of this workflow at a time per PR concurrency: @@ -15,7 +21,7 @@ concurrency: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml chainlink_version: ${{ github.sha }} @@ -25,6 +31,7 @@ jobs: slack_notification_after_tests: on_failure slack_notification_after_tests_channel_id: '#ccip-testing' slack_notification_after_tests_name: CCIP Chaos E2E Tests + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/ccip-load-tests.yml b/.github/workflows/ccip-load-tests.yml index 4f5b7ac509c..d1733147443 100644 --- a/.github/workflows/ccip-load-tests.yml +++ b/.github/workflows/ccip-load-tests.yml @@ -21,7 +21,12 @@ on: chainlink_version: description: Chainlink image version to use. Commit sha if not provided required: false - type: string + type: string + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + default: "ccip" + type: string # Only run 1 of this workflow at a time per PR concurrency: @@ -31,7 +36,7 @@ concurrency: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_trigger: E2E CCIP Load Tests @@ -41,6 +46,7 @@ jobs: slack_notification_after_tests_channel_id: '#ccip-testing' slack_notification_after_tests_name: CCIP E2E Load Tests test_image_suites: ccip-load + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 63f9949e821..bac453eb044 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -296,7 +296,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'pull_request' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: workflow_name: Run CCIP E2E Tests For PR chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -306,6 +306,7 @@ jobs: upload_cl_node_coverage_artifact: true upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + team: "CCIP" secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -337,7 +338,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'merge_group' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: workflow_name: Run CCIP E2E Tests For Merge Queue chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -347,6 +348,7 @@ jobs: upload_cl_node_coverage_artifact: true upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} + team: "CCIP" secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index ac97d3c6355..a9a8c3c2a2f 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -34,18 +34,23 @@ on: slackMemberID: description: Slack Member ID (Not your @) required: true - default: U01A2B2C3D4 + default: U01A2B2C3D4 + team: + description: Team to run the tests for (e.g. BIX, CCIP) + required: true + type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 with: test_path: .github/e2e-tests.yml test_ids: ${{ inputs.testToRun}} test_config_override_path: ${{ inputs.test_config_override_path }} chainlink_version: ${{ inputs.chainlink_version }} SLACK_USER: ${{ inputs.slackMemberID }} + team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/integration-tests/.tool-versions b/integration-tests/.tool-versions index 5d980451979..3e44e439ff2 100644 --- a/integration-tests/.tool-versions +++ b/integration-tests/.tool-versions @@ -2,5 +2,5 @@ golang 1.23.3 k3d 5.4.6 kubectl 1.25.5 nodejs 20.13.1 -golangci-lint 1.61.1 +golangci-lint 1.62.0 task 3.35.1 diff --git a/integration-tests/benchmark/automation_test.go b/integration-tests/benchmark/automation_test.go index 0a63ff2c27a..c4a113a8d99 100644 --- a/integration-tests/benchmark/automation_test.go +++ b/integration-tests/benchmark/automation_test.go @@ -77,7 +77,7 @@ func TestAutomationBenchmark(t *testing.T) { config, err := tc.GetConfig([]string{testType}, tc.Automation) require.NoError(t, err, "Error getting test config") - testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, &config) + testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, testType, &config) if testEnvironment.WillUseRemoteRunner() { return } @@ -245,7 +245,7 @@ var networkConfig = map[string]NetworkConfig{ }, } -func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.AutomationBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { +func SetupAutomationBenchmarkEnv(t *testing.T, testType string, keeperTestConfig types.AutomationBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { l := logging.GetTestLogger(t) testNetwork := networks.MustGetSelectedNetworkConfig(keeperTestConfig.GetNetworkConfig())[0] // Environment currently being used to run benchmark test on blockTime := "1" @@ -259,6 +259,12 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.Automation networkName = strings.ReplaceAll(networkName, "_", "-") testNetwork.Name = networkName + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Keeper), testType) + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Keeper), testType) + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment.New(&environment.Config{ TTL: time.Hour * 720, // 30 days, NamespacePrefix: fmt.Sprintf( @@ -269,6 +275,9 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.Automation ), Test: t, PreventPodEviction: true, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, }) dbResources := dbResources @@ -316,7 +325,6 @@ func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.Automation }, })) } - var err error if testNetwork.Simulated { // TODO we need to update the image in CTF, the old one is not available anymore // deploy blockscout if running on simulated diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index 10ca0a971b8..fbfbc4c1ccd 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -37,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" integrationactions "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" @@ -1414,9 +1415,19 @@ func (o *CCIPTestSetUpOutputs) CreateEnvironment( } func createEnvironmentConfig(t *testing.T, envName string, testConfig *CCIPTestConfig, reportPath string) *environment.Config { + testType := testConfig.TestGroupInput.Type + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.CCIP), testType) + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.CCIP), testType) + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + envConfig := &environment.Config{ NamespacePrefix: envName, Test: t, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, // PreventPodEviction: true, //TODO: enable this once we have a way to handle pod eviction } if pointer.GetBool(testConfig.TestGroupInput.StoreLaneConfig) { diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index 73ae7c07378..80e4a46581e 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -197,11 +197,20 @@ func TestAutomationChaos(t *testing.T) { t.Parallel() network := networks.MustGetSelectedNetworkConfig(config.Network)[0] // Need a new copy of the network for each test + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Automation), "chaos") + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Automation), "chaos") + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment. New(&environment.Config{ NamespacePrefix: fmt.Sprintf("chaos-automation-%s", name), TTL: time.Hour * 1, Test: t, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, }). AddHelm(testCase.networkChart). AddHelm(testCase.clChart) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 41017d7eeb7..f072adcc46a 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -141,15 +141,24 @@ func TestOCRChaos(t *testing.T) { t.Run(fmt.Sprintf("OCR_%s", name), func(t *testing.T) { t.Parallel() + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels("data-feedsv1.0", "chaos") + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels("data-feedsv1.0", "chaos") + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment.New(&environment.Config{ NamespacePrefix: fmt.Sprintf("chaos-ocr-%s", name), Test: t, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, }). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). AddHelm(testCase.networkChart). AddHelm(testCase.clChart) - err := testEnvironment.Run() + err = testEnvironment.Run() require.NoError(t, err) if testEnvironment.WillUseRemoteRunner() { return diff --git a/integration-tests/example.env b/integration-tests/example.env index 35db6263644..fbc9a76091e 100644 --- a/integration-tests/example.env +++ b/integration-tests/example.env @@ -3,6 +3,7 @@ ########## General Test Settings ########## export CHAINLINK_ENV_USER="Satoshi-Nakamoto" # Name of the person running the tests (change to your own) +export CHAINLINK_USER_TEAM="My awesome team" # Name of the team you are running the test for (change to your own) export TEST_LOG_LEVEL="info" # info | debug | trace ########## Soak/Chaos/Load Test Specific Settings ########## @@ -16,6 +17,7 @@ export SLACK_API_KEY="xoxb-example-key" # API key used to report soak test resul export SLACK_CHANNEL="C000000000" # Channel ID for the slack bot to post test results export SLACK_USER="U000000000" # User ID of the person running the soak tests to properly notify them +##### ---- applicable only, when using legacy EVMClient ---- ##### ########## Network Settings ########## # General EVM Settings, used only for quick prototyping when using GENERAL as the SELECTED_NETWORK export EVM_NAME="General EVM" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 8d7bcec57b2..c9eced2ddfc 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -41,7 +41,7 @@ require ( github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 125e890aa25..272cc05e0a5 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1450,8 +1450,8 @@ github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2 github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 h1:a3xetGZh2nFO1iX5xd9OuqiCkgbWLvW6fTN6fgVubPo= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 65f1d21257a..823c1bd8825 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -196,6 +196,12 @@ Load Config: loadDuration := time.Duration(*loadedTestConfig.Automation.General.Duration) * time.Second automationDefaultLinkFunds := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(10000))) //10000 LINK + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Automation), testType) + require.NoError(t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Automation), testType) + require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") + testEnvironment := environment.New(&environment.Config{ TTL: loadDuration.Round(time.Hour) + time.Hour, NamespacePrefix: fmt.Sprintf( @@ -203,6 +209,9 @@ Load Config: testType, strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), ), + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, Test: t, PreventPodEviction: true, }) diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index b75a854daac..30eb132d24f 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -18,7 +18,7 @@ require ( github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 github.com/smartcontractkit/chainlink/deployment v0.0.0-20241120141814-47da13e86197 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 84833e7e665..5fbafb202bc 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1441,8 +1441,8 @@ github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2 github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 h1:a3xetGZh2nFO1iX5xd9OuqiCkgbWLvW6fTN6fgVubPo= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 69da49ae404..20e1b4bf158 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -160,11 +160,21 @@ func (o *OCRSoakTest) DeployEnvironment(ocrTestConfig tt.OcrTestConfig) { nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(nodeNetwork.Name), " ", "-")) nsPre = strings.ReplaceAll(nsPre, "_", "-") + productName := fmt.Sprintf("data-feedsv%s.0", o.OCRVersion) + nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(productName, "soak") + require.NoError(o.t, err, "Error creating required chain.link labels for namespace") + + workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(productName, "soak") + require.NoError(o.t, err, "Error creating required chain.link labels for workloads and pods") + baseEnvironmentConfig := &environment.Config{ TTL: time.Hour * 720, // 30 days, NamespacePrefix: nsPre, Test: o.t, PreventPodEviction: true, + Labels: nsLabels, + WorkloadLabels: workloadPodLabels, + PodLabels: workloadPodLabels, } testEnv := environment.New(baseEnvironmentConfig). From 138d4c51ad0d2b9bd6ac242b03b1849f14fa7f8f Mon Sep 17 00:00:00 2001 From: David Cauchi <13139524+davidcauchi@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:48:49 +0100 Subject: [PATCH 16/55] fix track config delay in ocr soak (#15144) * fix track config delay in ocr soak * Extracts link deployment * Replace bespoke retry logic * Update field name * go mod tidy --- integration-tests/actions/ocr2_helpers.go | 45 +++- integration-tests/go.mod | 2 +- integration-tests/testsetups/ocr.go | 267 +++++++++++++--------- 3 files changed, 210 insertions(+), 104 deletions(-) diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index 1d386b158a0..842395bb25b 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -4,12 +4,15 @@ import ( "crypto/ed25519" "encoding/hex" "fmt" + "net/http" "strings" "time" + "github.com/avast/retry-go" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/lib/pq" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" "gopkg.in/guregu/null.v4" @@ -192,6 +195,7 @@ func CreateOCRv2Jobs( mockServerValue int, // Value to get from the mock server when querying the path chainId int64, // EVM chain ID forwardingAllowed bool, + l zerolog.Logger, ) error { // Collect P2P ID bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() @@ -218,6 +222,9 @@ func CreateOCRv2Jobs( } } + // Initialize map to store job IDs for each chainlink node + jobIDs := make(map[*nodeclient.ChainlinkK8sClient][]string) + for _, ocrInstance := range ocrInstances { bootstrapSpec := &nodeclient.OCR2TaskJobSpec{ Name: fmt.Sprintf("ocr2-bootstrap-%s", ocrInstance.Address()), @@ -284,10 +291,46 @@ func CreateOCRv2Jobs( P2PV2Bootstrappers: pq.StringArray{p2pV2Bootstrapper}, // bootstrap node key and address @bootstrap:6690 }, } - _, err = chainlinkNode.MustCreateJob(ocrSpec) + var ocrJob *nodeclient.Job + ocrJob, err = chainlinkNode.MustCreateJob(ocrSpec) if err != nil { return fmt.Errorf("creating OCR task job on OCR node have failed: %w", err) } + jobIDs[chainlinkNode] = append(jobIDs[chainlinkNode], ocrJob.Data.ID) // Store each job ID per node + } + } + l.Info().Msg("Verify OCRv2 jobs have been created") + for chainlinkNode, ids := range jobIDs { + for _, jobID := range ids { + err := retry.Do( + func() error { + _, resp, err := chainlinkNode.ReadJob(jobID) + if err != nil { + return err + } + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("unexpected response status: %d", resp.StatusCode) + } + l.Info(). + Str("Node", chainlinkNode.PodName). + Str("Job ID", jobID). + Msg("OCRv2 job successfully created") + return nil + }, + retry.Attempts(4), + retry.Delay(time.Second*2), + retry.OnRetry(func(n uint, err error) { + l.Debug(). + Str("Node", chainlinkNode.PodName). + Str("Job ID", jobID). + Uint("Attempt", n+1). + Err(err). + Msg("Retrying job verification") + }), + ) + if err != nil { + l.Error().Err(err).Str("Node", chainlinkNode.PodName).Str("JobID", jobID).Msg("Failed to verify OCRv2 job creation") + } } } return nil diff --git a/integration-tests/go.mod b/integration-tests/go.mod index c9eced2ddfc..621c1c0941b 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -11,6 +11,7 @@ require ( dario.cat/mergo v1.0.1 github.com/AlekSi/pointer v1.1.0 github.com/Masterminds/semver/v3 v3.3.0 + github.com/avast/retry-go v3.0.0+incompatible github.com/avast/retry-go/v4 v4.6.0 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a @@ -102,7 +103,6 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect - github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.54.19 // indirect github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 20e1b4bf158..7a90c38fdd0 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -64,13 +64,14 @@ type OCRSoakTest struct { Config *tc.TestConfig TestReporter testreporters.OCRSoakTestReporter OperatorForwarderFlow bool - seth *seth.Client + sethClient *seth.Client OCRVersion string t *testing.T startTime time.Time timeLeft time.Duration startingBlockNum uint64 + startingValue int testEnvironment *environment.Environment namespace string log zerolog.Logger @@ -88,6 +89,8 @@ type OCRSoakTest struct { ocrV2Instances []contracts.OffchainAggregatorV2 ocrV2InstanceMap map[string]contracts.OffchainAggregatorV2 // address : instance + linkContract *contracts.EthereumLinkToken + rpcNetwork blockchain.EVMNetwork // network configuration for the blockchain node reorgHappened bool // flag to indicate if a reorg happened during the test gasSpikeSimulationHappened bool // flag to indicate if a gas spike simulation happened during the test @@ -280,107 +283,151 @@ func (o *OCRSoakTest) Environment() *environment.Environment { return o.testEnvironment } +// Setup initializes the OCR Soak Test by setting up clients, funding nodes, and deploying OCR contracts. func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { + o.initializeClients() + o.deployLinkTokenContract(ocrTestConfig) + o.fundChainlinkNodes() + + o.startingValue = 5 + + var forwarders []common.Address + if o.OperatorForwarderFlow { + _, forwarders = o.deployForwarderContracts() + } + + o.setupOCRContracts(ocrTestConfig, forwarders) + o.log.Info().Msg("OCR Soak Test Setup Complete") +} + +// initializeClients sets up the Seth client, Chainlink nodes, and mock server. +func (o *OCRSoakTest) initializeClients() { sethClient, err := seth_utils.GetChainClient(o.Config, o.rpcNetwork) require.NoError(o.t, err, "Error creating seth client") - o.seth = sethClient + o.sethClient = sethClient nodes, err := nodeclient.ConnectChainlinkNodes(o.testEnvironment) require.NoError(o.t, err, "Connecting to chainlink nodes shouldn't fail") o.bootstrapNode, o.workerNodes = nodes[0], nodes[1:] + o.mockServer = ctf_client.ConnectMockServer(o.testEnvironment) require.NoError(o.t, err, "Creating mockserver clients shouldn't fail") +} - linkContract, err := actions.LinkTokenContract(o.log, sethClient, ocrTestConfig.GetActiveOCRConfig()) +func (o *OCRSoakTest) deployLinkTokenContract(ocrTestConfig tt.OcrTestConfig) { + linkContract, err := actions.LinkTokenContract(o.log, o.sethClient, ocrTestConfig.GetActiveOCRConfig()) require.NoError(o.t, err, "Error loading/deploying link token contract") + o.linkContract = linkContract +} - // Fund Chainlink nodes, excluding the bootstrap node +// fundChainlinkNodes funds the Chainlink worker nodes. +func (o *OCRSoakTest) fundChainlinkNodes() { o.log.Info().Float64("ETH amount per node", *o.Config.Common.ChainlinkNodeFunding).Msg("Funding Chainlink nodes") - err = actions.FundChainlinkNodesFromRootAddress(o.log, sethClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) + err := actions.FundChainlinkNodesFromRootAddress(o.log, o.sethClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) require.NoError(o.t, err, "Error funding Chainlink nodes") +} - var forwarders []common.Address - if o.OperatorForwarderFlow { - var operators []common.Address - operators, forwarders, _ = actions.DeployForwarderContracts( - o.t, o.seth, common.HexToAddress(linkContract.Address()), len(o.workerNodes), - ) - require.Equal(o.t, len(o.workerNodes), len(operators), "Number of operators should match number of nodes") - require.Equal(o.t, len(o.workerNodes), len(forwarders), "Number of authorized forwarders should match number of nodes") - forwarderNodesAddresses, err := actions.ChainlinkNodeAddresses(o.workerNodes) - require.NoError(o.t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") - for i := range o.workerNodes { - actions.AcceptAuthorizedReceiversOperator( - o.t, o.log, o.seth, operators[i], forwarders[i], []common.Address{forwarderNodesAddresses[i]}) - require.NoError(o.t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions.TrackForwarder(o.t, o.seth, forwarders[i], o.workerNodes[i]) - } - } else if o.OCRVersion == "1" { - if o.OperatorForwarderFlow { - o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( - o.log, - o.seth, - o.Config.GetActiveOCRConfig(), - common.HexToAddress(linkContract.Address()), - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), - forwarders, - ) - require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") - } else { - o.ocrV1Instances, err = actions.SetupOCRv1Contracts( - o.log, - sethClient, - o.Config.GetActiveOCRConfig(), - common.HexToAddress(linkContract.Address()), - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), - ) - require.NoError(o.t, err) - } - } else if o.OCRVersion == "2" { - var transmitters []string +// deployForwarderContracts deploys forwarder contracts if OperatorForwarderFlow is enabled. +func (o *OCRSoakTest) deployForwarderContracts() (operators []common.Address, forwarders []common.Address) { + operators, forwarders, _ = actions.DeployForwarderContracts( + o.t, o.sethClient, common.HexToAddress(o.linkContract.Address()), len(o.workerNodes), + ) + require.Equal(o.t, len(o.workerNodes), len(operators), "Number of operators should match number of nodes") + require.Equal(o.t, len(o.workerNodes), len(forwarders), "Number of authorized forwarders should match number of nodes") + + forwarderNodesAddresses, err := actions.ChainlinkNodeAddresses(o.workerNodes) + require.NoError(o.t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") + for i := range o.workerNodes { + actions.AcceptAuthorizedReceiversOperator(o.t, o.log, o.sethClient, operators[i], forwarders[i], []common.Address{forwarderNodesAddresses[i]}) + require.NoError(o.t, err, "Accepting Authorize Receivers on Operator shouldn't fail") + actions.TrackForwarder(o.t, o.sethClient, forwarders[i], o.workerNodes[i]) + } + return operators, forwarders +} - if o.OperatorForwarderFlow { - for _, forwarder := range forwarders { - transmitters = append(transmitters, forwarder.Hex()) - } - } else { - for _, node := range o.workerNodes { - nodeAddress, err := node.PrimaryEthAddress() - require.NoError(o.t, err, "Error getting node's primary ETH address") - transmitters = append(transmitters, nodeAddress) - } - } +// setupOCRContracts deploys and configures OCR contracts based on the version and forwarder flow. +func (o *OCRSoakTest) setupOCRContracts(ocrTestConfig tt.OcrTestConfig, forwarders []common.Address) { + if o.OCRVersion == "1" { + o.setupOCRv1Contracts(forwarders) + } else if o.OCRVersion == "2" { + o.setupOCRv2Contracts(ocrTestConfig, forwarders) + } +} - ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - o.ocrV2Instances, err = actions.SetupOCRv2Contracts( +// setupOCRv1Contracts deploys and configures OCRv1 contracts based on the forwarder flow. +func (o *OCRSoakTest) setupOCRv1Contracts(forwarders []common.Address) { + var err error + if o.OperatorForwarderFlow { + o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( o.log, - o.seth, - ocrTestConfig.GetActiveOCRConfig(), - common.HexToAddress(linkContract.Address()), - transmitters, - ocrOffchainOptions, + o.sethClient, + o.Config.GetActiveOCRConfig(), + common.HexToAddress(o.linkContract.Address()), + contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), + forwarders, ) - require.NoError(o.t, err, "Error deploying OCRv2 contracts") - - if !ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() || (ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() && ocrTestConfig.GetActiveOCRConfig().ConfigureExistingOffChainAggregatorsContracts()) { - contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) - require.NoError(o.t, err, "Error building median config") - err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) - require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") - } + require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") + o.createJobsWithForwarder() + } else { + o.ocrV1Instances, err = actions.SetupOCRv1Contracts( + o.log, + o.sethClient, + o.Config.GetActiveOCRConfig(), + common.HexToAddress(o.linkContract.Address()), + contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), + ) + require.NoError(o.t, err, "Error setting up OCRv1 contracts") + err = o.createOCRv1Jobs() + require.NoError(o.t, err, "Error creating OCR jobs") } - if o.OCRVersion == "1" { - for _, ocrInstance := range o.ocrV1Instances { - o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance + o.storeOCRInstancesV1() +} + +// setupOCRv2Contracts sets up and configures OCRv2 contracts. +func (o *OCRSoakTest) setupOCRv2Contracts(ocrTestConfig tt.OcrTestConfig, forwarders []common.Address) { + var err error + var transmitters []string + if o.OperatorForwarderFlow { + for _, forwarder := range forwarders { + transmitters = append(transmitters, forwarder.Hex()) } - } else if o.OCRVersion == "2" { - for _, ocrInstance := range o.ocrV2Instances { - o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance + } else { + for _, node := range o.workerNodes { + nodeAddress, err := node.PrimaryEthAddress() + require.NoError(o.t, err, "Error getting node's primary ETH address") + transmitters = append(transmitters, nodeAddress) } } - o.log.Info().Msg("OCR Soak Test Setup Complete") + ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() + o.ocrV2Instances, err = actions.SetupOCRv2Contracts( + o.log, o.sethClient, ocrTestConfig.GetActiveOCRConfig(), common.HexToAddress(o.linkContract.Address()), transmitters, ocrOffchainOptions, + ) + require.NoError(o.t, err, "Error deploying OCRv2 contracts") + err = o.createOCRv2Jobs() + require.NoError(o.t, err, "Error creating OCR jobs") + if !ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() || (ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() && ocrTestConfig.GetActiveOCRConfig().ConfigureExistingOffChainAggregatorsContracts()) { + contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) + require.NoError(o.t, err, "Error building median config") + err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) + require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") + } + o.storeOCRInstancesV2() +} + +// storeOCRInstancesV1 stores OCRv1 contract instances by their addresses. +func (o *OCRSoakTest) storeOCRInstancesV1() { + for _, ocrInstance := range o.ocrV1Instances { + o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance + } +} + +// storeOCRInstancesV2 stores OCRv2 contract instances by their addresses. +func (o *OCRSoakTest) storeOCRInstancesV2() { + for _, ocrInstance := range o.ocrV2Instances { + o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance + } } // Run starts the OCR soak test @@ -389,36 +436,52 @@ func (o *OCRSoakTest) Run() { require.NoError(o.t, err, "Error getting config") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) - latestBlockNum, err := o.seth.Client.BlockNumber(ctx) + latestBlockNum, err := o.sethClient.Client.BlockNumber(ctx) cancel() require.NoError(o.t, err, "Error getting current block number") o.startingBlockNum = latestBlockNum - startingValue := 5 - if o.OperatorForwarderFlow { - actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.seth.ChainID) - } else if o.OCRVersion == "1" { - ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) - chainId, err := o.seth.Client.ChainID(ctx) - cancel() - require.NoError(o.t, err, "Error getting chain ID") - err = actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, chainId.String()) - require.NoError(o.t, err, "Error creating OCR jobs") - } else if o.OCRVersion == "2" { - err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, startingValue, o.seth.ChainID, o.OperatorForwarderFlow) - require.NoError(o.t, err, "Error creating OCR jobs") - } - o.log.Info(). Str("Test Duration", o.Config.GetActiveOCRConfig().Common.TestDuration.Duration.Truncate(time.Second).String()). Int("Number of OCR Contracts", *config.GetActiveOCRConfig().Common.NumberOfContracts). Str("OCR Version", o.OCRVersion). Msg("Starting OCR Soak Test") - o.testLoop(o.Config.GetActiveOCRConfig().Common.TestDuration.Duration, startingValue) + o.testLoop(o.Config.GetActiveOCRConfig().Common.TestDuration.Duration, o.startingValue) o.complete() } +// createJobsWithForwarder creates OCR jobs with the forwarder setup. +func (o *OCRSoakTest) createJobsWithForwarder() { + actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, o.startingValue, o.mockServer, o.sethClient.ChainID) +} + +// createOCRv1Jobs creates OCRv1 jobs. +func (o *OCRSoakTest) createOCRv1Jobs() error { + ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) + defer cancel() + + chainId, err := o.sethClient.Client.ChainID(ctx) + if err != nil { + return fmt.Errorf("error getting chain ID: %w", err) + } + + err = actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, o.startingValue, o.mockServer, chainId.String()) + if err != nil { + return fmt.Errorf("error creating OCRv1 jobs: %w", err) + } + return nil +} + +// createOCRv2Jobs creates OCRv2 jobs. +func (o *OCRSoakTest) createOCRv2Jobs() error { + err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, o.startingValue, o.sethClient.ChainID, o.OperatorForwarderFlow, o.log) + if err != nil { + return fmt.Errorf("error creating OCRv2 jobs: %w", err) + } + return nil +} + // Networks returns the networks that the test is running on func (o *OCRSoakTest) TearDownVals(t *testing.T) ( *testing.T, @@ -428,7 +491,7 @@ func (o *OCRSoakTest) TearDownVals(t *testing.T) ( reportModel.TestReporter, reportModel.GrafanaURLProvider, ) { - return t, o.seth, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.Config + return t, o.sethClient, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.Config } // ********************* @@ -542,7 +605,7 @@ func (o *OCRSoakTest) LoadState() error { if testState.OCRVersion == "1" { o.ocrV1Instances = make([]contracts.OffchainAggregator, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffChainAggregator(o.log, o.seth, common.HexToAddress(addr)) + instance, err := contracts.LoadOffChainAggregator(o.log, o.sethClient, common.HexToAddress(addr)) if err != nil { return fmt.Errorf("failed to instantiate OCR instance: %w", err) } @@ -551,7 +614,7 @@ func (o *OCRSoakTest) LoadState() error { } else if testState.OCRVersion == "2" { o.ocrV2Instances = make([]contracts.OffchainAggregatorV2, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffchainAggregatorV2(o.log, o.seth, common.HexToAddress(addr)) + instance, err := contracts.LoadOffchainAggregatorV2(o.log, o.sethClient, common.HexToAddress(addr)) if err != nil { return err } @@ -790,7 +853,7 @@ func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork func (o *OCRSoakTest) startAnvilGasLimitSimulation(network blockchain.EVMNetwork, conf ctf_config.GasLimitSimulationConfig) { client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) - latestBlock, err := o.seth.Client.BlockByNumber(context.Background(), nil) + latestBlock, err := o.sethClient.Client.BlockByNumber(context.Background(), nil) require.NoError(o.t, err) newGasLimit := int64(math.Ceil(float64(latestBlock.GasUsed()) * conf.NextGasLimitPercentage)) o.log.Info(). @@ -916,7 +979,7 @@ func (o *OCRSoakTest) pollingOCREvents(ctx context.Context, wg *sync.WaitGroup, // Helper function to poll events and update eventCounter func (o *OCRSoakTest) fetchAndProcessEvents(eventCounter *int, expectedEvents int, processedBlockNum *uint64) { - latestBlock, err := o.seth.Client.BlockNumber(context.Background()) + latestBlock, err := o.sethClient.Client.BlockNumber(context.Background()) if err != nil { o.log.Error().Err(err).Msg("Error getting latest block number") return @@ -949,7 +1012,7 @@ func (o *OCRSoakTest) fetchAndProcessEvents(eventCounter *int, expectedEvents in Uint64("To Block", latestBlock). Msg("Fetching logs for the specified range") - logs, err := o.seth.Client.FilterLogs(context.Background(), o.filterQuery) + logs, err := o.sethClient.Client.FilterLogs(context.Background(), o.filterQuery) if err != nil { o.log.Error().Err(err).Msg("Error fetching logs") return @@ -1066,12 +1129,12 @@ func (o *OCRSoakTest) collectEvents() error { o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout) - contractEvents, err := o.seth.Client.FilterLogs(ctx, o.filterQuery) + contractEvents, err := o.sethClient.Client.FilterLogs(ctx, o.filterQuery) cancel() for err != nil { o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout) - contractEvents, err = o.seth.Client.FilterLogs(ctx, o.filterQuery) + contractEvents, err = o.sethClient.Client.FilterLogs(ctx, o.filterQuery) cancel() if err != nil { o.log.Warn().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Error collecting on-chain events, trying again") From 4f0222b074b35adf3b0a3e87596130fc651005de Mon Sep 17 00:00:00 2001 From: Silas Lenihan <32529249+silaslenihan@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:30:21 -0500 Subject: [PATCH 17/55] Temporarily skip ChainComponents tests due to flakes (#15526) --- core/services/relay/evm/chain_components_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/services/relay/evm/chain_components_test.go b/core/services/relay/evm/chain_components_test.go index 2fcdad0184c..bc2703d9678 100644 --- a/core/services/relay/evm/chain_components_test.go +++ b/core/services/relay/evm/chain_components_test.go @@ -207,6 +207,7 @@ func TestContractReaderEventsInitValidation(t *testing.T) { } func TestChainComponents(t *testing.T) { + testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCFR-1083") t.Parallel() it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}} // TODO, generated binding tests are broken From 63bca128a529dec7705e68d8c5a46f07cecef479 Mon Sep 17 00:00:00 2001 From: Makram Date: Thu, 5 Dec 2024 18:41:48 +0200 Subject: [PATCH 18/55] deployment/ccip/changeset: conform to ChangeSet iface (#15456) * deployment/ccip/changeset: conform to ChangeSet iface * port over some more changesets * compose more changesets * remove skips * Revert "remove skips" This reverts commit f97cf7f34b466f2bc8787f0775b6a3c297ca70e7. * address comments * fix --- .../ccip/changeset/cs_active_candidate.go | 138 ++++++++++----- deployment/ccip/changeset/cs_add_chain.go | 159 ++++++++++++++---- .../ccip/changeset/cs_add_chain_test.go | 77 ++++++--- 3 files changed, 277 insertions(+), 97 deletions(-) diff --git a/deployment/ccip/changeset/cs_active_candidate.go b/deployment/ccip/changeset/cs_active_candidate.go index 29516b36736..b2aad3889ec 100644 --- a/deployment/ccip/changeset/cs_active_candidate.go +++ b/deployment/ccip/changeset/cs_active_candidate.go @@ -17,18 +17,76 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" ) +var ( + _ deployment.ChangeSet[PromoteAllCandidatesChangesetConfig] = PromoteAllCandidatesChangeset + _ deployment.ChangeSet[AddDonAndSetCandidateChangesetConfig] = SetCandidatePluginChangeset +) + +type PromoteAllCandidatesChangesetConfig struct { + HomeChainSelector uint64 + NewChainSelector uint64 + NodeIDs []string +} + +func (p PromoteAllCandidatesChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (deployment.Nodes, error) { + if p.HomeChainSelector == 0 { + return nil, fmt.Errorf("HomeChainSelector must be set") + } + if p.NewChainSelector == 0 { + return nil, fmt.Errorf("NewChainSelector must be set") + } + if len(p.NodeIDs) == 0 { + return nil, fmt.Errorf("NodeIDs must be set") + } + + nodes, err := deployment.NodeInfo(p.NodeIDs, e.Offchain) + if err != nil { + return nil, fmt.Errorf("fetch node info: %w", err) + } + + donID, err := internal.DonIDForChain( + state.Chains[p.HomeChainSelector].CapabilityRegistry, + state.Chains[p.HomeChainSelector].CCIPHome, + p.NewChainSelector, + ) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + + // check if the DON ID has a candidate digest set that we can promote + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + candidateDigest, err := state.Chains[p.HomeChainSelector].CCIPHome.GetCandidateDigest(nil, donID, uint8(pluginType)) + if err != nil { + return nil, fmt.Errorf("error fetching candidate digest for pluginType(%s): %w", pluginType.String(), err) + } + if candidateDigest == [32]byte{} { + return nil, fmt.Errorf("candidate digest is zero, must be non-zero to promote") + } + } + + return nodes, nil +} + // PromoteAllCandidatesChangeset generates a proposal to call promoteCandidate on the CCIPHome through CapReg. // This needs to be called after SetCandidateProposal is executed. -// TODO: make it conform to the ChangeSet interface. func PromoteAllCandidatesChangeset( - state CCIPOnChainState, - homeChainSel, newChainSel uint64, - nodes deployment.Nodes, + e deployment.Environment, + cfg PromoteAllCandidatesChangesetConfig, ) (deployment.ChangesetOutput, error) { + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + nodes, err := cfg.Validate(e, state) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + } + promoteCandidateOps, err := promoteAllCandidatesForChainOps( - state.Chains[homeChainSel].CapabilityRegistry, - state.Chains[homeChainSel].CCIPHome, - newChainSel, + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + state.Chains[cfg.HomeChainSelector].CCIPHome, + cfg.NewChainSelector, nodes.NonBootstraps(), ) if err != nil { @@ -37,17 +95,17 @@ func PromoteAllCandidatesChangeset( var ( timelocksPerChain = map[uint64]common.Address{ - homeChainSel: state.Chains[homeChainSel].Timelock.Address(), + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), } proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{ - homeChainSel: state.Chains[homeChainSel].ProposerMcm, + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, } ) prop, err := proposalutils.BuildProposalFromBatches( timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), Batch: promoteCandidateOps, }}, "promoteCandidate for commit and execution", @@ -63,46 +121,45 @@ func PromoteAllCandidatesChangeset( }, nil } -// SetCandidateExecPluginProposal calls setCandidate on the CCIPHome for setting up OCR3 exec Plugin config for the new chain. -// TODO: make it conform to the ChangeSet interface. +// SetCandidatePluginChangeset calls setCandidate on the CCIPHome for setting up OCR3 exec Plugin config for the new chain. func SetCandidatePluginChangeset( - state CCIPOnChainState, e deployment.Environment, - nodes deployment.Nodes, - ocrSecrets deployment.OCRSecrets, - homeChainSel, feedChainSel, newChainSel uint64, - tokenConfig TokenConfig, - pluginType cctypes.PluginType, + cfg AddDonAndSetCandidateChangesetConfig, ) (deployment.ChangesetOutput, error) { - ccipOCRParams := DefaultOCRParams( - feedChainSel, - tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), - nil, - ) + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + nodes, err := cfg.Validate(e, state) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + } + newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - ocrSecrets, - state.Chains[newChainSel].OffRamp, - e.Chains[newChainSel], + cfg.OCRSecrets, + state.Chains[cfg.NewChainSelector].OffRamp, + e.Chains[cfg.NewChainSelector], nodes.NonBootstraps(), - state.Chains[homeChainSel].RMNHome.Address(), - ccipOCRParams.OCRParameters, - ccipOCRParams.CommitOffChainConfig, - ccipOCRParams.ExecuteOffChainConfig, + state.Chains[cfg.HomeChainSelector].RMNHome.Address(), + cfg.CCIPOCRParams.OCRParameters, + cfg.CCIPOCRParams.CommitOffChainConfig, + cfg.CCIPOCRParams.ExecuteOffChainConfig, ) if err != nil { return deployment.ChangesetOutput{}, err } - execConfig, ok := newDONArgs[pluginType] + config, ok := newDONArgs[cfg.PluginType] if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("missing exec plugin in ocr3Configs") + return deployment.ChangesetOutput{}, fmt.Errorf("missing %s plugin in ocr3Configs", cfg.PluginType.String()) } setCandidateMCMSOps, err := setCandidateOnExistingDon( - execConfig, - state.Chains[homeChainSel].CapabilityRegistry, - state.Chains[homeChainSel].CCIPHome, - newChainSel, + config, + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, + state.Chains[cfg.HomeChainSelector].CCIPHome, + cfg.NewChainSelector, nodes.NonBootstraps(), ) if err != nil { @@ -111,20 +168,20 @@ func SetCandidatePluginChangeset( var ( timelocksPerChain = map[uint64]common.Address{ - homeChainSel: state.Chains[homeChainSel].Timelock.Address(), + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), } proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{ - homeChainSel: state.Chains[homeChainSel].ProposerMcm, + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, } ) prop, err := proposalutils.BuildProposalFromBatches( timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), Batch: setCandidateMCMSOps, }}, - "SetCandidate for execution", + fmt.Sprintf("SetCandidate for %s plugin", cfg.PluginType.String()), 0, // minDelay ) if err != nil { @@ -135,7 +192,6 @@ func SetCandidatePluginChangeset( *prop, }, }, nil - } // setCandidateOnExistingDon calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract diff --git a/deployment/ccip/changeset/cs_add_chain.go b/deployment/ccip/changeset/cs_add_chain.go index 262d2e85e7e..9c19517260f 100644 --- a/deployment/ccip/changeset/cs_add_chain.go +++ b/deployment/ccip/changeset/cs_add_chain.go @@ -23,22 +23,47 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" ) +var _ deployment.ChangeSet[ChainInboundChangesetConfig] = NewChainInboundChangeset + +type ChainInboundChangesetConfig struct { + HomeChainSelector uint64 + NewChainSelector uint64 + SourceChainSelectors []uint64 +} + +func (c ChainInboundChangesetConfig) Validate() error { + if c.HomeChainSelector == 0 { + return fmt.Errorf("HomeChainSelector must be set") + } + if c.NewChainSelector == 0 { + return fmt.Errorf("NewChainSelector must be set") + } + if len(c.SourceChainSelectors) == 0 { + return fmt.Errorf("SourceChainSelectors must be set") + } + return nil +} + // NewChainInboundChangeset generates a proposal // to connect the new chain to the existing chains. -// TODO: doesn't implement the ChangeSet interface. func NewChainInboundChangeset( e deployment.Environment, - state CCIPOnChainState, - homeChainSel uint64, - newChainSel uint64, - sources []uint64, + cfg ChainInboundChangesetConfig, ) (deployment.ChangesetOutput, error) { + if err := cfg.Validate(); err != nil { + return deployment.ChangesetOutput{}, err + } + + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } // Generate proposal which enables new destination (from test router) on all source chains. var batches []timelock.BatchChainOperation - for _, source := range sources { + for _, source := range cfg.SourceChainSelectors { enableOnRampDest, err := state.Chains[source].OnRamp.ApplyDestChainConfigUpdates(deployment.SimTransactOpts(), []onramp.OnRampDestChainConfigArgs{ { - DestChainSelector: newChainSel, + DestChainSelector: cfg.NewChainSelector, Router: state.Chains[source].TestRouter.Address(), }, }) @@ -49,7 +74,7 @@ func NewChainInboundChangeset( deployment.SimTransactOpts(), []fee_quoter.FeeQuoterDestChainConfigArgs{ { - DestChainSelector: newChainSel, + DestChainSelector: cfg.NewChainSelector, DestChainConfig: DefaultFeeQuoterDestChainConfig(), }, }) @@ -74,13 +99,13 @@ func NewChainInboundChangeset( }) } - addChainOp, err := applyChainConfigUpdatesOp(e, state, homeChainSel, []uint64{newChainSel}) + addChainOp, err := applyChainConfigUpdatesOp(e, state, cfg.HomeChainSelector, []uint64{cfg.NewChainSelector}) if err != nil { return deployment.ChangesetOutput{}, err } batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), Batch: []mcms.Operation{ addChainOp, }, @@ -90,7 +115,7 @@ func NewChainInboundChangeset( timelocksPerChain = make(map[uint64]common.Address) proposerMCMSes = make(map[uint64]*gethwrappers.ManyChainMultiSig) ) - for _, chain := range append(sources, homeChainSel) { + for _, chain := range append(cfg.SourceChainSelectors, cfg.HomeChainSelector) { timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() proposerMCMSes[chain] = state.Chains[chain].ProposerMcm } @@ -110,48 +135,110 @@ func NewChainInboundChangeset( }, nil } +type AddDonAndSetCandidateChangesetConfig struct { + HomeChainSelector uint64 + FeedChainSelector uint64 + NewChainSelector uint64 + PluginType types.PluginType + NodeIDs []string + CCIPOCRParams CCIPOCRParams + OCRSecrets deployment.OCRSecrets +} + +func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (deployment.Nodes, error) { + if a.HomeChainSelector == 0 { + return nil, fmt.Errorf("HomeChainSelector must be set") + } + if a.FeedChainSelector == 0 { + return nil, fmt.Errorf("FeedChainSelector must be set") + } + if a.NewChainSelector == 0 { + return nil, fmt.Errorf("ocr config chain selector must be set") + } + if a.PluginType != types.PluginTypeCCIPCommit && + a.PluginType != types.PluginTypeCCIPExec { + return nil, fmt.Errorf("PluginType must be set to either CCIPCommit or CCIPExec") + } + // TODO: validate token config + if len(a.NodeIDs) == 0 { + return nil, fmt.Errorf("nodeIDs must be set") + } + nodes, err := deployment.NodeInfo(a.NodeIDs, e.Offchain) + if err != nil { + return nil, fmt.Errorf("get node info: %w", err) + } + + // check that chain config is set up for the new chain + // TODO: feels like we should just have a getter for a particular chain, this pagination + // logic seems a bit out of place here. + allConfigs, err := state.Chains[a.HomeChainSelector].CCIPHome.GetAllChainConfigs(nil, big.NewInt(0), big.NewInt(100)) + if err != nil { + return nil, fmt.Errorf("get all chain configs: %w", err) + } + var found bool + for _, chainConfig := range allConfigs { + if chainConfig.ChainSelector == a.NewChainSelector { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("chain config not set for chain %d", a.NewChainSelector) + } + + err = a.CCIPOCRParams.Validate() + if err != nil { + return nil, fmt.Errorf("invalid ccip ocr params: %w", err) + } + + if a.OCRSecrets.IsEmpty() { + return nil, fmt.Errorf("OCR secrets must be set") + } + + return nodes, nil +} + // AddDonAndSetCandidateChangeset adds new DON for destination to home chain // and sets the commit plugin config as candidateConfig for the don. func AddDonAndSetCandidateChangeset( - state CCIPOnChainState, e deployment.Environment, - nodes deployment.Nodes, - ocrSecrets deployment.OCRSecrets, - homeChainSel, feedChainSel, newChainSel uint64, - tokenConfig TokenConfig, - pluginType types.PluginType, + cfg AddDonAndSetCandidateChangesetConfig, ) (deployment.ChangesetOutput, error) { - ccipOCRParams := DefaultOCRParams( - feedChainSel, - tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), - // TODO: Need USDC support. - nil, - ) + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + nodes, err := cfg.Validate(e, state) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) + } + newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - ocrSecrets, - state.Chains[newChainSel].OffRamp, - e.Chains[newChainSel], + cfg.OCRSecrets, + state.Chains[cfg.NewChainSelector].OffRamp, + e.Chains[cfg.NewChainSelector], nodes.NonBootstraps(), - state.Chains[homeChainSel].RMNHome.Address(), - ccipOCRParams.OCRParameters, - ccipOCRParams.CommitOffChainConfig, - ccipOCRParams.ExecuteOffChainConfig, + state.Chains[cfg.HomeChainSelector].RMNHome.Address(), + cfg.CCIPOCRParams.OCRParameters, + cfg.CCIPOCRParams.CommitOffChainConfig, + cfg.CCIPOCRParams.ExecuteOffChainConfig, ) if err != nil { return deployment.ChangesetOutput{}, err } - latestDon, err := internal.LatestCCIPDON(state.Chains[homeChainSel].CapabilityRegistry) + latestDon, err := internal.LatestCCIPDON(state.Chains[cfg.HomeChainSelector].CapabilityRegistry) if err != nil { return deployment.ChangesetOutput{}, err } - commitConfig, ok := newDONArgs[pluginType] + commitConfig, ok := newDONArgs[cfg.PluginType] if !ok { return deployment.ChangesetOutput{}, fmt.Errorf("missing commit plugin in ocr3Configs") } donID := latestDon.Id + 1 addDonOp, err := newDonWithCandidateOp( donID, commitConfig, - state.Chains[homeChainSel].CapabilityRegistry, + state.Chains[cfg.HomeChainSelector].CapabilityRegistry, nodes.NonBootstraps(), ) if err != nil { @@ -160,17 +247,17 @@ func AddDonAndSetCandidateChangeset( var ( timelocksPerChain = map[uint64]common.Address{ - homeChainSel: state.Chains[homeChainSel].Timelock.Address(), + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), } proposerMCMSes = map[uint64]*gethwrappers.ManyChainMultiSig{ - homeChainSel: state.Chains[homeChainSel].ProposerMcm, + cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, } ) prop, err := proposalutils.BuildProposalFromBatches( timelocksPerChain, proposerMCMSes, []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), Batch: []mcms.Operation{addDonOp}, }}, "setCandidate for commit and AddDon on new Chain", diff --git a/deployment/ccip/changeset/cs_add_chain_test.go b/deployment/ccip/changeset/cs_add_chain_test.go index b8a845ac27c..c83872c0dd7 100644 --- a/deployment/ccip/changeset/cs_add_chain_test.go +++ b/deployment/ccip/changeset/cs_add_chain_test.go @@ -151,11 +151,18 @@ func TestAddChainInbound(t *testing.T) { initialDeploy[1]: state.Chains[initialDeploy[1]].Timelock, initialDeploy[2]: state.Chains[initialDeploy[2]].Timelock, }, []commonchangeset.ChangesetApplication{ - // note this doesn't have proposals. { Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), Config: genTestTransferOwnershipConfig(e, initialDeploy, state), }, + { + Changeset: commonchangeset.WrapChangeSet(NewChainInboundChangeset), + Config: ChainInboundChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + NewChainSelector: newChain, + SourceChainSelectors: initialDeploy, + }, + }, }) require.NoError(t, err) @@ -164,29 +171,59 @@ func TestAddChainInbound(t *testing.T) { nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) require.NoError(t, err) - // Generate and sign inbound proposal to new 4th chain. - chainInboundChangeset, err := NewChainInboundChangeset(e.Env, state, e.HomeChainSel, newChain, initialDeploy) - require.NoError(t, err) - ProcessChangeset(t, e.Env, chainInboundChangeset) - // TODO This currently is not working - Able to send the request here but request gets stuck in execution // Send a new message and expect that this is delivered once the chain is completely set up as inbound //TestSendRequest(t, e.Env, state, initialDeploy[0], newChain, true) + var nodeIDs []string + for _, node := range nodes { + nodeIDs = append(nodeIDs, node.NodeID) + } - t.Logf("Executing add don and set candidate proposal for commit plugin on chain %d", newChain) - addDonChangeset, err := AddDonAndSetCandidateChangeset(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, types.PluginTypeCCIPCommit) - require.NoError(t, err) - ProcessChangeset(t, e.Env, addDonChangeset) - - t.Logf("Executing promote candidate proposal for exec plugin on chain %d", newChain) - setCandidateForExecChangeset, err := SetCandidatePluginChangeset(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, types.PluginTypeCCIPExec) - require.NoError(t, err) - ProcessChangeset(t, e.Env, setCandidateForExecChangeset) - - t.Logf("Executing promote candidate proposal for both commit and exec plugins on chain %d", newChain) - donPromoteChangeset, err := PromoteAllCandidatesChangeset(state, e.HomeChainSel, newChain, nodes) - require.NoError(t, err) - ProcessChangeset(t, e.Env, donPromoteChangeset) + _, err = commonchangeset.ApplyChangesets(t, e.Env, map[uint64]*gethwrappers.RBACTimelock{ + e.HomeChainSel: state.Chains[e.HomeChainSel].Timelock, + newChain: state.Chains[newChain].Timelock, + }, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(AddDonAndSetCandidateChangeset), + Config: AddDonAndSetCandidateChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + FeedChainSelector: e.FeedChainSel, + NewChainSelector: newChain, + PluginType: types.PluginTypeCCIPCommit, + NodeIDs: nodeIDs, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + CCIPOCRParams: DefaultOCRParams( + e.FeedChainSel, + tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), + nil, + ), + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(SetCandidatePluginChangeset), + Config: AddDonAndSetCandidateChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + FeedChainSelector: e.FeedChainSel, + NewChainSelector: newChain, + PluginType: types.PluginTypeCCIPExec, + NodeIDs: nodeIDs, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + CCIPOCRParams: DefaultOCRParams( + e.FeedChainSel, + tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), + nil, + ), + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset), + Config: PromoteAllCandidatesChangesetConfig{ + HomeChainSelector: e.HomeChainSel, + NewChainSelector: newChain, + NodeIDs: nodeIDs, + }, + }, + }) // verify if the configs are updated require.NoError(t, ValidateCCIPHomeConfigSetUp( From bbddf93768a226bcbf98f74b10ccef2d42b0e170 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:54:09 -0700 Subject: [PATCH 19/55] support mcms in ocr3 contract config changeset (#15510) * support mcms in ocr3 contract config changeset * test working for ocr3 config with mcms * migrate deployment test to setup test env * fix test --- core/scripts/go.mod | 1 + core/scripts/go.sum | 2 + deployment/environment/memory/chain.go | 61 ++- .../keystone/changeset/accept_ownership.go | 38 +- .../changeset/accept_ownership_test.go | 4 - .../keystone/changeset/configure_contracts.go | 19 + .../keystone/changeset/deploy_forwarder.go | 10 +- .../changeset/deploy_forwarder_test.go | 33 -- deployment/keystone/changeset/deploy_ocr3.go | 48 +- .../keystone/changeset/deploy_ocr3_test.go | 106 +++++ deployment/keystone/changeset/helpers_test.go | 419 ++++++++++++++++++ .../keystone/changeset/internal/test/utils.go | 1 - deployment/keystone/deploy.go | 30 +- deployment/keystone/deploy_test.go | 186 +------- deployment/keystone/ocr3config.go | 103 ++++- deployment/keystone/state.go | 21 + 16 files changed, 768 insertions(+), 314 deletions(-) create mode 100644 deployment/keystone/changeset/helpers_test.go diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 94eea2b4b3a..7e846dcd545 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -304,6 +304,7 @@ require ( github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index e312f248ceb..0c60e0596d7 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1158,6 +1158,8 @@ github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef9 github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99/go.mod h1:p8aUDfJeley6oer7y+Ucd3edOtRlMTnWg3mN6rhaLWo= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= diff --git a/deployment/environment/memory/chain.go b/deployment/environment/memory/chain.go index cbb3e67df7a..58f71a83a8c 100644 --- a/deployment/environment/memory/chain.go +++ b/deployment/environment/memory/chain.go @@ -47,30 +47,7 @@ func GenerateChains(t *testing.T, numChains int, numUsers int) map[uint64]EVMCha chains := make(map[uint64]EVMChain) for i := 0; i < numChains; i++ { chainID := chainsel.TEST_90000001.EvmChainID + uint64(i) - key, err := crypto.GenerateKey() - require.NoError(t, err) - owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - require.NoError(t, err) - genesis := types.GenesisAlloc{ - owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(7000), big.NewInt(params.Ether))}} - // create a set of user keys - var users []*bind.TransactOpts - for j := 0; j < numUsers; j++ { - key, err := crypto.GenerateKey() - require.NoError(t, err) - user, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - require.NoError(t, err) - users = append(users, user) - genesis[user.From] = types.Account{Balance: big.NewInt(0).Mul(big.NewInt(7000), big.NewInt(params.Ether))} - } - // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test - backend := simulated.NewBackend(genesis, simulated.WithBlockGasLimit(50000000)) - backend.Commit() // ts will be now. - chains[chainID] = EVMChain{ - Backend: backend, - DeployerKey: owner, - Users: users, - } + chains[chainID] = evmChain(t, numUsers) } return chains } @@ -78,18 +55,34 @@ func GenerateChains(t *testing.T, numChains int, numUsers int) map[uint64]EVMCha func GenerateChainsWithIds(t *testing.T, chainIDs []uint64) map[uint64]EVMChain { chains := make(map[uint64]EVMChain) for _, chainID := range chainIDs { + chains[chainID] = evmChain(t, 1) + } + return chains +} + +func evmChain(t *testing.T, numUsers int) EVMChain { + key, err := crypto.GenerateKey() + require.NoError(t, err) + owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + require.NoError(t, err) + genesis := types.GenesisAlloc{ + owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(700000), big.NewInt(params.Ether))}} + // create a set of user keys + var users []*bind.TransactOpts + for j := 0; j < numUsers; j++ { key, err := crypto.GenerateKey() require.NoError(t, err) - owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + user, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) require.NoError(t, err) - backend := simulated.NewBackend(types.GenesisAlloc{ - owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(700000), big.NewInt(params.Ether))}}, - simulated.WithBlockGasLimit(10000000)) - backend.Commit() // Note initializes block timestamp to now(). - chains[chainID] = EVMChain{ - Backend: backend, - DeployerKey: owner, - } + users = append(users, user) + genesis[user.From] = types.Account{Balance: big.NewInt(0).Mul(big.NewInt(700000), big.NewInt(params.Ether))} + } + // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test + backend := simulated.NewBackend(genesis, simulated.WithBlockGasLimit(50000000)) + backend.Commit() // ts will be now. + return EVMChain{ + Backend: backend, + DeployerKey: owner, + Users: users, } - return chains } diff --git a/deployment/keystone/changeset/accept_ownership.go b/deployment/keystone/changeset/accept_ownership.go index 7dffc5a70c4..662a4c2dcfa 100644 --- a/deployment/keystone/changeset/accept_ownership.go +++ b/deployment/keystone/changeset/accept_ownership.go @@ -5,6 +5,8 @@ import ( "github.com/ethereum/go-ethereum/common" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset" ) @@ -23,39 +25,21 @@ func AcceptAllOwnershipsProposal(e deployment.Environment, req *AcceptAllOwnersh chain := e.Chains[chainSelector] addrBook := e.ExistingAddresses - capRegs, err := capRegistriesFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, err - } - ocr3, err := ocr3FromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, err - } - forwarders, err := forwardersFromAddrBook(addrBook, chain) - if err != nil { - return deployment.ChangesetOutput{}, err - } - consumers, err := feedsConsumersFromAddrBook(addrBook, chain) + r, err := kslib.GetContractSets(e.Logger, &kslib.GetContractSetsRequest{ + Chains: map[uint64]deployment.Chain{ + req.ChainSelector: chain, + }, + AddressBook: addrBook, + }) if err != nil { return deployment.ChangesetOutput{}, err } - var addrsToTransfer []common.Address - for _, consumer := range consumers { - addrsToTransfer = append(addrsToTransfer, consumer.Address()) - } - for _, o := range ocr3 { - addrsToTransfer = append(addrsToTransfer, o.Address()) - } - for _, f := range forwarders { - addrsToTransfer = append(addrsToTransfer, f.Address()) - } - for _, c := range capRegs { - addrsToTransfer = append(addrsToTransfer, c.Address()) - } + contracts := r.ContractSets[chainSelector] + // Construct the configuration cfg := changeset.TransferToMCMSWithTimelockConfig{ ContractsByChain: map[uint64][]common.Address{ - chainSelector: addrsToTransfer, + chainSelector: contracts.TransferableContracts(), }, MinDelay: minDelay, } diff --git a/deployment/keystone/changeset/accept_ownership_test.go b/deployment/keystone/changeset/accept_ownership_test.go index 997f0b7e163..ec65ef920ac 100644 --- a/deployment/keystone/changeset/accept_ownership_test.go +++ b/deployment/keystone/changeset/accept_ownership_test.go @@ -38,10 +38,6 @@ func TestAcceptAllOwnership(t *testing.T) { Changeset: commonchangeset.WrapChangeSet(changeset.DeployForwarder), Config: registrySel, }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployFeedsConsumer), - Config: &changeset.DeployFeedsConsumerRequest{ChainSelector: registrySel}, - }, { Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), Config: map[uint64]types.MCMSWithTimelockConfig{ diff --git a/deployment/keystone/changeset/configure_contracts.go b/deployment/keystone/changeset/configure_contracts.go index d5bcb32243b..17635a42ed1 100644 --- a/deployment/keystone/changeset/configure_contracts.go +++ b/deployment/keystone/changeset/configure_contracts.go @@ -9,6 +9,25 @@ import ( kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) +var _ deployment.ChangeSet[InitialContractsCfg] = ConfigureInitialContractsChangeset + +type InitialContractsCfg struct { + RegistryChainSel uint64 + Dons []kslib.DonCapabilities + OCR3Config *kslib.OracleConfigWithSecrets +} + +func ConfigureInitialContractsChangeset(e deployment.Environment, cfg InitialContractsCfg) (deployment.ChangesetOutput, error) { + req := &kslib.ConfigureContractsRequest{ + Env: &e, + RegistryChainSel: cfg.RegistryChainSel, + Dons: cfg.Dons, + OCR3Config: cfg.OCR3Config, + } + return ConfigureInitialContracts(e.Logger, req) +} + +// Deprecated: Use ConfigureInitialContractsChangeset instead. func ConfigureInitialContracts(lggr logger.Logger, req *kslib.ConfigureContractsRequest) (deployment.ChangesetOutput, error) { if err := req.Validate(); err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to validate request: %w", err) diff --git a/deployment/keystone/changeset/deploy_forwarder.go b/deployment/keystone/changeset/deploy_forwarder.go index 2dc160dcf4c..5207d99aacd 100644 --- a/deployment/keystone/changeset/deploy_forwarder.go +++ b/deployment/keystone/changeset/deploy_forwarder.go @@ -9,16 +9,10 @@ import ( var _ deployment.ChangeSet[uint64] = DeployForwarder +// DeployForwarder deploys the KeystoneForwarder contract to all chains in the environment +// callers must merge the output addressbook with the existing one func DeployForwarder(env deployment.Environment, registryChainSel uint64) (deployment.ChangesetOutput, error) { lggr := env.Logger - // expect OCR3 to be deployed & capabilities registry - regAddrs, err := env.ExistingAddresses.AddressesForChain(registryChainSel) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("no addresses found for chain %d: %w", registryChainSel, err) - } - if len(regAddrs) != 2 { - return deployment.ChangesetOutput{}, fmt.Errorf("expected 2 addresses for chain %d, got %d", registryChainSel, len(regAddrs)) - } ab := deployment.NewMemoryAddressBook() for _, chain := range env.Chains { lggr.Infow("deploying forwarder", "chainSelector", chain.Selector) diff --git a/deployment/keystone/changeset/deploy_forwarder_test.go b/deployment/keystone/changeset/deploy_forwarder_test.go index 8d73134fc1d..b6d8ec8f753 100644 --- a/deployment/keystone/changeset/deploy_forwarder_test.go +++ b/deployment/keystone/changeset/deploy_forwarder_test.go @@ -10,7 +10,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - kslb "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -24,43 +23,11 @@ func TestDeployForwarder(t *testing.T) { } env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - var ( - ocrTV = deployment.NewTypeAndVersion(kslb.OCR3Capability, deployment.Version1_0_0) - crTV = deployment.NewTypeAndVersion(kslb.CapabilitiesRegistry, deployment.Version1_0_0) - ) - registrySel := env.AllChainSelectors()[0] - t.Run("err if no capabilities registry on registry chain", func(t *testing.T) { - m := make(map[uint64]map[string]deployment.TypeAndVersion) - m[registrySel] = map[string]deployment.TypeAndVersion{ - "0x0000000000000000000000000000000000000002": ocrTV, - } - env.ExistingAddresses = deployment.NewMemoryAddressBookFromMap(m) - // capabilities registry and ocr3 must be deployed on registry chain - _, err := changeset.DeployForwarder(env, registrySel) - require.Error(t, err) - }) - - t.Run("err if no ocr3 on registry chain", func(t *testing.T) { - m := make(map[uint64]map[string]deployment.TypeAndVersion) - m[registrySel] = map[string]deployment.TypeAndVersion{ - "0x0000000000000000000000000000000000000001": crTV, - } - env.ExistingAddresses = deployment.NewMemoryAddressBookFromMap(m) - // capabilities registry and ocr3 must be deployed on registry chain - _, err := changeset.DeployForwarder(env, registrySel) - require.Error(t, err) - }) t.Run("should deploy forwarder", func(t *testing.T) { ab := deployment.NewMemoryAddressBook() - // fake capabilities registry - err := ab.Save(registrySel, "0x0000000000000000000000000000000000000001", crTV) - require.NoError(t, err) - // fake ocr3 - err = ab.Save(registrySel, "0x0000000000000000000000000000000000000002", ocrTV) - require.NoError(t, err) // deploy forwarder env.ExistingAddresses = ab resp, err := changeset.DeployForwarder(env, registrySel) diff --git a/deployment/keystone/changeset/deploy_ocr3.go b/deployment/keystone/changeset/deploy_ocr3.go index 40d9e558584..fdf51e644be 100644 --- a/deployment/keystone/changeset/deploy_ocr3.go +++ b/deployment/keystone/changeset/deploy_ocr3.go @@ -1,10 +1,11 @@ package changeset import ( + "encoding/json" "fmt" + "io" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) @@ -27,12 +28,49 @@ func DeployOCR3(env deployment.Environment, registryChainSel uint64) (deployment return deployment.ChangesetOutput{AddressBook: ab}, nil } -func ConfigureOCR3Contract(lggr logger.Logger, env deployment.Environment, cfg kslib.ConfigureOCR3Config) (deployment.ChangesetOutput, error) { +var _ deployment.ChangeSet[ConfigureOCR3Config] = ConfigureOCR3Contract + +type ConfigureOCR3Config struct { + ChainSel uint64 + NodeIDs []string + OCR3Config *kslib.OracleConfigWithSecrets + DryRun bool + WriteGeneratedConfig io.Writer // if not nil, write the generated config to this writer as JSON [OCR2OracleConfig] + + UseMCMS bool +} - _, err := kslib.ConfigureOCR3ContractFromJD(&env, cfg) +func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config) (deployment.ChangesetOutput, error) { + resp, err := kslib.ConfigureOCR3ContractFromJD(&env, kslib.ConfigureOCR3Config{ + ChainSel: cfg.ChainSel, + NodeIDs: cfg.NodeIDs, + OCR3Config: cfg.OCR3Config, + DryRun: cfg.DryRun, + UseMCMS: cfg.UseMCMS, + }) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure OCR3Capability: %w", err) } + if w := cfg.WriteGeneratedConfig; w != nil { + b, err := json.MarshalIndent(&resp.OCR2OracleConfig, "", " ") + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to marshal response output: %w", err) + } + env.Logger.Infof("Generated OCR3 config: %s", string(b)) + n, err := w.Write(b) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to write response output: %w", err) + } + if n != len(b) { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to write all bytes") + } + } // does not create any new addresses - return deployment.ChangesetOutput{}, nil + var proposals []timelock.MCMSWithTimelockProposal + if cfg.UseMCMS { + proposals = append(proposals, *resp.Proposal) + } + return deployment.ChangesetOutput{ + Proposals: proposals, + }, nil } diff --git a/deployment/keystone/changeset/deploy_ocr3_test.go b/deployment/keystone/changeset/deploy_ocr3_test.go index d3fdf118f8b..0d49af68823 100644 --- a/deployment/keystone/changeset/deploy_ocr3_test.go +++ b/deployment/keystone/changeset/deploy_ocr3_test.go @@ -1,6 +1,8 @@ package changeset_test import ( + "bytes" + "encoding/json" "testing" "go.uber.org/zap/zapcore" @@ -8,8 +10,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -37,3 +43,103 @@ func TestDeployOCR3(t *testing.T) { oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) assert.Len(t, oaddrs, 0) } + +func TestConfigureOCR3(t *testing.T) { + t.Parallel() + lggr := logger.Test(t) + + c := kslib.OracleConfigWithSecrets{ + OracleConfig: kslib.OracleConfig{ + MaxFaultyOracles: 1, + DeltaProgressMillis: 12345, + }, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + } + + t.Run("no mcms", func(t *testing.T) { + + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 1, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + w := &bytes.Buffer{} + cfg := changeset.ConfigureOCR3Config{ + ChainSel: te.RegistrySelector, + NodeIDs: wfNodes, + OCR3Config: &c, + WriteGeneratedConfig: w, + UseMCMS: false, + } + + csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) + require.NoError(t, err) + var got kslib.OCR2OracleConfig + err = json.Unmarshal(w.Bytes(), &got) + require.NoError(t, err) + assert.Len(t, got.Signers, 4) + assert.Len(t, got.Transmitters, 4) + assert.Nil(t, csOut.Proposals) + }) + + t.Run("mcms", func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 1, + UseMCMS: true, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + w := &bytes.Buffer{} + cfg := changeset.ConfigureOCR3Config{ + ChainSel: te.RegistrySelector, + NodeIDs: wfNodes, + OCR3Config: &c, + WriteGeneratedConfig: w, + UseMCMS: true, + } + + csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) + require.NoError(t, err) + var got kslib.OCR2OracleConfig + err = json.Unmarshal(w.Bytes(), &got) + require.NoError(t, err) + assert.Len(t, got.Signers, 4) + assert.Len(t, got.Transmitters, 4) + assert.NotNil(t, csOut.Proposals) + t.Logf("got: %v", csOut.Proposals[0]) + + contractSetsResp, err := kslib.GetContractSets(lggr, &kslib.GetContractSetsRequest{ + Chains: te.Env.Chains, + AddressBook: te.Env.ExistingAddresses, + }) + require.NoError(t, err) + var timelocks = map[uint64]*gethwrappers.RBACTimelock{ + te.RegistrySelector: contractSetsResp.ContractSets[te.RegistrySelector].Timelock, + } + // now apply the changeset such that the proposal is signed and execed + w2 := &bytes.Buffer{} + cfg.WriteGeneratedConfig = w2 + _, err = commonchangeset.ApplyChangesets(t, te.Env, timelocks, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureOCR3Contract), + Config: cfg, + }, + }) + require.NoError(t, err) + }) + +} diff --git a/deployment/keystone/changeset/helpers_test.go b/deployment/keystone/changeset/helpers_test.go new file mode 100644 index 00000000000..85e69507009 --- /dev/null +++ b/deployment/keystone/changeset/helpers_test.go @@ -0,0 +1,419 @@ +package changeset_test + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "math/big" + "sort" + + "math" + "testing" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kschangeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "golang.org/x/exp/maps" +) + +func TestSetupTestEnv(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + for _, useMCMS := range []bool{true, false} { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 3, + UseMCMS: useMCMS, + }) + t.Run(fmt.Sprintf("set up test env using MCMS: %T", useMCMS), func(t *testing.T) { + require.NotNil(t, te.Env.ExistingAddresses) + require.Len(t, te.Env.Chains, 3) + require.NotEmpty(t, te.RegistrySelector) + require.NotNil(t, te.Env.Offchain) + r, err := te.Env.Offchain.ListNodes(ctx, &node.ListNodesRequest{}) + require.NoError(t, err) + require.Len(t, r.Nodes, 12) + }) + } +} + +type DonConfig struct { + N int +} + +func (c DonConfig) Validate() error { + if c.N < 4 { + return errors.New("N must be at least 4") + } + return nil +} + +// TODO: separate the config into different types; wf should expand to types of ocr keybundles; writer to target chains; ... +type WFDonConfig = DonConfig +type AssetDonConfig = DonConfig +type WriterDonConfig = DonConfig + +type TestConfig struct { + WFDonConfig + AssetDonConfig + WriterDonConfig + NumChains int + + UseMCMS bool +} + +func (c TestConfig) Validate() error { + if err := c.WFDonConfig.Validate(); err != nil { + return err + } + if err := c.AssetDonConfig.Validate(); err != nil { + return err + } + if err := c.WriterDonConfig.Validate(); err != nil { + return err + } + if c.NumChains < 1 { + return errors.New("NumChains must be at least 1") + } + return nil +} + +type TestEnv struct { + Env deployment.Environment + RegistrySelector uint64 + + WFNodes map[string]memory.Node + CWNodes map[string]memory.Node + AssetNodes map[string]memory.Node +} + +// SetupTestEnv sets up a keystone test environment with the given configuration +func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { + require.NoError(t, c.Validate()) + lggr := logger.Test(t) + ctx := tests.Context(t) + chains, _ := memory.NewMemoryChains(t, c.NumChains, 1) + registryChainSel := registryChain(t, chains) + // note that all the nodes require TOML configuration of the cap registry address + // and writers need forwarder address as TOML config + // we choose to use changesets to deploy the initial contracts because that's how it's done in the real world + // this requires a initial environment to house the address book + e := deployment.Environment{ + Logger: lggr, + Chains: chains, + ExistingAddresses: deployment.NewMemoryAddressBook(), + } + e, err := commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployCapabilityRegistry), + Config: registryChainSel, + }, + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployOCR3), + Config: registryChainSel, + }, + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployForwarder), + Config: registryChainSel, + }, + }) + require.NoError(t, err) + require.NotNil(t, e) + require.Len(t, e.Chains, c.NumChains) + validateInitialChainState(t, e, registryChainSel) + // now that we have the initial contracts deployed, we can configure the nodes with the addresses + // TODO: configure the nodes with the correct override functions + crConfig := deployment.CapabilityRegistryConfig{ + EVMChainID: registryChainSel, + Contract: [20]byte{}, + } + + wfChains := map[uint64]deployment.Chain{} + wfChains[registryChainSel] = chains[registryChainSel] + wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, c.WFDonConfig.N, 0, crConfig) + require.Len(t, wfNodes, c.WFDonConfig.N) + + writerChains := map[uint64]deployment.Chain{} + maps.Copy(writerChains, chains) + cwNodes := memory.NewNodes(t, zapcore.InfoLevel, writerChains, c.WriterDonConfig.N, 0, crConfig) + require.Len(t, cwNodes, c.WriterDonConfig.N) + + assetChains := map[uint64]deployment.Chain{} + assetChains[registryChainSel] = chains[registryChainSel] + assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, c.AssetDonConfig.N, 0, crConfig) + require.Len(t, assetNodes, c.AssetDonConfig.N) + + // TODO: partition nodes into multiple nops + + wfDon := keystone.DonCapabilities{ + Name: keystone.WFDonName, + Nops: []keystone.NOP{ + { + Name: "nop 1", + Nodes: maps.Keys(wfNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, + } + cwDon := keystone.DonCapabilities{ + Name: keystone.TargetDonName, + Nops: []keystone.NOP{ + { + Name: "nop 2", + Nodes: maps.Keys(cwNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, + } + assetDon := keystone.DonCapabilities{ + Name: keystone.StreamDonName, + Nops: []keystone.NOP{ + { + Name: "nop 3", + Nodes: maps.Keys(assetNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, + } + + allChains := make(map[uint64]deployment.Chain) + maps.Copy(allChains, chains) + + allNodes := make(map[string]memory.Node) + maps.Copy(allNodes, wfNodes) + maps.Copy(allNodes, cwNodes) + maps.Copy(allNodes, assetNodes) + env := memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, allChains, allNodes) + // set the env addresses to the deployed addresses that were created prior to configuring the nodes + err = env.ExistingAddresses.Merge(e.ExistingAddresses) + require.NoError(t, err) + + var ocr3Config = keystone.OracleConfigWithSecrets{ + OracleConfig: keystone.OracleConfig{ + MaxFaultyOracles: len(wfNodes) / 3, + }, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + } + var allDons = []keystone.DonCapabilities{wfDon, cwDon, assetDon} + + _, err = kschangeset.ConfigureInitialContractsChangeset(env, kschangeset.InitialContractsCfg{ + RegistryChainSel: registryChainSel, + Dons: allDons, + OCR3Config: &ocr3Config, + }) + require.NoError(t, err) + // TODO: KS-rm_deploy_opt + //require.Nil(t, csOut.AddressBook, "no new addresses should be created in configure initial contracts") + //require.NoError(t, env.ExistingAddresses.Merge(csOut.AddressBook)) + + req := &keystone.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + } + + contractSetsResp, err := keystone.GetContractSets(lggr, req) + require.NoError(t, err) + require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) + // check the registry + gotRegistry := contractSetsResp.ContractSets[registryChainSel].CapabilitiesRegistry + require.NotNil(t, gotRegistry) + // validate the registry + // check the nodes + gotNodes, err := gotRegistry.GetNodes(nil) + require.NoError(t, err) + require.Len(t, gotNodes, len(allNodes)) + validateNodes(t, gotRegistry, wfNodes, expectedHashedCapabilities(t, gotRegistry, wfDon)) + validateNodes(t, gotRegistry, cwNodes, expectedHashedCapabilities(t, gotRegistry, cwDon)) + validateNodes(t, gotRegistry, assetNodes, expectedHashedCapabilities(t, gotRegistry, assetDon)) + + // check the dons + validateDon(t, gotRegistry, wfNodes, wfDon) + validateDon(t, gotRegistry, cwNodes, cwDon) + validateDon(t, gotRegistry, assetNodes, assetDon) + + if c.UseMCMS { + // TODO: mcms on all the chains, currently only on the registry chain. need to fix this for forwarders + t.Logf("Enabling MCMS registry chain %d", registryChainSel) + // deploy, configure and xfer ownership of MCMS + env, err = commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), + Config: map[uint64]commontypes.MCMSWithTimelockConfig{ + registryChainSel: { + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + }, + }, + }, + }) + require.NoError(t, err) + // extract the MCMS address + r, err := kslib.GetContractSets(lggr, &kslib.GetContractSetsRequest{ + Chains: map[uint64]deployment.Chain{ + registryChainSel: env.Chains[registryChainSel], + }, + AddressBook: env.ExistingAddresses, + }) + require.NoError(t, err) + mcms := r.ContractSets[registryChainSel].MCMSWithTimelockState + require.NotNil(t, mcms) + // transfer ownership of all contracts to the MCMS + env, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*gethwrappers.RBACTimelock{registryChainSel: mcms.Timelock}, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.AcceptAllOwnershipsProposal), + Config: &kschangeset.AcceptAllOwnershipRequest{ + ChainSelector: registryChainSel, + MinDelay: 0, + }, + }, + }) + require.NoError(t, err) + // ensure the MCMS is deployed + req = &keystone.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + } + contractSetsResp, err = keystone.GetContractSets(lggr, req) + require.NoError(t, err) + require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) + // check the mcms contract on registry chain + gotMCMS := contractSetsResp.ContractSets[registryChainSel].MCMSWithTimelockState + require.NoError(t, gotMCMS.Validate()) + } + return TestEnv{ + Env: env, + RegistrySelector: registryChainSel, + WFNodes: wfNodes, + CWNodes: cwNodes, + AssetNodes: assetNodes, + } +} + +func registryChain(t *testing.T, chains map[uint64]deployment.Chain) uint64 { + var registryChainSel uint64 = math.MaxUint64 + for sel := range chains { + if sel < registryChainSel { + registryChainSel = sel + } + } + return registryChainSel +} + +// validateInitialChainState checks that the initial chain state +// has the expected contracts deployed +func validateInitialChainState(t *testing.T, env deployment.Environment, registryChainSel uint64) { + ad := env.ExistingAddresses + // all contracts on registry chain + registryChainAddrs, err := ad.AddressesForChain(registryChainSel) + require.NoError(t, err) + require.Len(t, registryChainAddrs, 3) // registry, ocr3, forwarder + // only forwarder on non-home chain + for sel := range env.Chains { + chainAddrs, err := ad.AddressesForChain(sel) + require.NoError(t, err) + if sel != registryChainSel { + require.Len(t, chainAddrs, 1) + } else { + require.Len(t, chainAddrs, 3) + } + containsForwarder := false + for _, tv := range chainAddrs { + if tv.Type == keystone.KeystoneForwarder { + containsForwarder = true + break + } + } + require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) + } +} + +// validateNodes checks that the nodes exist and have the expected capabilities +func validateNodes(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, expectedHashedCaps [][32]byte) { + gotNodes, err := gotRegistry.GetNodesByP2PIds(nil, p2pIDs(t, maps.Keys(nodes))) + require.NoError(t, err) + require.Len(t, gotNodes, len(nodes)) + for _, n := range gotNodes { + require.Equal(t, expectedHashedCaps, n.HashedCapabilityIds) + } +} + +// validateDon checks that the don exists and has the expected capabilities +func validateDon(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, don kslib.DonCapabilities) { + gotDons, err := gotRegistry.GetDONs(nil) + require.NoError(t, err) + wantP2PID := sortedHash(p2pIDs(t, maps.Keys(nodes))) + found := false + for _, have := range gotDons { + gotP2PID := sortedHash(have.NodeP2PIds) + if gotP2PID == wantP2PID { + found = true + gotCapIDs := capIDs(t, have.CapabilityConfigurations) + require.Equal(t, expectedHashedCapabilities(t, gotRegistry, don), gotCapIDs) + break + } + } + require.True(t, found, "don not found in registry") +} + +func capIDs(t *testing.T, cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration) [][32]byte { + var out [][32]byte + for _, cfg := range cfgs { + out = append(out, cfg.CapabilityId) + } + return out +} + +func ptr[T any](t T) *T { + return &t +} + +func p2pIDs(t *testing.T, vals []string) [][32]byte { + var out [][32]byte + for _, v := range vals { + id, err := p2pkey.MakePeerID(v) + require.NoError(t, err) + out = append(out, id) + } + return out +} + +func expectedHashedCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, don kslib.DonCapabilities) [][32]byte { + out := make([][32]byte, len(don.Capabilities)) + var err error + for i, cap := range don.Capabilities { + out[i], err = registry.GetHashedCapabilityId(nil, cap.LabelledName, cap.Version) + require.NoError(t, err) + } + return out +} + +func sortedHash(p2pids [][32]byte) string { + sha256Hash := sha256.New() + sort.Slice(p2pids, func(i, j int) bool { + return bytes.Compare(p2pids[i][:], p2pids[j][:]) < 0 + }) + for _, id := range p2pids { + sha256Hash.Write(id[:]) + } + return hex.EncodeToString(sha256Hash.Sum(nil)) +} diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/internal/test/utils.go index df01266043a..6fe4a8f4a2e 100644 --- a/deployment/keystone/changeset/internal/test/utils.go +++ b/deployment/keystone/changeset/internal/test/utils.go @@ -158,7 +158,6 @@ func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry cc.Config = defaultCapConfig(t, ccfg.Capability) } var exists bool - //var cc kcr.CapabilitiesRegistryCapabilityConfiguration{} cc.CapabilityId, exists = capCache.Get(ccfg.Capability) require.True(t, exists, "capability not found in cache %v", ccfg.Capability) capConfigs = append(capConfigs, cc) diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index 374f7f06460..2aa26312eae 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" "golang.org/x/exp/maps" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" "google.golang.org/protobuf/proto" @@ -40,6 +41,7 @@ type ConfigureContractsRequest struct { Dons []DonCapabilities // externally sourced based on the environment OCR3Config *OracleConfigWithSecrets // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config + // TODO rm this option; unused DoContractDeploy bool // if false, the contracts are assumed to be deployed and the address book is used } @@ -75,6 +77,7 @@ func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureCo } addrBook := req.Env.ExistingAddresses + // TODO: KS-rm_deploy_opt remove this option; it's not used if req.DoContractDeploy { contractDeployCS, err := DeployContracts(req.Env, req.RegistryChainSel) if err != nil { @@ -320,6 +323,7 @@ func ConfigureForwardContracts(env *deployment.Environment, dons []RegisteredDon return nil } +// Depreciated: use changeset.ConfigureOCR3Contract instead // ocr3 contract on the registry chain for the wf dons func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, addrBook deployment.AddressBook, cfg *OracleConfigWithSecrets) error { registryChain, ok := env.Chains[chainSel] @@ -350,10 +354,11 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] } _, err := configureOCR3contract(configureOCR3Request{ - cfg: cfg, - chain: registryChain, - contract: contract, - nodes: don.Nodes, + cfg: cfg, + chain: registryChain, + contract: contract, + nodes: don.Nodes, + contractSet: &contracts, }) if err != nil { return fmt.Errorf("failed to configure OCR3 contract for don %s: %w", don.Name, err) @@ -364,6 +369,7 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] type ConfigureOCR3Resp struct { OCR2OracleConfig + Proposal *timelock.MCMSWithTimelockProposal } type ConfigureOCR3Config struct { @@ -371,8 +377,11 @@ type ConfigureOCR3Config struct { NodeIDs []string OCR3Config *OracleConfigWithSecrets DryRun bool + + UseMCMS bool } +// Depreciated: use changeset.ConfigureOCR3Contract instead func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3Config) (*ConfigureOCR3Resp, error) { prefix := "" if cfg.DryRun { @@ -403,17 +412,20 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C return nil, err } r, err := configureOCR3contract(configureOCR3Request{ - cfg: cfg.OCR3Config, - chain: registryChain, - contract: contract, - nodes: nodes, - dryRun: cfg.DryRun, + cfg: cfg.OCR3Config, + chain: registryChain, + contract: contract, + nodes: nodes, + dryRun: cfg.DryRun, + contractSet: &contracts, + useMCMS: cfg.UseMCMS, }) if err != nil { return nil, err } return &ConfigureOCR3Resp{ OCR2OracleConfig: r.ocrConfig, + Proposal: r.proposal, }, nil } diff --git a/deployment/keystone/deploy_test.go b/deployment/keystone/deploy_test.go index b02497c22fa..fd59f3007fd 100644 --- a/deployment/keystone/deploy_test.go +++ b/deployment/keystone/deploy_test.go @@ -1,7 +1,6 @@ package keystone_test import ( - "context" "encoding/json" "fmt" "os" @@ -22,192 +21,9 @@ import ( kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/stretchr/testify/assert" - "github.com/test-go/testify/require" - "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" + "github.com/stretchr/testify/require" ) -func TestDeploy(t *testing.T) { - lggr := logger.Test(t) - ctx := tests.Context(t) - - // sepolia; all nodes are on the this chain - sepoliaChainId := uint64(11155111) - sepoliaArbitrumChainId := uint64(421614) - - sepoliaChainSel, err := chainsel.SelectorFromChainId(sepoliaChainId) - require.NoError(t, err) - // sepoliaArbitrumChainSel, err := chainsel.SelectorFromChainId(sepoliaArbitrumChainId) - // require.NoError(t, err) - // aptos-testnet - aptosChainSel := chainsel.AptosChainIdToChainSelector()[2] - - crConfig := deployment.CapabilityRegistryConfig{ - EVMChainID: sepoliaChainId, - Contract: [20]byte{}, - } - - evmChains := memory.NewMemoryChainsWithChainIDs(t, []uint64{sepoliaChainId, sepoliaArbitrumChainId}) - aptosChain := memory.NewMemoryChain(t, aptosChainSel) - - wfChains := map[uint64]deployment.Chain{} - wfChains[sepoliaChainSel] = evmChains[sepoliaChainSel] - wfChains[aptosChainSel] = aptosChain - wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, 4, 0, crConfig) - require.Len(t, wfNodes, 4) - - cwNodes := memory.NewNodes(t, zapcore.InfoLevel, evmChains, 4, 0, crConfig) - - assetChains := map[uint64]deployment.Chain{} - assetChains[sepoliaChainSel] = evmChains[sepoliaChainSel] - assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, 4, 0, crConfig) - require.Len(t, assetNodes, 4) - - // TODO: partition nodes into multiple nops - - wfDon := keystone.DonCapabilities{ - Name: keystone.WFDonName, - Nops: []keystone.NOP{ - { - Name: "nop 1", - Nodes: maps.Keys(wfNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, - } - cwDon := keystone.DonCapabilities{ - Name: keystone.TargetDonName, - Nops: []keystone.NOP{ - { - Name: "nop 2", - Nodes: maps.Keys(cwNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, - } - assetDon := keystone.DonCapabilities{ - Name: keystone.StreamDonName, - Nops: []keystone.NOP{ - { - Name: "nop 3", - Nodes: maps.Keys(assetNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, - } - - allChains := make(map[uint64]deployment.Chain) - maps.Copy(allChains, evmChains) - // allChains[aptosChainSel] = aptosChain - - allNodes := make(map[string]memory.Node) - maps.Copy(allNodes, wfNodes) - maps.Copy(allNodes, cwNodes) - maps.Copy(allNodes, assetNodes) - env := memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, allChains, allNodes) - - var ocr3Config = keystone.OracleConfigWithSecrets{ - OracleConfig: keystone.OracleConfig{ - MaxFaultyOracles: len(wfNodes) / 3, - }, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - } - - // explicitly deploy the contracts - cs, err := keystone.DeployContracts(&env, sepoliaChainSel) - require.NoError(t, err) - env.ExistingAddresses = cs.AddressBook - deployReq := keystone.ConfigureContractsRequest{ - RegistryChainSel: sepoliaChainSel, - Env: &env, - OCR3Config: &ocr3Config, - Dons: []keystone.DonCapabilities{wfDon, cwDon, assetDon}, - DoContractDeploy: false, - } - deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) - require.NoError(t, err) - ad := deployResp.Changeset.AddressBook - addrs, err := ad.Addresses() - require.NoError(t, err) - lggr.Infow("Deployed Keystone contracts", "address book", addrs) - - // all contracts on home chain - homeChainAddrs, err := ad.AddressesForChain(sepoliaChainSel) - require.NoError(t, err) - require.Len(t, homeChainAddrs, 3) - // only forwarder on non-home chain - for sel := range env.Chains { - chainAddrs, err := ad.AddressesForChain(sel) - require.NoError(t, err) - if sel != sepoliaChainSel { - require.Len(t, chainAddrs, 1) - } else { - require.Len(t, chainAddrs, 3) - } - containsForwarder := false - for _, tv := range chainAddrs { - if tv.Type == keystone.KeystoneForwarder { - containsForwarder = true - break - } - } - require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) - } - req := &keystone.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: ad, - } - - contractSetsResp, err := keystone.GetContractSets(lggr, req) - require.NoError(t, err) - require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) - // check the registry - regChainContracts, ok := contractSetsResp.ContractSets[sepoliaChainSel] - require.True(t, ok) - gotRegistry := regChainContracts.CapabilitiesRegistry - require.NotNil(t, gotRegistry) - // contract reads - gotDons, err := gotRegistry.GetDONs(&bind.CallOpts{}) - if err != nil { - err = keystone.DecodeErr(kcr.CapabilitiesRegistryABI, err) - require.Fail(t, fmt.Sprintf("failed to get Dons from registry at %s: %s", gotRegistry.Address().String(), err)) - } - require.NoError(t, err) - assert.Len(t, gotDons, len(deployReq.Dons)) - - for n, info := range deployResp.DonInfos { - found := false - for _, gdon := range gotDons { - if gdon.Id == info.Id { - found = true - assert.EqualValues(t, info, gdon) - break - } - } - require.True(t, found, "don %s not found in registry", n) - } - // check the forwarder - for _, cs := range contractSetsResp.ContractSets { - forwarder := cs.Forwarder - require.NotNil(t, forwarder) - // any read to ensure that the contract is deployed correctly - _, err := forwarder.Owner(&bind.CallOpts{}) - require.NoError(t, err) - // TODO expand this test; there is no get method on the forwarder so unclear how to test it - } - // check the ocr3 contract - for chainSel, cs := range contractSetsResp.ContractSets { - if chainSel != sepoliaChainSel { - require.Nil(t, cs.OCR3) - continue - } - require.NotNil(t, cs.OCR3) - // any read to ensure that the contract is deployed correctly - _, err := cs.OCR3.LatestConfigDetails(&bind.CallOpts{}) - require.NoError(t, err) - } -} - // TODO: Deprecated, remove everything below that leverages CLO func nodeOperatorsToIDs(t *testing.T, nops []*models.NodeOperator) (nodeIDs []keystone.NOP) { diff --git a/deployment/keystone/ocr3config.go b/deployment/keystone/ocr3config.go index a281a69ed8a..c4f8714b113 100644 --- a/deployment/keystone/ocr3config.go +++ b/deployment/keystone/ocr3config.go @@ -8,6 +8,8 @@ import ( "encoding/json" "errors" "fmt" + "math/big" + "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -16,7 +18,11 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" @@ -107,6 +113,44 @@ func (c OCR2OracleConfig) MarshalJSON() ([]byte, error) { return json.Marshal(alias) } +func (c *OCR2OracleConfig) UnmarshalJSON(data []byte) error { + type aliasT struct { + Signers []string + Transmitters []string + F uint8 + OnchainConfig string + OffchainConfigVersion uint64 + OffchainConfig string + } + var alias aliasT + err := json.Unmarshal(data, &alias) + if err != nil { + return fmt.Errorf("failed to unmarshal OCR2OracleConfig alias: %w", err) + } + c.F = alias.F + c.OffchainConfigVersion = alias.OffchainConfigVersion + c.Signers = make([][]byte, len(alias.Signers)) + for i, signer := range alias.Signers { + c.Signers[i], err = hex.DecodeString(strings.TrimPrefix(signer, "0x")) + if err != nil { + return fmt.Errorf("failed to decode signer: %w", err) + } + } + c.Transmitters = make([]common.Address, len(alias.Transmitters)) + for i, transmitter := range alias.Transmitters { + c.Transmitters[i] = common.HexToAddress(transmitter) + } + c.OnchainConfig, err = hex.DecodeString(strings.TrimPrefix(alias.OnchainConfig, "0x")) + if err != nil { + return fmt.Errorf("failed to decode onchain config: %w", err) + } + c.OffchainConfig, err = hex.DecodeString(strings.TrimPrefix(alias.OffchainConfig, "0x")) + if err != nil { + return fmt.Errorf("failed to decode offchain config: %w", err) + } + return nil +} + func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (OCR2OracleConfig, error) { onchainPubKeys := [][]byte{} allPubKeys := map[string]any{} @@ -245,6 +289,9 @@ type configureOCR3Request struct { contract *kocr3.OCR3Capability nodes []deployment.Node dryRun bool + + useMCMS bool + contractSet *ContractSet } func (r configureOCR3Request) generateOCR3Config() (OCR2OracleConfig, error) { @@ -254,6 +301,7 @@ func (r configureOCR3Request) generateOCR3Config() (OCR2OracleConfig, error) { type configureOCR3Response struct { ocrConfig OCR2OracleConfig + proposal *timelock.MCMSWithTimelockProposal } func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, error) { @@ -265,9 +313,15 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er return nil, fmt.Errorf("failed to generate OCR3 config: %w", err) } if req.dryRun { - return &configureOCR3Response{ocrConfig}, nil + return &configureOCR3Response{ocrConfig, nil}, nil } - tx, err := req.contract.SetConfig(req.chain.DeployerKey, + + txOpt := req.chain.DeployerKey + if req.useMCMS { + txOpt = deployment.SimTransactOpts() + } + + tx, err := req.contract.SetConfig(txOpt, ocrConfig.Signers, ocrConfig.Transmitters, ocrConfig.F, @@ -277,12 +331,45 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er ) if err != nil { err = DecodeErr(kocr3.OCR3CapabilityABI, err) - return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s using mcms: %T: %w", req.contract.Address().String(), req.useMCMS, err) } - _, err = req.chain.Confirm(tx) - if err != nil { - err = DecodeErr(kocr3.OCR3CapabilityABI, err) - return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + + var proposal *timelock.MCMSWithTimelockProposal + if !req.useMCMS { + _, err = req.chain.Confirm(tx) + if err != nil { + err = DecodeErr(kocr3.OCR3CapabilityABI, err) + return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + } + } else { + ops := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(req.chain.Selector), + Batch: []mcms.Operation{ + { + To: req.contract.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + } + timelocksPerChain := map[uint64]common.Address{ + req.chain.Selector: req.contractSet.Timelock.Address(), + } + proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ + req.chain.Selector: req.contractSet.ProposerMcm, + } + + proposal, err = proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{ops}, + "proposal to set ocr3 config", + 0, + ) + if err != nil { + return nil, fmt.Errorf("failed to build proposal: %w", err) + } } - return &configureOCR3Response{ocrConfig}, nil + + return &configureOCR3Response{ocrConfig, proposal}, nil } diff --git a/deployment/keystone/state.go b/deployment/keystone/state.go index 68f2ab97a5d..1e6ffdd895f 100644 --- a/deployment/keystone/state.go +++ b/deployment/keystone/state.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" "github.com/smartcontractkit/chainlink/deployment/keystone/view" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" @@ -25,11 +26,26 @@ type GetContractSetsResponse struct { } type ContractSet struct { + commonchangeset.MCMSWithTimelockState OCR3 *ocr3_capability.OCR3Capability Forwarder *forwarder.KeystoneForwarder CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry } +func (cs ContractSet) TransferableContracts() []common.Address { + var out []common.Address + if cs.OCR3 != nil { + out = append(out, cs.OCR3.Address()) + } + if cs.Forwarder != nil { + out = append(out, cs.Forwarder.Address()) + } + if cs.CapabilitiesRegistry != nil { + out = append(out, cs.CapabilitiesRegistry.Address()) + } + return out +} + func (cs ContractSet) View() (view.KeystoneChainView, error) { out := view.NewKeystoneChainView() if cs.CapabilitiesRegistry != nil { @@ -62,6 +78,11 @@ func GetContractSets(lggr logger.Logger, req *GetContractSetsRequest) (*GetContr func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*ContractSet, error) { var out ContractSet + mcmsWithTimelock, err := commonchangeset.LoadMCMSWithTimelockState(chain, addresses) + if err != nil { + return nil, fmt.Errorf("failed to load mcms contract: %w", err) + } + out.MCMSWithTimelockState = *mcmsWithTimelock for addr, tv := range addresses { // todo handle versions From ef3fd2fa844c1051256d806a5673183f3ee8dd39 Mon Sep 17 00:00:00 2001 From: Justin Kaseman Date: Thu, 5 Dec 2024 11:03:08 -0800 Subject: [PATCH 20/55] Remove built in capabilities from local registry on Close (#15471) * Remove built in capabilities from local registry on Close * Add 1 sec timeout to close * Return error instead of logging --- core/capabilities/compute/compute.go | 10 ++++++++++ core/capabilities/registry.go | 15 +++++++++++++++ core/capabilities/webapi/target/target.go | 7 +++++++ core/capabilities/webapi/trigger/trigger.go | 7 +++++++ core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- core/services/relay/evm/evm.go | 9 +++++++++ deployment/go.mod | 2 +- deployment/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 ++-- 15 files changed, 63 insertions(+), 15 deletions(-) diff --git a/core/capabilities/compute/compute.go b/core/capabilities/compute/compute.go index 32e43e8d62e..316e4f00eea 100644 --- a/core/capabilities/compute/compute.go +++ b/core/capabilities/compute/compute.go @@ -273,9 +273,19 @@ func (c *Compute) worker(ctx context.Context) { } func (c *Compute) Close() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + c.modules.close() close(c.stopCh) + + err := c.registry.Remove(ctx, CapabilityIDCompute) + if err != nil { + return err + } + c.wg.Wait() + return nil } diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 47285505805..7038dcdb4b7 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -193,6 +193,21 @@ func (r *Registry) Add(ctx context.Context, c capabilities.BaseCapability) error return nil } +// Add adds a capability to the registry. +func (r *Registry) Remove(ctx context.Context, id string) error { + r.mu.Lock() + defer r.mu.Unlock() + + _, ok := r.m[id] + if !ok { + return fmt.Errorf("unable to remove, capability not found: %s", id) + } + + delete(r.m, id) + r.lggr.Infow("capability removed", "id", id) + return nil +} + // NewRegistry returns a new Registry. func NewRegistry(lggr logger.Logger) *Registry { return &Registry{ diff --git a/core/capabilities/webapi/target/target.go b/core/capabilities/webapi/target/target.go index 4576f95a54e..b211e0fe837 100644 --- a/core/capabilities/webapi/target/target.go +++ b/core/capabilities/webapi/target/target.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -57,6 +58,12 @@ func (c *Capability) Start(ctx context.Context) error { } func (c *Capability) Close() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + err := c.registry.Remove(ctx, c.capabilityInfo.ID) + if err != nil { + return err + } return nil } diff --git a/core/capabilities/webapi/trigger/trigger.go b/core/capabilities/webapi/trigger/trigger.go index c607f0dbb6f..712cf38a4cc 100644 --- a/core/capabilities/webapi/trigger/trigger.go +++ b/core/capabilities/webapi/trigger/trigger.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "sync" + "time" ethCommon "github.com/ethereum/go-ethereum/common" @@ -256,6 +257,12 @@ func (h *triggerConnectorHandler) Start(ctx context.Context) error { } func (h *triggerConnectorHandler) Close() error { return h.StopOnce("GatewayConnectorServiceWrapper", func() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + err := h.registry.Remove(ctx, h.ID) + if err != nil { + return err + } return nil }) } diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 7e846dcd545..afb91f5425f 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 0c60e0596d7..ec3b5c496d3 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1142,8 +1142,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 847b5bb72d9..e60dbe1bfdb 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -12,6 +12,7 @@ import ( "net/http" "strings" "sync" + "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -259,6 +260,14 @@ func (r *Relayer) Close() error { cs := make([]io.Closer, 0, 2) if r.triggerCapability != nil { cs = append(cs, r.triggerCapability) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + err := r.capabilitiesRegistry.Remove(ctx, r.triggerCapability.ID) + if err != nil { + return err + } } cs = append(cs, r.chain) return services.MultiCloser(cs).Close() diff --git a/deployment/go.mod b/deployment/go.mod index e1d51c46433..1fc60d00bfb 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -23,7 +23,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/deployment/go.sum b/deployment/go.sum index a2dc68f9dc6..718c1d5c2a4 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1411,8 +1411,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/go.mod b/go.mod index 75557e56d2b..3e75f03ae35 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db github.com/smartcontractkit/chainlink-feeds v0.1.1 diff --git a/go.sum b/go.sum index fb8eab948e4..f9e188b628b 100644 --- a/go.sum +++ b/go.sum @@ -1125,8 +1125,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 621c1c0941b..93e6d93f5fe 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -39,7 +39,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 272cc05e0a5..dca5ee213fc 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1432,8 +1432,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 30eb132d24f..58117f967fc 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,7 +17,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 5fbafb202bc..ab2c403d7ac 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1423,8 +1423,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 h1:atCZ1jol7a+tdtgU/wNqXgliBun5H7BjGBicGL8Tj6o= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= From 90a82cbc749361588c122a4839fc524871a3cbec Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:27:08 -0800 Subject: [PATCH 21/55] [Keystone][Deployment] Minor refactor to expose RegisterNodes publicly (#15529) --- deployment/keystone/deploy.go | 80 ++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index 2aa26312eae..dc61e0491b6 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -256,13 +256,13 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon lggr.Infow("registered node operators", "nops", nopsResp.Nops) // register nodes - nodesResp, err := registerNodes(lggr, ®isterNodesRequest{ - registry: registry, - chain: registryChain, - nopToNodeIDs: nopsToNodeIDs, - donToNodes: donToNodes, - donToCapabilities: capabilitiesResp.DonToCapabilities, - nops: nopsResp.Nops, + nodesResp, err := RegisterNodes(lggr, &RegisterNodesRequest{ + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + NopToNodeIDs: nopsToNodeIDs, + DonToNodes: donToNodes, + DonToCapabilities: capabilitiesResp.DonToCapabilities, + Nops: nopsResp.Nops, }) if err != nil { return nil, fmt.Errorf("failed to register nodes: %w", err) @@ -445,6 +445,21 @@ type RegisteredCapability struct { ID [32]byte } +func FromCapabilitiesRegistryCapability(cap *kcr.CapabilitiesRegistryCapability, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { + registry, _, err := GetRegistryContract(&e, registryChainSelector, e.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + if err != nil { + return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) + } + return &RegisteredCapability{ + CapabilitiesRegistryCapability: *cap, + ID: id, + }, nil +} + // RegisterCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) (*RegisterCapabilitiesResponse, error) { if len(req.DonToCapabilities) == 0 { @@ -629,34 +644,39 @@ func DecodeErr(encodedABI string, err error) error { } // register nodes -type registerNodesRequest struct { - registry *kcr.CapabilitiesRegistry - chain deployment.Chain - nopToNodeIDs map[kcr.CapabilitiesRegistryNodeOperator][]string - donToNodes map[string][]deployment.Node - donToCapabilities map[string][]RegisteredCapability - nops []*kcr.CapabilitiesRegistryNodeOperatorAdded +type RegisterNodesRequest struct { + Env *deployment.Environment + RegistryChainSelector uint64 + NopToNodeIDs map[kcr.CapabilitiesRegistryNodeOperator][]string + DonToNodes map[string][]deployment.Node + DonToCapabilities map[string][]RegisteredCapability + Nops []*kcr.CapabilitiesRegistryNodeOperatorAdded } -type registerNodesResponse struct { +type RegisterNodesResponse struct { nodeIDToParams map[string]kcr.CapabilitiesRegistryNodeParams } // registerNodes registers the nodes with the registry. it assumes that the deployer key in the Chain // can sign the transactions update the contract state // TODO: 467 refactor to support MCMS. Specifically need to separate the call data generation from the actual contract call -func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNodesResponse, error) { +func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNodesResponse, error) { + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + var count int - for _, nodes := range req.nopToNodeIDs { + for _, nodes := range req.NopToNodeIDs { count += len(nodes) } lggr.Infow("registering nodes...", "len", count) nodeToRegisterNop := make(map[string]*kcr.CapabilitiesRegistryNodeOperatorAdded) - for _, nop := range req.nops { + for _, nop := range req.Nops { n := kcr.CapabilitiesRegistryNodeOperator{ Name: nop.Name, Admin: nop.Admin, } - nodeIDs := req.nopToNodeIDs[n] + nodeIDs := req.NopToNodeIDs[n] for _, nodeID := range nodeIDs { _, exists := nodeToRegisterNop[nodeID] if !exists { @@ -666,7 +686,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } // TODO: deduplicate everywhere - registryChainID, err := chainsel.ChainIdFromSelector(req.chain.Selector) + registryChainID, err := chainsel.ChainIdFromSelector(registryChain.Selector) if err != nil { return nil, err } @@ -676,10 +696,10 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } nodeIDToParams := make(map[string]kcr.CapabilitiesRegistryNodeParams) - for don, nodes := range req.donToNodes { - caps, ok := req.donToCapabilities[don] + for don, nodes := range req.DonToNodes { + caps, ok := req.DonToCapabilities[don] if !ok { - return nil, fmt.Errorf("capabilities not found for node operator %s", don) + return nil, fmt.Errorf("capabilities not found for don %s", don) } var hashedCapabilityIds [][32]byte for _, cap := range caps { @@ -700,7 +720,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode if !ok { evmCC, exists := n.SelToOCRConfig[registryChainDetails] if !exists { - return nil, fmt.Errorf("config for selector not found on node: %v", req.chain.Selector) + return nil, fmt.Errorf("config for selector %v not found on node (id: %s, name: %s)", registryChain.Selector, n.NodeID, n.Name) } var signer [32]byte copy(signer[:], evmCC.OnchainPublicKey) @@ -738,8 +758,8 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode for _, v := range nodeIDToParams { uniqueNodeParams = append(uniqueNodeParams, v) } - lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams)) - tx, err := req.registry.AddNodes(req.chain.DeployerKey, uniqueNodeParams) + lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams), "params", uniqueNodeParams) + tx, err := registry.AddNodes(registryChain.DeployerKey, uniqueNodeParams) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) // no typed errors in the abi, so we have to do string matching @@ -749,7 +769,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } lggr.Warn("nodes already exist, falling back to 1-by-1") for _, singleNodeParams := range uniqueNodeParams { - tx, err = req.registry.AddNodes(req.chain.DeployerKey, []kcr.CapabilitiesRegistryNodeParams{singleNodeParams}) + tx, err = registry.AddNodes(registryChain.DeployerKey, []kcr.CapabilitiesRegistryNodeParams{singleNodeParams}) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) if strings.Contains(err.Error(), "NodeAlreadyExists") { @@ -759,7 +779,7 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode return nil, fmt.Errorf("failed to call AddNode for node with p2pid %v: %w", singleNodeParams.P2pId, err) } // 1-by-1 tx is pending and we need to wait for it to be mined - _, err = req.chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNode of p2pid node %v transaction %s: %w", singleNodeParams.P2pId, tx.Hash().String(), err) } @@ -767,12 +787,12 @@ func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNode } } else { // the bulk add tx is pending and we need to wait for it to be mined - _, err = req.chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNode confirm transaction %s: %w", tx.Hash().String(), err) } } - return ®isterNodesResponse{ + return &RegisterNodesResponse{ nodeIDToParams: nodeIDToParams, }, nil } From c3c926fc604fa34eac50cec34cb7acbf2bc907b0 Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 5 Dec 2024 21:13:43 +0000 Subject: [PATCH 22/55] [CAPPL-338] Move to a common method to generate a workflowID (#15513) * [CAPPL-338] Harmonize generate workflow ID implementations * Linting --- core/scripts/go.mod | 4 +- core/scripts/go.sum | 4 +- core/services/chainlink/application.go | 11 +-- core/services/workflows/syncer/fetcher.go | 2 +- core/services/workflows/syncer/handler.go | 32 ++++----- .../services/workflows/syncer/handler_test.go | 69 ++++++++----------- .../workflows/syncer/workflow_registry.go | 4 +- deployment/go.mod | 4 +- deployment/go.sum | 4 +- go.mod | 4 +- go.sum | 4 +- integration-tests/go.mod | 4 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 4 +- integration-tests/load/go.sum | 4 +- 15 files changed, 80 insertions(+), 78 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index afb91f5425f..65d63f2a1df 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -2,6 +2,8 @@ module github.com/smartcontractkit/chainlink/core/scripts go 1.23.3 +toolchain go1.23.4 + // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -24,7 +26,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index ec3b5c496d3..1f1374bc11d 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1142,8 +1142,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 863c5d915e9..29473c4d932 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -300,18 +300,19 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("expected 1 key, got %d", len(keys)) } - fetcher := syncer.NewFetcherService(globalLogger, gatewayConnectorWrapper) + lggr := globalLogger.Named("WorkflowRegistrySyncer") + fetcher := syncer.NewFetcherService(lggr, gatewayConnectorWrapper) - eventHandler := syncer.NewEventHandler(globalLogger, syncer.NewWorkflowRegistryDS(opts.DS, globalLogger), - fetcher.Fetch, workflowstore.NewDBStore(opts.DS, globalLogger, clockwork.NewRealClock()), opts.CapabilitiesRegistry, + eventHandler := syncer.NewEventHandler(lggr, syncer.NewWorkflowRegistryDS(opts.DS, globalLogger), + fetcher.Fetch, workflowstore.NewDBStore(opts.DS, lggr, clockwork.NewRealClock()), opts.CapabilitiesRegistry, custmsg.NewLabeler(), clockwork.NewRealClock(), keys[0]) - loader := syncer.NewWorkflowRegistryContractLoader(globalLogger, cfg.Capabilities().WorkflowRegistry().Address(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + loader := syncer.NewWorkflowRegistryContractLoader(lggr, cfg.Capabilities().WorkflowRegistry().Address(), func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { return relayer.NewContractReader(ctx, bytes) }, eventHandler) globalLogger.Debugw("Creating WorkflowRegistrySyncer") - wfSyncer := syncer.NewWorkflowRegistry(globalLogger, func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { + wfSyncer := syncer.NewWorkflowRegistry(lggr, func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { return relayer.NewContractReader(ctx, bytes) }, cfg.Capabilities().WorkflowRegistry().Address(), syncer.WorkflowEventPollerConfig{ diff --git a/core/services/workflows/syncer/fetcher.go b/core/services/workflows/syncer/fetcher.go index 357f7518635..fdd0134909d 100644 --- a/core/services/workflows/syncer/fetcher.go +++ b/core/services/workflows/syncer/fetcher.go @@ -44,7 +44,7 @@ func (s *FetcherService) Start(ctx context.Context) error { return s.StartOnce("FetcherService", func() error { connector := s.wrapper.GetGatewayConnector() - outgoingConnectorLggr := s.lggr.Named("WorkflowSyncer") + outgoingConnectorLggr := s.lggr.Named("OutgoingConnectorHandler") webAPIConfig := webapi.ServiceConfig{ RateLimiter: common.RateLimiterConfig{ diff --git a/core/services/workflows/syncer/handler.go b/core/services/workflows/syncer/handler.go index 5cfce71d56c..46dcd21ed90 100644 --- a/core/services/workflows/syncer/handler.go +++ b/core/services/workflows/syncer/handler.go @@ -1,8 +1,8 @@ package syncer import ( + "bytes" "context" - "crypto/sha256" "encoding/hex" "encoding/json" "errors" @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/custmsg" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" "github.com/smartcontractkit/chainlink-common/pkg/workflows/secrets" "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -263,6 +264,7 @@ func (h *eventHandler) Handle(ctx context.Context, event Event) error { return err } + h.lggr.Debugw("handled force update secrets events for URL hash", "urlHash", payload.SecretsURLHash) return nil case WorkflowRegisteredEvent: payload, ok := event.GetData().(WorkflowRegistryWorkflowRegisteredV1) @@ -282,7 +284,7 @@ func (h *eventHandler) Handle(ctx context.Context, event Event) error { return err } - h.lggr.Debugf("workflow 0x%x registered and started", wfID) + h.lggr.Debugw("handled workflow registration event", "workflowID", wfID) return nil case WorkflowUpdatedEvent: payload, ok := event.GetData().(WorkflowRegistryWorkflowUpdatedV1) @@ -302,6 +304,7 @@ func (h *eventHandler) Handle(ctx context.Context, event Event) error { return err } + h.lggr.Debugw("handled workflow updated event", "workflowID", newWorkflowID) return nil case WorkflowPausedEvent: payload, ok := event.GetData().(WorkflowRegistryWorkflowPausedV1) @@ -321,6 +324,7 @@ func (h *eventHandler) Handle(ctx context.Context, event Event) error { logCustMsg(ctx, cma, fmt.Sprintf("failed to handle workflow paused event: %v", err), h.lggr) return err } + h.lggr.Debugw("handled workflow paused event", "workflowID", wfID) return nil case WorkflowActivatedEvent: payload, ok := event.GetData().(WorkflowRegistryWorkflowActivatedV1) @@ -340,6 +344,7 @@ func (h *eventHandler) Handle(ctx context.Context, event Event) error { return err } + h.lggr.Debugw("handled workflow activated event", "workflowID", wfID) return nil case WorkflowDeletedEvent: payload, ok := event.GetData().(WorkflowRegistryWorkflowDeletedV1) @@ -360,6 +365,7 @@ func (h *eventHandler) Handle(ctx context.Context, event Event) error { return err } + h.lggr.Debugw("handled workflow deleted event", "workflowID", wfID) return nil default: return fmt.Errorf("event type unsupported: %v", event.GetEventType()) @@ -371,8 +377,6 @@ func (h *eventHandler) workflowRegisteredEvent( ctx context.Context, payload WorkflowRegistryWorkflowRegisteredV1, ) error { - wfID := hex.EncodeToString(payload.WorkflowID[:]) - // Download the contents of binaryURL, configURL and secretsURL and cache them locally. binary, err := h.fetcher(ctx, payload.BinaryURL) if err != nil { @@ -390,11 +394,14 @@ func (h *eventHandler) workflowRegisteredEvent( } // Calculate the hash of the binary and config files - hash := workflowID(binary, config, []byte(payload.SecretsURL)) + hash, err := pkgworkflows.GenerateWorkflowID(payload.Owner, binary, config, payload.SecretsURL) + if err != nil { + return fmt.Errorf("failed to generate workflow id: %w", err) + } // Pre-check: verify that the workflowID matches; if it doesn’t abort and log an error via Beholder. - if hash != wfID { - return fmt.Errorf("workflowID mismatch: %s != %s", hash, wfID) + if !bytes.Equal(hash[:], payload.WorkflowID[:]) { + return fmt.Errorf("workflowID mismatch: %x != %x", hash, payload.WorkflowID) } // Save the workflow secrets @@ -409,6 +416,7 @@ func (h *eventHandler) workflowRegisteredEvent( status = job.WorkflowSpecStatusPaused } + wfID := hex.EncodeToString(payload.WorkflowID[:]) entry := &job.WorkflowSpec{ Workflow: hex.EncodeToString(binary), Config: string(config), @@ -425,6 +433,7 @@ func (h *eventHandler) workflowRegisteredEvent( } if status != job.WorkflowSpecStatusActive { + h.lggr.Debugw("workflow is marked as paused, so not starting it", "workflow", wfID) return nil } @@ -611,15 +620,6 @@ func (h *eventHandler) tryEngineCleanup(wfID string) error { return nil } -// workflowID returns a hex encoded sha256 hash of the wasm, config and secretsURL. -func workflowID(wasm, config, secretsURL []byte) string { - sum := sha256.New() - sum.Write(wasm) - sum.Write(config) - sum.Write(secretsURL) - return hex.EncodeToString(sum.Sum(nil)) -} - // logCustMsg emits a custom message to the external sink and logs an error if that fails. func logCustMsg(ctx context.Context, cma custmsg.MessageEmitter, msg string, log logger.Logger) { err := cma.Emit(ctx, msg) diff --git a/core/services/workflows/syncer/handler_test.go b/core/services/workflows/syncer/handler_test.go index f5a915e48ab..bb0a61aea4d 100644 --- a/core/services/workflows/syncer/handler_test.go +++ b/core/services/workflows/syncer/handler_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/smartcontractkit/chainlink-common/pkg/custmsg" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" "github.com/smartcontractkit/chainlink-common/pkg/workflows/secrets" "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -194,16 +195,12 @@ func Test_workflowRegisteredHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) - - b, err := hex.DecodeString(giveWFID) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) paused := WorkflowRegistryWorkflowRegisteredV1{ Status: uint8(1), - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, Owner: wfOwner, WorkflowName: "workflow-name", BinaryURL: binaryURL, @@ -250,16 +247,14 @@ func Test_workflowRegisteredHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) + require.NoError(t, err) - b, err := hex.DecodeString(giveWFID) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) active := WorkflowRegistryWorkflowRegisteredV1{ Status: uint8(0), - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, Owner: wfOwner, WorkflowName: "workflow-name", BinaryURL: binaryURL, @@ -291,7 +286,7 @@ func Test_workflowRegisteredHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err := h.engineRegistry.Get(giveWFID) + engine, err := h.engineRegistry.Get(hex.EncodeToString(giveWFID[:])) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) @@ -321,16 +316,14 @@ func Test_workflowDeletedHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) - b, err := hex.DecodeString(giveWFID) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) + wfIDs := hex.EncodeToString(giveWFID[:]) active := WorkflowRegistryWorkflowRegisteredV1{ Status: uint8(0), - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, Owner: wfOwner, WorkflowName: "workflow-name", BinaryURL: binaryURL, @@ -362,13 +355,13 @@ func Test_workflowDeletedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err := h.engineRegistry.Get(giveWFID) + engine, err := h.engineRegistry.Get(wfIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) deleteEvent := WorkflowRegistryWorkflowDeletedV1{ - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", DonID: 1, @@ -381,7 +374,7 @@ func Test_workflowDeletedHandler(t *testing.T) { require.Error(t, err) // Verify the engine is deleted - _, err = h.engineRegistry.Get(giveWFID) + _, err = h.engineRegistry.Get(wfIDs) require.Error(t, err) }) } @@ -412,22 +405,20 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { }) ) - giveWFID := workflowID(binary, config, []byte(secretsURL)) - updatedWFID := workflowID(binary, updateConfig, []byte(secretsURL)) + giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) + require.NoError(t, err) + updatedWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, updateConfig, secretsURL) + require.NoError(t, err) - b, err := hex.DecodeString(giveWFID) require.NoError(t, err) - wfID := make([]byte, 32) - copy(wfID, b) + wfIDs := hex.EncodeToString(giveWFID[:]) - b, err = hex.DecodeString(updatedWFID) require.NoError(t, err) - newWFID := make([]byte, 32) - copy(newWFID, b) + newWFIDs := hex.EncodeToString(updatedWFID[:]) active := WorkflowRegistryWorkflowRegisteredV1{ Status: uint8(0), - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, Owner: wfOwner, WorkflowName: "workflow-name", BinaryURL: binaryURL, @@ -459,14 +450,14 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err := h.engineRegistry.Get(giveWFID) + engine, err := h.engineRegistry.Get(wfIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) // create a paused event pauseEvent := WorkflowRegistryWorkflowPausedV1{ - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", DonID: 1, @@ -482,12 +473,12 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusPaused, dbSpec.Status) // Verify the engine is removed - _, err = h.engineRegistry.Get(giveWFID) + _, err = h.engineRegistry.Get(wfIDs) require.Error(t, err) // create an activated workflow event activatedEvent := WorkflowRegistryWorkflowActivatedV1{ - WorkflowID: [32]byte(wfID), + WorkflowID: giveWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", DonID: 1, @@ -504,15 +495,15 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) // Verify the engine is started - engine, err = h.engineRegistry.Get(giveWFID) + engine, err = h.engineRegistry.Get(wfIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) // create an updated event updatedEvent := WorkflowRegistryWorkflowUpdatedV1{ - OldWorkflowID: [32]byte(wfID), - NewWorkflowID: [32]byte(newWFID), + OldWorkflowID: giveWFID, + NewWorkflowID: updatedWFID, WorkflowOwner: wfOwner, WorkflowName: "workflow-name", BinaryURL: binaryURL, @@ -529,16 +520,16 @@ func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) require.Equal(t, "workflow-name", dbSpec.WorkflowName) require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - require.Equal(t, hex.EncodeToString(newWFID), dbSpec.WorkflowID) + require.Equal(t, newWFIDs, dbSpec.WorkflowID) require.Equal(t, newConfigURL, dbSpec.ConfigURL) require.Equal(t, string(updateConfig), dbSpec.Config) // old engine is no longer running - _, err = h.engineRegistry.Get(giveWFID) + _, err = h.engineRegistry.Get(wfIDs) require.Error(t, err) // new engine is started - engine, err = h.engineRegistry.Get(updatedWFID) + engine, err = h.engineRegistry.Get(newWFIDs) require.NoError(t, err) err = engine.Ready() require.NoError(t, err) diff --git a/core/services/workflows/syncer/workflow_registry.go b/core/services/workflows/syncer/workflow_registry.go index 6fc319da76b..024975539af 100644 --- a/core/services/workflows/syncer/workflow_registry.go +++ b/core/services/workflows/syncer/workflow_registry.go @@ -173,7 +173,7 @@ func NewWorkflowRegistry( ) *workflowRegistry { ets := []WorkflowRegistryEventType{ForceUpdateSecretsEvent} wr := &workflowRegistry{ - lggr: lggr.Named(name), + lggr: lggr, newContractReaderFn: newContractReaderFn, workflowRegistryAddress: addr, eventPollerCfg: eventPollerConfig, @@ -633,7 +633,7 @@ func (l *workflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don Data: workflow, EventType: WorkflowRegisteredEvent, }); err != nil { - return nil, fmt.Errorf("failed to handle workflow registration: %w", err) + l.lggr.Errorf("failed to handle workflow registration: %s", err) } } diff --git a/deployment/go.mod b/deployment/go.mod index 1fc60d00bfb..b914f76d59b 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -2,6 +2,8 @@ module github.com/smartcontractkit/chainlink/deployment go 1.23.3 +toolchain go1.23.4 + // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ @@ -23,7 +25,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/deployment/go.sum b/deployment/go.sum index 718c1d5c2a4..d740931e9a4 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1411,8 +1411,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/go.mod b/go.mod index 3e75f03ae35..f1d3b1b71e5 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/smartcontractkit/chainlink/v2 go 1.23.3 +toolchain go1.23.4 + require ( github.com/Depado/ginprom v1.8.0 github.com/Masterminds/semver/v3 v3.3.0 @@ -77,7 +79,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db github.com/smartcontractkit/chainlink-feeds v0.1.1 diff --git a/go.sum b/go.sum index f9e188b628b..cdf7fb3805d 100644 --- a/go.sum +++ b/go.sum @@ -1125,8 +1125,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 93e6d93f5fe..b7ef4de1bae 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -2,6 +2,8 @@ module github.com/smartcontractkit/chainlink/integration-tests go 1.23.3 +toolchain go1.23.4 + // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ @@ -39,7 +41,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index dca5ee213fc..9cc6814f3cc 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1432,8 +1432,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 58117f967fc..847fc58b543 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -2,6 +2,8 @@ module github.com/smartcontractkit/chainlink/load-tests go 1.23.3 +toolchain go1.23.4 + // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -17,7 +19,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index ab2c403d7ac..c4215f0c19e 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1423,8 +1423,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23 h1:eFXguUq9e4ETuSteII8ge3mJKyyVIt5pIUxuvyuUuTA= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241202172404-26d4a0b45b23/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= From 699e172108fcda7eeaa23c52e47c4d8a07fdb3b2 Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Thu, 5 Dec 2024 17:06:05 -0800 Subject: [PATCH 23/55] [Keystone][Deployments] Refactor RegisterDONs() (#15534) 1. Make it ordered. 2. Pass the F value in the request. --- deployment/keystone/deploy.go | 112 +++++++++++++++++++++------------- deployment/keystone/types.go | 1 + 2 files changed, 72 insertions(+), 41 deletions(-) diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index dc61e0491b6..0370cc54ba9 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -17,6 +17,7 @@ import ( "golang.org/x/exp/maps" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "google.golang.org/protobuf/proto" @@ -152,6 +153,7 @@ func DeployContracts(e *deployment.Environment, chainSel uint64) (*deployment.Ch // DonInfo is DonCapabilities, but expanded to contain node information type DonInfo struct { Name string + F uint8 Nodes []deployment.Node Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each node } @@ -169,6 +171,7 @@ func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, } donInfos = append(donInfos, DonInfo{ Name: don.Name, + F: don.F, Nodes: nodes, Capabilities: don.Capabilities, }) @@ -207,11 +210,6 @@ func GetRegistryContract(e *deployment.Environment, registryChainSel uint64, add // ConfigureRegistry configures the registry contract with the given DONS and their capabilities // the address book is required to contain the addresses of the deployed registry contract func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { - registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSel, addrBook) - if err != nil { - return nil, fmt.Errorf("failed to get registry: %w", err) - } - donInfos, err := DonInfos(req.Dons, req.Env.Offchain) if err != nil { return nil, fmt.Errorf("failed to get don infos: %w", err) @@ -271,24 +269,47 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon // TODO: annotate nodes with node_operator_id in JD? + donsToRegister := []DONToRegister{} + for _, don := range req.Dons { + nodes, ok := donToNodes[don.Name] + if !ok { + return nil, fmt.Errorf("nodes not found for don %s", don.Name) + } + f := don.F + if f == 0 { + // TODO: fallback to a default value for compatibility - change to error + f = uint8(len(nodes) / 3) + lggr.Warnw("F not set for don - falling back to default", "don", don.Name, "f", f) + } + donsToRegister = append(donsToRegister, DONToRegister{ + Name: don.Name, + F: f, + Nodes: nodes, + }) + } + + nodeIdToP2PID := map[string][32]byte{} + for nodeID, params := range nodesResp.nodeIDToParams { + nodeIdToP2PID[nodeID] = params.P2pId + } // register DONS - donsResp, err := registerDons(lggr, registerDonsRequest{ - registry: registry, - chain: registryChain, - nodeIDToParams: nodesResp.nodeIDToParams, - donToCapabilities: capabilitiesResp.DonToCapabilities, - donToNodes: donToNodes, + donsResp, err := RegisterDons(lggr, RegisterDonsRequest{ + Env: req.Env, + RegistryChainSelector: req.RegistryChainSel, + NodeIDToP2PID: nodeIdToP2PID, + DonToCapabilities: capabilitiesResp.DonToCapabilities, + DonsToRegister: donsToRegister, }) if err != nil { return nil, fmt.Errorf("failed to register DONS: %w", err) } - lggr.Infow("registered DONs", "dons", len(donsResp.donInfos)) + lggr.Infow("registered DONs", "dons", len(donsResp.DonInfos)) return &ConfigureContractsResponse{ Changeset: &deployment.ChangesetOutput{ AddressBook: addrBook, }, - DonInfos: donsResp.donInfos, + DonInfos: donsResp.DonInfos, }, nil } @@ -797,17 +818,23 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode }, nil } -type registerDonsRequest struct { - registry *kcr.CapabilitiesRegistry - chain deployment.Chain +type DONToRegister struct { + Name string + F uint8 + Nodes []deployment.Node +} + +type RegisterDonsRequest struct { + Env *deployment.Environment + RegistryChainSelector uint64 - nodeIDToParams map[string]kcr.CapabilitiesRegistryNodeParams - donToCapabilities map[string][]RegisteredCapability - donToNodes map[string][]deployment.Node + NodeIDToP2PID map[string][32]byte + DonToCapabilities map[string][]RegisteredCapability + DonsToRegister []DONToRegister } -type registerDonsResponse struct { - donInfos map[string]kcr.CapabilitiesRegistryDONInfo +type RegisterDonsResponse struct { + DonInfos map[string]kcr.CapabilitiesRegistryDONInfo } func sortedHash(p2pids [][32]byte) string { @@ -821,14 +848,18 @@ func sortedHash(p2pids [][32]byte) string { return hex.EncodeToString(sha256Hash.Sum(nil)) } -func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsResponse, error) { - lggr.Infow("registering DONs...", "len", len(req.donToNodes)) +func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsResponse, error) { + registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector, req.Env.ExistingAddresses) + if err != nil { + return nil, fmt.Errorf("failed to get registry: %w", err) + } + lggr.Infow("registering DONs...", "len", len(req.DonsToRegister)) // track hash of sorted p2pids to don name because the registry return value does not include the don name // and we need to map it back to the don name to access the other mapping data such as the don's capabilities & nodes p2pIdsToDon := make(map[string]string) var addedDons = 0 - donInfos, err := req.registry.GetDONs(&bind.CallOpts{}) + donInfos, err := registry.GetDONs(&bind.CallOpts{}) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) @@ -839,30 +870,30 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes } lggr.Infow("fetched existing DONs...", "len", len(donInfos), "lenByNodesHash", len(existingDONs)) - for don, nodes := range req.donToNodes { + for _, don := range req.DonsToRegister { var p2pIds [][32]byte - for _, n := range nodes { + for _, n := range don.Nodes { if n.IsBootstrap { continue } - params, ok := req.nodeIDToParams[n.NodeID] + p2pID, ok := req.NodeIDToP2PID[n.NodeID] if !ok { return nil, fmt.Errorf("node params not found for non-bootstrap node %s", n.NodeID) } - p2pIds = append(p2pIds, params.P2pId) + p2pIds = append(p2pIds, p2pID) } p2pSortedHash := sortedHash(p2pIds) - p2pIdsToDon[p2pSortedHash] = don + p2pIdsToDon[p2pSortedHash] = don.Name if _, ok := existingDONs[p2pSortedHash]; ok { lggr.Debugw("don already exists, ignoring", "don", don, "p2p sorted hash", p2pSortedHash) continue } - caps, ok := req.donToCapabilities[don] + caps, ok := req.DonToCapabilities[don.Name] if !ok { - return nil, fmt.Errorf("capabilities not found for node operator %s", don) + return nil, fmt.Errorf("capabilities not found for DON %s", don.Name) } wfSupported := false var cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration @@ -882,17 +913,16 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes }) } - f := len(p2pIds) / 3 // assuming n=3f+1. TODO should come for some config. - tx, err := req.registry.AddDON(req.chain.DeployerKey, p2pIds, cfgs, true, wfSupported, uint8(f)) + tx, err := registry.AddDON(registryChain.DeployerKey, p2pIds, cfgs, true, wfSupported, don.F) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) - return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don, p2pSortedHash, cfgs, err) + return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don.Name, p2pSortedHash, cfgs, err) } - _, err = req.chain.Confirm(tx) + _, err = registryChain.Confirm(tx) if err != nil { - return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don, err) + return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don.Name, err) } - lggr.Debugw("registered DON", "don", don, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", f) + lggr.Debugw("registered DON", "don", don.Name, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F) addedDons++ } lggr.Debugf("Registered all DONs (new=%d), waiting for registry to update", addedDons) @@ -902,7 +932,7 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes foundAll := false for i := 0; i < 10; i++ { lggr.Debugw("attempting to get DONs from registry", "attempt#", i) - donInfos, err = req.registry.GetDONs(&bind.CallOpts{}) + donInfos, err = registry.GetDONs(&bind.CallOpts{}) if !containsAllDONs(donInfos, p2pIdsToDon) { lggr.Debugw("some expected dons not registered yet, re-checking after a delay ...") time.Sleep(2 * time.Second) @@ -919,8 +949,8 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes return nil, fmt.Errorf("did not find all desired DONS") } - resp := registerDonsResponse{ - donInfos: make(map[string]kcr.CapabilitiesRegistryDONInfo), + resp := RegisterDonsResponse{ + DonInfos: make(map[string]kcr.CapabilitiesRegistryDONInfo), } for i, donInfo := range donInfos { donName, ok := p2pIdsToDon[sortedHash(donInfo.NodeP2PIds)] @@ -929,7 +959,7 @@ func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsRes continue } lggr.Debugw("adding don info to the reponse (keyed by DON name)", "don", donName) - resp.donInfos[donName] = donInfos[i] + resp.DonInfos[donName] = donInfos[i] } return &resp, nil } diff --git a/deployment/keystone/types.go b/deployment/keystone/types.go index 4b00e5e4dc0..52620a52a0e 100644 --- a/deployment/keystone/types.go +++ b/deployment/keystone/types.go @@ -127,6 +127,7 @@ func (v NOP) Validate() error { // in is in a convenient form to handle the CLO representation of the nop data type DonCapabilities struct { Name string + F uint8 Nops []NOP Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each nop } From f6f2457d9367c543bef20491a26785266849c154 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Fri, 6 Dec 2024 08:31:42 +0100 Subject: [PATCH 24/55] CCIP-4447 Promwrapper for OCR3 plugins and factories (#15521) * PoC * Basic implementation * Basic implementation * Basic implementation * fixes * fixes * fixes * fixes * fixes * fixes * fixes * fixes * fixes * fixes * fixes --- .changeset/fuzzy-hairs-appear.md | 5 + .../capabilities/ccip/oraclecreator/plugin.go | 9 + core/services/ocr3/promwrapper/factory.go | 42 +++++ .../services/ocr3/promwrapper/factory_test.go | 41 +++++ core/services/ocr3/promwrapper/plugin.go | 122 +++++++++++++ core/services/ocr3/promwrapper/plugin_test.go | 171 ++++++++++++++++++ core/services/ocr3/promwrapper/types.go | 51 ++++++ 7 files changed, 441 insertions(+) create mode 100644 .changeset/fuzzy-hairs-appear.md create mode 100644 core/services/ocr3/promwrapper/factory.go create mode 100644 core/services/ocr3/promwrapper/factory_test.go create mode 100644 core/services/ocr3/promwrapper/plugin.go create mode 100644 core/services/ocr3/promwrapper/plugin_test.go create mode 100644 core/services/ocr3/promwrapper/types.go diff --git a/.changeset/fuzzy-hairs-appear.md b/.changeset/fuzzy-hairs-appear.md new file mode 100644 index 00000000000..a4797462546 --- /dev/null +++ b/.changeset/fuzzy-hairs-appear.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Prometheus observability layer added to OCR3 Reporting Plugins #internal diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index f8868b5d9b9..1b8c6344349 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -22,6 +22,7 @@ import ( cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" "github.com/smartcontractkit/libocr/commontypes" libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" @@ -229,6 +230,12 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( ) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { var factory ocr3types.ReportingPluginFactory[[]byte] var transmitter ocr3types.ContractTransmitter[[]byte] + + chainID, err := chainsel.GetChainIDFromSelector(uint64(config.Config.ChainSelector)) + if err != nil { + return nil, nil, fmt.Errorf("unsupported chain selector %d %w", config.Config.ChainSelector, err) + } + if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { if !i.peerWrapper.IsStarted() { return nil, nil, fmt.Errorf("peer wrapper is not started") @@ -263,6 +270,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( rmnPeerClient, rmnCrypto, ) + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, chainID, "CCIPCommit") transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? @@ -283,6 +291,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( contractReaders, chainWriters, ) + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, chainID, "CCIPExec") transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? diff --git a/core/services/ocr3/promwrapper/factory.go b/core/services/ocr3/promwrapper/factory.go new file mode 100644 index 00000000000..0dabd346112 --- /dev/null +++ b/core/services/ocr3/promwrapper/factory.go @@ -0,0 +1,42 @@ +package promwrapper + +import ( + "context" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" +) + +var _ ocr3types.ReportingPluginFactory[any] = &ReportingPluginFactory[any]{} + +type ReportingPluginFactory[RI any] struct { + origin ocr3types.ReportingPluginFactory[RI] + chainID string + plugin string +} + +func NewReportingPluginFactory[RI any]( + origin ocr3types.ReportingPluginFactory[RI], + chainID string, + plugin string, +) *ReportingPluginFactory[RI] { + return &ReportingPluginFactory[RI]{ + origin: origin, + chainID: chainID, + plugin: plugin, + } +} + +func (r ReportingPluginFactory[RI]) NewReportingPlugin(ctx context.Context, config ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[RI], ocr3types.ReportingPluginInfo, error) { + plugin, info, err := r.origin.NewReportingPlugin(ctx, config) + if err != nil { + return nil, ocr3types.ReportingPluginInfo{}, err + } + wrapped := newReportingPlugin( + plugin, + r.chainID, + r.plugin, + promOCR3ReportsGenerated, + promOCR3Durations, + ) + return wrapped, info, err +} diff --git a/core/services/ocr3/promwrapper/factory_test.go b/core/services/ocr3/promwrapper/factory_test.go new file mode 100644 index 00000000000..72f35aad172 --- /dev/null +++ b/core/services/ocr3/promwrapper/factory_test.go @@ -0,0 +1,41 @@ +package promwrapper + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" +) + +func Test_WrapperFactory(t *testing.T) { + validFactory := NewReportingPluginFactory(fakeFactory[uint]{}, "solana", "plugin") + failingFactory := NewReportingPluginFactory(fakeFactory[uint]{err: errors.New("error")}, "123", "plugin") + + plugin, _, err := validFactory.NewReportingPlugin(tests.Context(t), ocr3types.ReportingPluginConfig{}) + require.NoError(t, err) + + _, err = plugin.Outcome(tests.Context(t), ocr3types.OutcomeContext{}, nil, nil) + require.NoError(t, err) + + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "plugin", "outcome", "true")) + require.Equal(t, 0, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "plugin", "outcome", "false")) + + _, _, err = failingFactory.NewReportingPlugin(tests.Context(t), ocr3types.ReportingPluginConfig{}) + require.Error(t, err) +} + +type fakeFactory[RI any] struct { + err error +} + +func (f fakeFactory[RI]) NewReportingPlugin(context.Context, ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[RI], ocr3types.ReportingPluginInfo, error) { + if f.err != nil { + return nil, ocr3types.ReportingPluginInfo{}, f.err + } + return fakePlugin[RI]{}, ocr3types.ReportingPluginInfo{}, nil +} diff --git a/core/services/ocr3/promwrapper/plugin.go b/core/services/ocr3/promwrapper/plugin.go new file mode 100644 index 00000000000..e4e0c3d35d5 --- /dev/null +++ b/core/services/ocr3/promwrapper/plugin.go @@ -0,0 +1,122 @@ +package promwrapper + +import ( + "context" + "strconv" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +var _ ocr3types.ReportingPlugin[any] = &reportingPlugin[any]{} + +type reportingPlugin[RI any] struct { + ocr3types.ReportingPlugin[RI] + chainID string + plugin string + + // Prometheus components for tracking metrics + reportsGenerated *prometheus.CounterVec + durations *prometheus.HistogramVec +} + +func newReportingPlugin[RI any]( + origin ocr3types.ReportingPlugin[RI], + chainID string, + plugin string, + reportsGenerated *prometheus.CounterVec, + durations *prometheus.HistogramVec, +) *reportingPlugin[RI] { + return &reportingPlugin[RI]{ + ReportingPlugin: origin, + chainID: chainID, + plugin: plugin, + reportsGenerated: reportsGenerated, + durations: durations, + } +} + +func (p *reportingPlugin[RI]) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (ocrtypes.Query, error) { + return withObservedExecution(p, query, func() (ocrtypes.Query, error) { + return p.ReportingPlugin.Query(ctx, outctx) + }) +} + +func (p *reportingPlugin[RI]) Observation(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query) (ocrtypes.Observation, error) { + return withObservedExecution(p, observation, func() (ocrtypes.Observation, error) { + return p.ReportingPlugin.Observation(ctx, outctx, query) + }) +} + +func (p *reportingPlugin[RI]) ValidateObservation(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query, ao ocrtypes.AttributedObservation) error { + _, err := withObservedExecution(p, validateObservation, func() (any, error) { + err := p.ReportingPlugin.ValidateObservation(ctx, outctx, query, ao) + return nil, err + }) + return err +} + +func (p *reportingPlugin[RI]) Outcome(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query, aos []ocrtypes.AttributedObservation) (ocr3types.Outcome, error) { + return withObservedExecution(p, outcome, func() (ocr3types.Outcome, error) { + return p.ReportingPlugin.Outcome(ctx, outctx, query, aos) + }) +} + +func (p *reportingPlugin[RI]) Reports(ctx context.Context, seqNr uint64, outcome ocr3types.Outcome) ([]ocr3types.ReportPlus[RI], error) { + result, err := withObservedExecution(p, reports, func() ([]ocr3types.ReportPlus[RI], error) { + return p.ReportingPlugin.Reports(ctx, seqNr, outcome) + }) + p.trackReports(reports, len(result)) + return result, err +} + +func (p *reportingPlugin[RI]) ShouldAcceptAttestedReport(ctx context.Context, seqNr uint64, reportWithInfo ocr3types.ReportWithInfo[RI]) (bool, error) { + result, err := withObservedExecution(p, shouldAccept, func() (bool, error) { + return p.ReportingPlugin.ShouldAcceptAttestedReport(ctx, seqNr, reportWithInfo) + }) + p.trackReports(shouldAccept, boolToInt(result)) + return result, err +} + +func (p *reportingPlugin[RI]) ShouldTransmitAcceptedReport(ctx context.Context, seqNr uint64, reportWithInfo ocr3types.ReportWithInfo[RI]) (bool, error) { + result, err := withObservedExecution(p, shouldTransmit, func() (bool, error) { + return p.ReportingPlugin.ShouldTransmitAcceptedReport(ctx, seqNr, reportWithInfo) + }) + p.trackReports(shouldTransmit, boolToInt(result)) + return result, err +} + +func (p *reportingPlugin[RI]) trackReports( + function functionType, + count int, +) { + p.reportsGenerated. + WithLabelValues(p.chainID, p.plugin, string(function)). + Add(float64(count)) +} + +func boolToInt(arg bool) int { + if arg { + return 1 + } + return 0 +} + +func withObservedExecution[RI, R any]( + p *reportingPlugin[RI], + function functionType, + exec func() (R, error), +) (R, error) { + start := time.Now() + result, err := exec() + + success := err == nil + + p.durations. + WithLabelValues(p.chainID, p.plugin, string(function), strconv.FormatBool(success)). + Observe(float64(time.Since(start))) + + return result, err +} diff --git a/core/services/ocr3/promwrapper/plugin_test.go b/core/services/ocr3/promwrapper/plugin_test.go new file mode 100644 index 00000000000..35a97d109aa --- /dev/null +++ b/core/services/ocr3/promwrapper/plugin_test.go @@ -0,0 +1,171 @@ +package promwrapper + +import ( + "context" + "errors" + "testing" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" + io_prometheus_client "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" +) + +func Test_ReportsGeneratedGauge(t *testing.T) { + plugin1 := newReportingPlugin( + fakePlugin[uint]{reports: make([]ocr3types.ReportPlus[uint], 2)}, + "123", "empty", promOCR3ReportsGenerated, promOCR3Durations, + ) + plugin2 := newReportingPlugin( + fakePlugin[bool]{reports: make([]ocr3types.ReportPlus[bool], 10)}, + "solana", "different_plugin", promOCR3ReportsGenerated, promOCR3Durations, + ) + plugin3 := newReportingPlugin( + fakePlugin[string]{err: errors.New("error")}, + "1234", "empty", promOCR3ReportsGenerated, promOCR3Durations, + ) + + r1, err := plugin1.Reports(tests.Context(t), 1, nil) + require.NoError(t, err) + require.Len(t, r1, 2) + + for i := 0; i < 10; i++ { + r2, err1 := plugin2.Reports(tests.Context(t), 1, nil) + require.NoError(t, err1) + require.Len(t, r2, 10) + } + + _, err = plugin2.ShouldAcceptAttestedReport(tests.Context(t), 1, ocr3types.ReportWithInfo[bool]{}) + require.NoError(t, err) + + _, err = plugin3.Reports(tests.Context(t), 1, nil) + require.Error(t, err) + + g1 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("123", "empty", "reports")) + require.Equal(t, 2, int(g1)) + + g2 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("solana", "different_plugin", "reports")) + require.Equal(t, 100, int(g2)) + + g3 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("solana", "different_plugin", "shouldAccept")) + require.Equal(t, 1, int(g3)) + + g4 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("1234", "empty", "reports")) + require.Equal(t, 0, int(g4)) +} + +func Test_DurationHistograms(t *testing.T) { + plugin1 := newReportingPlugin( + fakePlugin[uint]{}, + "123", "empty", promOCR3ReportsGenerated, promOCR3Durations, + ) + plugin2 := newReportingPlugin( + fakePlugin[uint]{err: errors.New("error")}, + "123", "empty", promOCR3ReportsGenerated, promOCR3Durations, + ) + plugin3 := newReportingPlugin( + fakePlugin[uint]{}, + "solana", "commit", promOCR3ReportsGenerated, promOCR3Durations, + ) + + for _, p := range []*reportingPlugin[uint]{plugin1, plugin2, plugin3} { + _, _ = p.Query(tests.Context(t), ocr3types.OutcomeContext{}) + for i := 0; i < 2; i++ { + _, _ = p.Observation(tests.Context(t), ocr3types.OutcomeContext{}, nil) + } + _ = p.ValidateObservation(tests.Context(t), ocr3types.OutcomeContext{}, nil, ocrtypes.AttributedObservation{}) + _, _ = p.Outcome(tests.Context(t), ocr3types.OutcomeContext{}, nil, nil) + _, _ = p.Reports(tests.Context(t), 0, nil) + _, _ = p.ShouldAcceptAttestedReport(tests.Context(t), 0, ocr3types.ReportWithInfo[uint]{}) + _, _ = p.ShouldTransmitAcceptedReport(tests.Context(t), 0, ocr3types.ReportWithInfo[uint]{}) + } + + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "query", "true")) + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "query", "false")) + require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "commit", "query", "true")) + + require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "observation", "true")) + require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "observation", "false")) + require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "commit", "observation", "true")) +} + +type fakePlugin[RI any] struct { + reports []ocr3types.ReportPlus[RI] + err error +} + +func (f fakePlugin[RI]) Query(context.Context, ocr3types.OutcomeContext) (ocrtypes.Query, error) { + if f.err != nil { + return nil, f.err + } + return ocrtypes.Query{}, nil +} + +func (f fakePlugin[RI]) Observation(context.Context, ocr3types.OutcomeContext, ocrtypes.Query) (ocrtypes.Observation, error) { + if f.err != nil { + return nil, f.err + } + return ocrtypes.Observation{}, nil +} + +func (f fakePlugin[RI]) ValidateObservation(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, ocrtypes.AttributedObservation) error { + return f.err +} + +func (f fakePlugin[RI]) ObservationQuorum(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, []ocrtypes.AttributedObservation) (quorumReached bool, err error) { + return false, f.err +} + +func (f fakePlugin[RI]) Outcome(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, []ocrtypes.AttributedObservation) (ocr3types.Outcome, error) { + if f.err != nil { + return nil, f.err + } + return ocr3types.Outcome{}, nil +} + +func (f fakePlugin[RI]) Reports(context.Context, uint64, ocr3types.Outcome) ([]ocr3types.ReportPlus[RI], error) { + if f.err != nil { + return nil, f.err + } + return f.reports, nil +} + +func (f fakePlugin[RI]) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[RI]) (bool, error) { + if f.err != nil { + return false, f.err + } + return true, nil +} + +func (f fakePlugin[RI]) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[RI]) (bool, error) { + if f.err != nil { + return false, f.err + } + return true, nil +} + +func (f fakePlugin[RI]) Close() error { + return f.err +} + +func counterFromHistogramByLabels(t *testing.T, histogramVec *prometheus.HistogramVec, labels ...string) int { + observer, err := histogramVec.GetMetricWithLabelValues(labels...) + require.NoError(t, err) + + metricCh := make(chan prometheus.Metric, 1) + observer.(prometheus.Histogram).Collect(metricCh) + close(metricCh) + + metric := <-metricCh + pb := &io_prometheus_client.Metric{} + err = metric.Write(pb) + require.NoError(t, err) + + //nolint:gosec // we don't care about that in tests + return int(pb.GetHistogram().GetSampleCount()) +} diff --git a/core/services/ocr3/promwrapper/types.go b/core/services/ocr3/promwrapper/types.go new file mode 100644 index 00000000000..bf6a1b2a39c --- /dev/null +++ b/core/services/ocr3/promwrapper/types.go @@ -0,0 +1,51 @@ +package promwrapper + +import ( + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +type functionType string + +const ( + query functionType = "query" + observation functionType = "observation" + validateObservation functionType = "validateObservation" + outcome functionType = "outcome" + reports functionType = "reports" + shouldAccept functionType = "shouldAccept" + shouldTransmit functionType = "shouldTransmit" +) + +var ( + buckets = []float64{ + float64(10 * time.Millisecond), + float64(50 * time.Millisecond), + float64(100 * time.Millisecond), + float64(200 * time.Millisecond), + float64(500 * time.Millisecond), + float64(700 * time.Millisecond), + float64(time.Second), + float64(2 * time.Second), + float64(5 * time.Second), + float64(10 * time.Second), + } + + promOCR3ReportsGenerated = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "ocr3_reporting_plugin_reports_processed", + Help: "Tracks number of reports processed/generated within by different OCR3 functions", + }, + []string{"chainID", "plugin", "function"}, + ) + promOCR3Durations = promauto.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "ocr3_reporting_plugin_duration", + Help: "The amount of time elapsed during the OCR3 plugin's function", + Buckets: buckets, + }, + []string{"chainID", "plugin", "function", "success"}, + ) +) From 5e5a4cdb916597fa21f23bd92a35a5202cf199c8 Mon Sep 17 00:00:00 2001 From: Makram Date: Fri, 6 Dec 2024 11:53:45 +0200 Subject: [PATCH 25/55] contracts/src/v0.8/ccip: setSecondary -> setCandidate (#15531) Super minor update to change the setSecondary to setCandidate in the ASCII state diagrams. --- contracts/src/v0.8/ccip/capability/CCIPHome.sol | 2 +- contracts/src/v0.8/ccip/rmn/RMNHome.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/src/v0.8/ccip/capability/CCIPHome.sol b/contracts/src/v0.8/ccip/capability/CCIPHome.sol index 7a425566c33..e43e4b0d03f 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPHome.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPHome.sol @@ -62,7 +62,7 @@ import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts /// │ Active │ revokeCandidate │ Candidate │◄───────────┐ /// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ /// │ ├───────────────────►│ │ -/// └─────────────┘ setSecondary └─────────────┘ +/// └─────────────┘ setCandidate └─────────────┘ /// contract CCIPHome is Ownable2StepMsgSender, ITypeAndVersion, ICapabilityConfiguration, IERC165 { using EnumerableSet for EnumerableSet.UintSet; diff --git a/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/contracts/src/v0.8/ccip/rmn/RMNHome.sol index 684dc3e994e..92aab25ae8e 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNHome.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -54,7 +54,7 @@ import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.s /// │ Active │ revokeCandidate │ Candidate │◄───────────┐ /// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ /// │ ├───────────────────►│ │ -/// └─────────────┘ setSecondary └─────────────┘ +/// └─────────────┘ setCandidate └─────────────┘ /// contract RMNHome is Ownable2StepMsgSender, ITypeAndVersion { event ConfigSet(bytes32 indexed configDigest, uint32 version, StaticConfig staticConfig, DynamicConfig dynamicConfig); From 3e742294cf5253d982147b376102db0630b0b5fc Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Fri, 6 Dec 2024 11:47:45 +0100 Subject: [PATCH 26/55] CCIP-4509 Refactoring and improvements around token transfer and usdc transfer tests (#15502) * Test * Test * Test * Test * Test * Minor fixes * Increasing timeout. Messages are sent much faster so we need to wait longer for the exec. * Increasing timeout. Messages are sent much faster so we need to wait longer for the exec. * Increasing timeout. Messages are sent much faster so we need to wait longer for the exec. * Docs * Docs --- deployment/ccip/changeset/test_assertions.go | 52 ++++- deployment/ccip/changeset/test_helpers.go | 126 +++++++++++ .../smoke/ccip/ccip_token_transfer_test.go | 137 +++++------ .../smoke/ccip/ccip_usdc_test.go | 212 ++++++++---------- 4 files changed, 335 insertions(+), 192 deletions(-) diff --git a/deployment/ccip/changeset/test_assertions.go b/deployment/ccip/changeset/test_assertions.go index ad2ea4257ea..a7d3ecf61f8 100644 --- a/deployment/ccip/changeset/test_assertions.go +++ b/deployment/ccip/changeset/test_assertions.go @@ -259,6 +259,40 @@ func (c *commitReportTracker) allCommited(sourceChainSelector uint64) bool { return true } +// ConfirmMultipleCommits waits for multiple ccipocr3.SeqNumRange to be committed by the Offramp. +// Waiting is done in parallel per every sourceChain/destChain (lane) passed as argument. +func ConfirmMultipleCommits( + t *testing.T, + chains map[uint64]deployment.Chain, + state map[uint64]CCIPChainState, + startBlocks map[uint64]*uint64, + enforceSingleCommit bool, + expectedSeqNums map[SourceDestPair]ccipocr3.SeqNumRange, +) error { + errGrp := &errgroup.Group{} + + for sourceDest, seqRange := range expectedSeqNums { + seqRange := seqRange + srcChain := sourceDest.SourceChainSelector + destChain := sourceDest.DestChainSelector + + errGrp.Go(func() error { + _, err := ConfirmCommitWithExpectedSeqNumRange( + t, + chains[srcChain], + chains[destChain], + state[destChain].OffRamp, + startBlocks[destChain], + seqRange, + enforceSingleCommit, + ) + return err + }) + } + + return errGrp.Wait() +} + // ConfirmCommitWithExpectedSeqNumRange waits for a commit report on the destination chain with the expected sequence number range. // startBlock is the block number to start watching from. // If startBlock is nil, it will start watching from the latest block. @@ -449,7 +483,7 @@ func ConfirmExecWithSeqNrs( return nil, fmt.Errorf("no expected sequence numbers provided") } - timer := time.NewTimer(3 * time.Minute) + timer := time.NewTimer(8 * time.Minute) defer timer.Stop() tick := time.NewTicker(3 * time.Second) defer tick.Stop() @@ -564,6 +598,22 @@ func RequireConsistently(t *testing.T, condition func() bool, duration time.Dura } } +func SeqNumberRageToSlice(seqRanges map[SourceDestPair]ccipocr3.SeqNumRange) map[SourceDestPair][]uint64 { + flatten := make(map[SourceDestPair][]uint64) + + for srcDst, seqRange := range seqRanges { + if _, ok := flatten[srcDst]; !ok { + flatten[srcDst] = make([]uint64, 0, seqRange.End()-seqRange.Start()+1) + } + + for i := seqRange.Start(); i <= seqRange.End(); i++ { + flatten[srcDst] = append(flatten[srcDst], uint64(i)) + } + } + + return flatten +} + const ( EXECUTION_STATE_UNTOUCHED = 0 EXECUTION_STATE_INPROGRESS = 1 diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index 742fe39200a..eb719450a0a 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -1225,6 +1225,78 @@ func Transfer( return msgSentEvent, startBlocks } +type TestTransferRequest struct { + Name string + SourceChain, DestChain uint64 + Receiver common.Address + ExpectedStatus int + // optional + Tokens []router.ClientEVMTokenAmount + Data []byte + ExtraArgs []byte + ExpectedTokenBalances map[common.Address]*big.Int +} + +// TransferMultiple sends multiple CCIPMessages (represented as TestTransferRequest) sequentially. +// It verifies whether message is not reverted on the source and proper event is emitted by OnRamp. +// However, it doesn't wait for message to be committed or executed. Therefore, you can send multiple messages very fast, +// but you need to make sure they are committed/executed on your own (if that's the intention). +// It saves some time during test execution, because we let plugins batch instead of executing one by one +// If you want to wait for execution in a "batch" manner you will need to pass maps returned by TransferMultiple to +// either ConfirmMultipleCommits (for commit) or ConfirmExecWithSeqNrsForAll (for exec). Check example usage in the tests. +func TransferMultiple( + ctx context.Context, + t *testing.T, + env deployment.Environment, + state CCIPOnChainState, + requests []TestTransferRequest, +) ( + map[uint64]*uint64, + map[SourceDestPair]cciptypes.SeqNumRange, + map[SourceDestPair]map[uint64]int, + map[uint64]map[TokenReceiverIdentifier]*big.Int, +) { + startBlocks := make(map[uint64]*uint64) + expectedSeqNums := make(map[SourceDestPair]cciptypes.SeqNumRange) + expectedExecutionStates := make(map[SourceDestPair]map[uint64]int) + expectedTokenBalances := make(TokenBalanceAccumulator) + + for _, tt := range requests { + t.Run(tt.Name, func(t *testing.T) { + expectedTokenBalances.add(tt.DestChain, tt.Receiver, tt.ExpectedTokenBalances) + + pairId := SourceDestPair{ + SourceChainSelector: tt.SourceChain, + DestChainSelector: tt.DestChain, + } + + msg, blocks := Transfer( + ctx, t, env, state, tt.SourceChain, tt.DestChain, tt.Tokens, tt.Receiver, tt.Data, tt.ExtraArgs) + if _, ok := expectedExecutionStates[pairId]; !ok { + expectedExecutionStates[pairId] = make(map[uint64]int) + } + expectedExecutionStates[pairId][msg.SequenceNumber] = tt.ExpectedStatus + + if _, ok := startBlocks[tt.DestChain]; !ok { + startBlocks[tt.DestChain] = blocks[tt.DestChain] + } + + seqNr, ok := expectedSeqNums[pairId] + if ok { + expectedSeqNums[pairId] = cciptypes.NewSeqNumRange( + seqNr.Start(), cciptypes.SeqNum(msg.SequenceNumber), + ) + } else { + expectedSeqNums[pairId] = cciptypes.NewSeqNumRange( + cciptypes.SeqNum(msg.SequenceNumber), cciptypes.SeqNum(msg.SequenceNumber), + ) + } + }) + } + + return startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances +} + // TransferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed func TransferAndWaitForSuccess( ctx context.Context, @@ -1258,6 +1330,60 @@ func TransferAndWaitForSuccess( require.Equal(t, expectedStatus, states[identifier][msgSentEvent.SequenceNumber]) } +// TokenBalanceAccumulator is a convenient accumulator to aggregate expected balances of different tokens +// used across the tests. You can iterate over your test cases and build the final "expected" balances for tokens (per chain, per sender) +// For instance, if your test runs multiple transfers for the same token, and you want to verify the balance of tokens at +// the end of the execution, you can simply use that struct for aggregating expected tokens +// Please also see WaitForTokenBalances to better understand how you can assert token balances +type TokenBalanceAccumulator map[uint64]map[TokenReceiverIdentifier]*big.Int + +func (t TokenBalanceAccumulator) add( + destChain uint64, + receiver common.Address, + expectedBalance map[common.Address]*big.Int) { + for token, balance := range expectedBalance { + tkIdentifier := TokenReceiverIdentifier{token, receiver} + + if _, ok := t[destChain]; !ok { + t[destChain] = make(map[TokenReceiverIdentifier]*big.Int) + } + actual, ok := t[destChain][tkIdentifier] + if !ok { + actual = big.NewInt(0) + } + t[destChain][tkIdentifier] = new(big.Int).Add(actual, balance) + } +} + +type TokenReceiverIdentifier struct { + token common.Address + receiver common.Address +} + +// WaitForTokenBalances waits for multiple ERC20 tokens to reach a particular balance +// It works in a batch manner, so you can pass and exhaustive list of different tokens (per senders and chains) +// and it would work concurrently for the balance to be met. Check WaitForTheTokenBalance to see how balance +// checking is made for a token/receiver pair +func WaitForTokenBalances( + ctx context.Context, + t *testing.T, + chains map[uint64]deployment.Chain, + expectedBalances map[uint64]map[TokenReceiverIdentifier]*big.Int, +) { + errGrp := &errgroup.Group{} + for chainID, tokens := range expectedBalances { + for id, balance := range tokens { + id := id + balance := balance + errGrp.Go(func() error { + WaitForTheTokenBalance(ctx, t, id.token, id.receiver, chains[chainID], balance) + return nil + }) + } + } + require.NoError(t, errGrp.Wait()) +} + func WaitForTheTokenBalance( ctx context.Context, t *testing.T, diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go index 06ee06297ae..81920246bed 100644 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -96,54 +96,44 @@ func TestTokenTransfer(t *testing.T) { }, ) - tcs := []struct { - name string - srcChain uint64 - dstChain uint64 - tokenAmounts []router.ClientEVMTokenAmount - receiver common.Address - data []byte - extraData []byte - expectedTokenBalances map[common.Address]*big.Int - expectedExecutionState int - }{ + tcs := []changeset.TestTransferRequest{ { - name: "Send token to EOA", - srcChain: sourceChain, - dstChain: destChain, - tokenAmounts: []router.ClientEVMTokenAmount{ + Name: "Send token to EOA", + SourceChain: sourceChain, + DestChain: destChain, + Tokens: []router.ClientEVMTokenAmount{ { Token: srcToken.Address(), Amount: oneE18, }, }, - receiver: utils.RandomAddress(), - expectedTokenBalances: map[common.Address]*big.Int{ + Receiver: utils.RandomAddress(), + ExpectedTokenBalances: map[common.Address]*big.Int{ destToken.Address(): oneE18, }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "Send token to contract", - srcChain: sourceChain, - dstChain: destChain, - tokenAmounts: []router.ClientEVMTokenAmount{ + Name: "Send token to contract", + SourceChain: sourceChain, + DestChain: destChain, + Tokens: []router.ClientEVMTokenAmount{ { Token: srcToken.Address(), Amount: oneE18, }, }, - receiver: state.Chains[destChain].Receiver.Address(), - expectedTokenBalances: map[common.Address]*big.Int{ + Receiver: state.Chains[destChain].Receiver.Address(), + ExpectedTokenBalances: map[common.Address]*big.Int{ destToken.Address(): oneE18, }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "Send N tokens to contract", - srcChain: destChain, - dstChain: sourceChain, - tokenAmounts: []router.ClientEVMTokenAmount{ + Name: "Send N tokens to contract", + SourceChain: destChain, + DestChain: sourceChain, + Tokens: []router.ClientEVMTokenAmount{ { Token: selfServeDestToken.Address(), Amount: oneE18, @@ -157,19 +147,19 @@ func TestTokenTransfer(t *testing.T) { Amount: oneE18, }, }, - receiver: state.Chains[sourceChain].Receiver.Address(), - extraData: changeset.MakeEVMExtraArgsV2(300_000, false), - expectedTokenBalances: map[common.Address]*big.Int{ + Receiver: state.Chains[sourceChain].Receiver.Address(), + ExtraArgs: changeset.MakeEVMExtraArgsV2(300_000, false), + ExpectedTokenBalances: map[common.Address]*big.Int{ selfServeSrcToken.Address(): new(big.Int).Add(oneE18, oneE18), srcToken.Address(): oneE18, }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "Sending token transfer with custom gasLimits to the EOA is successful", - srcChain: destChain, - dstChain: sourceChain, - tokenAmounts: []router.ClientEVMTokenAmount{ + Name: "Sending token transfer with custom gasLimits to the EOA is successful", + SourceChain: destChain, + DestChain: sourceChain, + Tokens: []router.ClientEVMTokenAmount{ { Token: selfServeDestToken.Address(), Amount: oneE18, @@ -179,19 +169,19 @@ func TestTokenTransfer(t *testing.T) { Amount: new(big.Int).Add(oneE18, oneE18), }, }, - receiver: utils.RandomAddress(), - extraData: changeset.MakeEVMExtraArgsV2(1, false), - expectedTokenBalances: map[common.Address]*big.Int{ + Receiver: utils.RandomAddress(), + ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExpectedTokenBalances: map[common.Address]*big.Int{ selfServeSrcToken.Address(): oneE18, srcToken.Address(): new(big.Int).Add(oneE18, oneE18), }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "Sending PTT with too low gas limit leads to the revert when receiver is a contract", - srcChain: destChain, - dstChain: sourceChain, - tokenAmounts: []router.ClientEVMTokenAmount{ + Name: "Sending PTT with too low gas limit leads to the revert when receiver is a contract", + SourceChain: destChain, + DestChain: sourceChain, + Tokens: []router.ClientEVMTokenAmount{ { Token: selfServeDestToken.Address(), Amount: oneE18, @@ -201,45 +191,40 @@ func TestTokenTransfer(t *testing.T) { Amount: oneE18, }, }, - receiver: state.Chains[sourceChain].Receiver.Address(), - data: []byte("this should be reverted because gasLimit is too low, no tokens are transferred as well"), - extraData: changeset.MakeEVMExtraArgsV2(1, false), - expectedTokenBalances: map[common.Address]*big.Int{ + Receiver: state.Chains[sourceChain].Receiver.Address(), + Data: []byte("this should be reverted because gasLimit is too low, no tokens are transferred as well"), + ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExpectedTokenBalances: map[common.Address]*big.Int{ selfServeSrcToken.Address(): big.NewInt(0), srcToken.Address(): big.NewInt(0), }, - expectedExecutionState: changeset.EXECUTION_STATE_FAILURE, + ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, }, } - for _, tt := range tcs { - t.Run(tt.name, func(t *testing.T) { - initialBalances := map[common.Address]*big.Int{} - for token := range tt.expectedTokenBalances { - initialBalance := changeset.GetTokenBalance(ctx, t, token, tt.receiver, e.Chains[tt.dstChain]) - initialBalances[token] = initialBalance - } + startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := + changeset.TransferMultiple(ctx, t, e, state, tcs) - changeset.TransferAndWaitForSuccess( - ctx, - t, - e, - state, - tt.srcChain, - tt.dstChain, - tt.tokenAmounts, - tt.receiver, - tt.data, - tt.expectedExecutionState, - tt.extraData, - ) + err = changeset.ConfirmMultipleCommits( + t, + e.Chains, + state.Chains, + startBlocks, + false, + expectedSeqNums, + ) + require.NoError(t, err) - for token, balance := range tt.expectedTokenBalances { - expected := new(big.Int).Add(initialBalances[token], balance) - changeset.WaitForTheTokenBalance(ctx, t, token, tt.receiver, e.Chains[tt.dstChain], expected) - } - }) - } + execStates := changeset.ConfirmExecWithSeqNrsForAll( + t, + e, + state, + changeset.SeqNumberRageToSlice(expectedSeqNums), + startBlocks, + ) + require.Equal(t, expectedExecutionStates, execStates) + + changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) } func createAndFundSelfServeActor( diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index d1df2a6da92..eacf03df926 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -11,12 +11,10 @@ import ( "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -37,7 +35,12 @@ func TestUSDCTokenTransfer(t *testing.T) { IsUSDC: true, } tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - //tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 3, 4, config) + //tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + // Chains: 3, + // NumOfUsersPerChain: 3, + // Nodes: 5, + // Bootstraps: 1, + //}, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) @@ -97,37 +100,28 @@ func TestUSDCTokenTransfer(t *testing.T) { // MockE2EUSDCTransmitter always mint 1, see MockE2EUSDCTransmitter.sol for more details tinyOneCoin := new(big.Int).SetUint64(1) - tcs := []struct { - name string - receiver common.Address - sourceChain uint64 - destChain uint64 - tokens []router.ClientEVMTokenAmount - data []byte - expectedTokenBalances map[common.Address]*big.Int - expectedExecutionState int - }{ + tcs := []changeset.TestTransferRequest{ { - name: "single USDC token transfer to EOA", - receiver: utils.RandomAddress(), - sourceChain: chainC, - destChain: chainA, - tokens: []router.ClientEVMTokenAmount{ + Name: "single USDC token transfer to EOA", + Receiver: utils.RandomAddress(), + SourceChain: chainC, + DestChain: chainA, + Tokens: []router.ClientEVMTokenAmount{ { Token: cChainUSDC.Address(), Amount: tinyOneCoin, }}, - expectedTokenBalances: map[common.Address]*big.Int{ + ExpectedTokenBalances: map[common.Address]*big.Int{ aChainUSDC.Address(): tinyOneCoin, }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "multiple USDC tokens within the same message", - receiver: utils.RandomAddress(), - sourceChain: chainC, - destChain: chainA, - tokens: []router.ClientEVMTokenAmount{ + Name: "multiple USDC tokens within the same message", + Receiver: utils.RandomAddress(), + SourceChain: chainC, + DestChain: chainA, + Tokens: []router.ClientEVMTokenAmount{ { Token: cChainUSDC.Address(), Amount: tinyOneCoin, @@ -137,18 +131,18 @@ func TestUSDCTokenTransfer(t *testing.T) { Amount: tinyOneCoin, }, }, - expectedTokenBalances: map[common.Address]*big.Int{ - // 2 coins because of the same receiver + ExpectedTokenBalances: map[common.Address]*big.Int{ + // 2 coins because of the same Receiver aChainUSDC.Address(): new(big.Int).Add(tinyOneCoin, tinyOneCoin), }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "USDC token together with another token transferred to EOA", - receiver: utils.RandomAddress(), - sourceChain: chainA, - destChain: chainC, - tokens: []router.ClientEVMTokenAmount{ + Name: "USDC token together with another token transferred to EOA", + Receiver: utils.RandomAddress(), + SourceChain: chainA, + DestChain: chainC, + Tokens: []router.ClientEVMTokenAmount{ { Token: aChainUSDC.Address(), Amount: tinyOneCoin, @@ -158,105 +152,89 @@ func TestUSDCTokenTransfer(t *testing.T) { Amount: new(big.Int).Mul(tinyOneCoin, big.NewInt(10)), }, }, - expectedTokenBalances: map[common.Address]*big.Int{ + ExpectedTokenBalances: map[common.Address]*big.Int{ cChainUSDC.Address(): tinyOneCoin, cChainToken.Address(): new(big.Int).Mul(tinyOneCoin, big.NewInt(10)), }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, { - name: "programmable token transfer to valid contract receiver", - receiver: state.Chains[chainC].Receiver.Address(), - sourceChain: chainA, - destChain: chainC, - tokens: []router.ClientEVMTokenAmount{ + Name: "USDC programmable token transfer to valid contract receiver", + Receiver: state.Chains[chainC].Receiver.Address(), + SourceChain: chainA, + DestChain: chainC, + Tokens: []router.ClientEVMTokenAmount{ { Token: aChainUSDC.Address(), Amount: tinyOneCoin, }, }, - data: []byte("hello world"), - expectedTokenBalances: map[common.Address]*big.Int{ + Data: []byte("hello world"), + ExpectedTokenBalances: map[common.Address]*big.Int{ cChainUSDC.Address(): tinyOneCoin, }, - expectedExecutionState: changeset.EXECUTION_STATE_SUCCESS, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, + }, + { + Name: "USDC programmable token transfer with too little gas", + Receiver: state.Chains[chainB].Receiver.Address(), + SourceChain: chainC, + DestChain: chainB, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: cChainUSDC.Address(), + Amount: tinyOneCoin, + }, + }, + Data: []byte("gimme more gas to execute that!"), + ExpectedTokenBalances: map[common.Address]*big.Int{ + bChainUSDC.Address(): new(big.Int).SetUint64(0), + }, + ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), + ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, + }, + { + Name: "USDC token transfer from a different source chain", + Receiver: utils.RandomAddress(), + SourceChain: chainB, + DestChain: chainC, + Tokens: []router.ClientEVMTokenAmount{ + { + Token: bChainUSDC.Address(), + Amount: tinyOneCoin, + }, + }, + Data: nil, + ExpectedTokenBalances: map[common.Address]*big.Int{ + cChainUSDC.Address(): tinyOneCoin, + }, + ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, }, } - for _, tt := range tcs { - t.Run(tt.name, func(t *testing.T) { - initialBalances := map[common.Address]*big.Int{} - for token := range tt.expectedTokenBalances { - initialBalance := changeset.GetTokenBalance(ctx, t, token, tt.receiver, e.Chains[tt.destChain]) - initialBalances[token] = initialBalance - } - - changeset.TransferAndWaitForSuccess( - ctx, - t, - e, - state, - tt.sourceChain, - tt.destChain, - tt.tokens, - tt.receiver, - tt.data, - tt.expectedExecutionState, - nil, - ) - - for token, balance := range tt.expectedTokenBalances { - expected := new(big.Int).Add(initialBalances[token], balance) - changeset.WaitForTheTokenBalance(ctx, t, token, tt.receiver, e.Chains[tt.destChain], expected) - } - }) - } - - t.Run("multi-source USDC transfer targeting the same dest receiver", func(t *testing.T) { - sendSingleTokenTransfer := func(source, dest uint64, token common.Address, receiver common.Address) (*onramp.OnRampCCIPMessageSent, changeset.SourceDestPair) { - msg := changeset.TestSendRequest(t, e, state, source, dest, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(receiver.Bytes(), 32), - Data: []byte{}, - TokenAmounts: []router.ClientEVMTokenAmount{{Token: token, Amount: tinyOneCoin}}, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - return msg, changeset.SourceDestPair{ - SourceChainSelector: source, - DestChainSelector: dest, - } - } - - receiver := utils.RandomAddress() - - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) + startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := + changeset.TransferMultiple(ctx, t, e, state, tcs) - latesthdr, err := e.Chains[chainC].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[chainC] = &block - - message1, message1ID := sendSingleTokenTransfer(chainA, chainC, aChainUSDC.Address(), receiver) - expectedSeqNum[message1ID] = message1.SequenceNumber - expectedSeqNumExec[message1ID] = []uint64{message1.SequenceNumber} - - message2, message2ID := sendSingleTokenTransfer(chainB, chainC, bChainUSDC.Address(), receiver) - expectedSeqNum[message2ID] = message2.SequenceNumber - expectedSeqNumExec[message2ID] = []uint64{message2.SequenceNumber} - - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) - states := changeset.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks) + err = changeset.ConfirmMultipleCommits( + t, + e.Chains, + state.Chains, + startBlocks, + false, + expectedSeqNums, + ) + require.NoError(t, err) - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, states[message1ID][message1.SequenceNumber]) - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, states[message2ID][message2.SequenceNumber]) + execStates := changeset.ConfirmExecWithSeqNrsForAll( + t, + e, + state, + changeset.SeqNumberRageToSlice(expectedSeqNums), + startBlocks, + ) + require.Equal(t, expectedExecutionStates, execStates) - // We sent 1 coin from each source chain, so we should have 2 coins on the destination chain - // Receiver is randomly generated so we don't need to get the initial balance first - expectedBalance := new(big.Int).Add(tinyOneCoin, tinyOneCoin) - changeset.WaitForTheTokenBalance(ctx, t, cChainUSDC.Address(), receiver, e.Chains[chainC], expectedBalance) - }) + changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) } func updateFeeQuoters( @@ -274,7 +252,11 @@ func updateFeeQuoters( return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC) }) updateFeeQtrGrp.Go(func() error { - return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC) + err1 := changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC) + if err1 != nil { + return err1 + } + return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainB, cChainUSDC) }) return updateFeeQtrGrp.Wait() } From 095a07c22f0986ad13dc18ea26536ab2e32b9291 Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Fri, 6 Dec 2024 05:51:10 -0800 Subject: [PATCH 27/55] fix: typo for contracts changeset validation (#15530) --- .github/workflows/changeset.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index 5d6b2deafe2..331492eb74f 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -182,7 +182,7 @@ jobs: - added|modified: 'contracts/.changeset/*.md' - name: Setup node - uses: ./.github/actions/setup-node + uses: ./.github/actions/setup-nodejs if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} - name: Validate changeset files From 2ed0c039910ace026b5608e13265295e78c70c3a Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 6 Dec 2024 09:36:48 -0500 Subject: [PATCH 28/55] wiring engine histogram buckets through to beholder Client (#15508) * wiring engine histogram buckets through to beholder Client * bumping common * Move metric views (#15515) * bumping common --------- Co-authored-by: Pavel <177363085+pkcll@users.noreply.github.com> --- core/cmd/shell.go | 5 +++++ core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- core/services/workflows/monitoring.go | 32 +++++++++++++++++++++++++++ deployment/go.mod | 2 +- deployment/go.sum | 4 ++-- go.mod | 4 ++-- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 12 files changed, 53 insertions(+), 16 deletions(-) diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 788e4da6f69..53ba5e3f82f 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -53,6 +53,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows" "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" @@ -111,6 +112,10 @@ func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTeleme AuthPublicKeyHex: csaPubKeyHex, AuthHeaders: beholderAuthHeaders, } + // note: due to the OTEL specification, all histogram buckets + // must be defined when the beholder client is created + clientCfg.MetricViews = append(clientCfg.MetricViews, workflows.MetricViews()...) + if tracingCfg.Enabled { clientCfg.TraceSpanExporter, err = tracingCfg.NewSpanExporter() if err != nil { diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 65d63f2a1df..d468907c550 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -26,7 +26,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 1f1374bc11d..225ae3b9191 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1142,8 +1142,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/core/services/workflows/monitoring.go b/core/services/workflows/monitoring.go index 205ce529c28..8457dadeb60 100644 --- a/core/services/workflows/monitoring.go +++ b/core/services/workflows/monitoring.go @@ -5,6 +5,7 @@ import ( "fmt" "go.opentelemetry.io/otel/metric" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" "github.com/smartcontractkit/chainlink-common/pkg/beholder" "github.com/smartcontractkit/chainlink-common/pkg/metrics" @@ -135,6 +136,37 @@ func initMonitoringResources() (em *engineMetrics, err error) { return em, nil } +// Note: due to the OTEL specification, all histogram buckets +// Must be defined when the beholder client is created +func MetricViews() []sdkmetric.View { + return []sdkmetric.View{ + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_earlyexit_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 1, 10, 100}, + }}, + ), + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_completed_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 100, 1000, 10_000, 50_000, 100_0000, 500_000}, + }}, + ), + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_error_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 20, 60, 120, 240}, + }}, + ), + sdkmetric.NewView( + sdkmetric.Instrument{Name: "platform_engine_workflow_step_time_seconds"}, + sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{0, 20, 60, 120, 240}, + }}, + ), + } +} + // workflowsMetricLabeler wraps monitoring.MetricsLabeler to provide workflow specific utilities // for monitoring resources type workflowsMetricLabeler struct { diff --git a/deployment/go.mod b/deployment/go.mod index b914f76d59b..7908b6a8048 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -25,7 +25,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/deployment/go.sum b/deployment/go.sum index d740931e9a4..fec529e51c6 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1411,8 +1411,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/go.mod b/go.mod index f1d3b1b71e5..ad71fa75be3 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db github.com/smartcontractkit/chainlink-feeds v0.1.1 @@ -106,6 +106,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 go.opentelemetry.io/otel v1.31.0 go.opentelemetry.io/otel/metric v1.31.0 + go.opentelemetry.io/otel/sdk/metric v1.31.0 go.opentelemetry.io/otel/trace v1.31.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -364,7 +365,6 @@ require ( go.opentelemetry.io/otel/log v0.6.0 // indirect go.opentelemetry.io/otel/sdk v1.31.0 // indirect go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/ratelimit v0.3.1 // indirect golang.org/x/arch v0.11.0 // indirect diff --git a/go.sum b/go.sum index cdf7fb3805d..42de8ab4a72 100644 --- a/go.sum +++ b/go.sum @@ -1125,8 +1125,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index b7ef4de1bae..b9c6f213277 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -41,7 +41,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.31 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 9cc6814f3cc..6914a06501f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1432,8 +1432,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 847fc58b543..34717eea023 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -19,7 +19,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index c4215f0c19e..bcb3680e9c5 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1423,8 +1423,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d h1:5XKarlliHXVVAhpCeOAx/TRU7eWsJ3tkqRI3I6Cc0SU= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241204184525-29871ced7b4d/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= From 83a36e9c58ddc924d79adda3c8327a47c1231d1f Mon Sep 17 00:00:00 2001 From: Makram Date: Fri, 6 Dec 2024 16:47:31 +0200 Subject: [PATCH 29/55] integration-tests/smoke/ccip: increase batch size (#15444) * integration-tests/smoke/ccip: increase batch size * bump balance of sender * bump cl-ccip to main * deployment/ccip/changeset: conform to ChangeSet iface * Revert "deployment/ccip/changeset: conform to ChangeSet iface" This reverts commit 449a77d1f5b07cc751c6f084827b7d53b8975254. * changes * split into separate tests * fix lint * rm comment * const * bump to a million --- .github/e2e-tests.yml | 13 - .github/integration-in-memory-tests.yml | 8 + deployment/ccip/changeset/test_helpers.go | 13 +- deployment/environment.go | 3 + deployment/environment/memory/chain.go | 6 +- deployment/environment/memory/environment.go | 1 + .../smoke/ccip/ccip_batching_test.go | 578 +++++++++--------- 7 files changed, 312 insertions(+), 310 deletions(-) diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index a671c081c1a..3b394293378 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -948,19 +948,6 @@ runner-test-matrix: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_batching_test.go:* - path: integration-tests/smoke/ccip/ccip_batching_test.go - test_env_type: docker - runs_on: ubuntu-latest - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_batching_test.go -timeout 12m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2,SIMULATED_3 - E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_token_transfer_test.go:* path: integration-tests/smoke/ccip/ccip_token_transfer_test.go test_env_type: docker diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index c5e0f088afe..4b4fd71258d 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -31,6 +31,14 @@ runner-test-matrix: triggers: - PR Integration CCIP Tests test_cmd: cd integration-tests/smoke/ccip && go test ccip_fee_boosting_test.go -timeout 12m -test.parallel=2 -count=1 -json + + - id: smoke/ccip/ccip_batching_test.go:* + path: integration-tests/smoke/ccip/ccip_batching_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_batching_test.go -timeout 12m -test.parallel=2 -count=1 -json - id: contracts/ccipreader_test.go:* path: integration-tests/contracts/ccipreader_test.go diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index eb719450a0a..1ee8b0d0e42 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -286,9 +286,15 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, TimelockMinDelay: big.NewInt(0), } } - var usdcChains []uint64 - if tCfg != nil && tCfg.IsUSDC { - usdcChains = allChains + var ( + usdcChains []uint64 + isMulticall3 bool + ) + if tCfg != nil { + if tCfg.IsUSDC { + usdcChains = allChains + } + isMulticall3 = tCfg.IsMultiCall3 } // Need to deploy prerequisites first so that we can form the USDC config // no proposals to be made, timelock can be passed as nil here @@ -303,6 +309,7 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, ChainSelectors: allChains, Opts: []PrerequisiteOpt{ WithUSDCChains(usdcChains), + WithMulticall3(isMulticall3), }, }, }, diff --git a/deployment/environment.go b/deployment/environment.go index bdf9fe6d5de..2de16a32cab 100644 --- a/deployment/environment.go +++ b/deployment/environment.go @@ -54,6 +54,9 @@ type Chain struct { // Note the Sign function can be abstract supporting a variety of key storage mechanisms (e.g. KMS etc). DeployerKey *bind.TransactOpts Confirm func(tx *types.Transaction) (uint64, error) + // Users are a set of keys that can be used to interact with the chain. + // These are distinct from the deployer key. + Users []*bind.TransactOpts } // Environment represents an instance of a deployed product diff --git a/deployment/environment/memory/chain.go b/deployment/environment/memory/chain.go index 58f71a83a8c..40a20a02416 100644 --- a/deployment/environment/memory/chain.go +++ b/deployment/environment/memory/chain.go @@ -9,12 +9,12 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" ) type EVMChain struct { @@ -66,7 +66,7 @@ func evmChain(t *testing.T, numUsers int) EVMChain { owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) require.NoError(t, err) genesis := types.GenesisAlloc{ - owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(700000), big.NewInt(params.Ether))}} + owner.From: {Balance: assets.Ether(1_000_000).ToInt()}} // create a set of user keys var users []*bind.TransactOpts for j := 0; j < numUsers; j++ { @@ -75,7 +75,7 @@ func evmChain(t *testing.T, numUsers int) EVMChain { user, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) require.NoError(t, err) users = append(users, user) - genesis[user.From] = types.Account{Balance: big.NewInt(0).Mul(big.NewInt(700000), big.NewInt(params.Ether))} + genesis[user.From] = types.Account{Balance: assets.Ether(1_000_000).ToInt()} } // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test backend := simulated.NewBackend(genesis, simulated.WithBlockGasLimit(50000000)) diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index f4692998d34..e8f0c265101 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -94,6 +94,7 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de return receipt.BlockNumber.Uint64(), nil } }, + Users: chain.Users, } } return chains diff --git a/integration-tests/smoke/ccip/ccip_batching_test.go b/integration-tests/smoke/ccip/ccip_batching_test.go index c801e899585..8c3615fbb20 100644 --- a/integration-tests/smoke/ccip/ccip_batching_test.go +++ b/integration-tests/smoke/ccip/ccip_batching_test.go @@ -9,20 +9,15 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -30,16 +25,33 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" ) -func Test_CCIPBatching(t *testing.T) { +const ( + numMessages = 40 +) + +type batchTestSetup struct { + e changeset.DeployedEnv + state changeset.CCIPOnChainState + sourceChain1 uint64 + sourceChain2 uint64 + destChain uint64 +} + +func newBatchTestSetup(t *testing.T) batchTestSetup { // Setup 3 chains, with 2 lanes going to the dest. - lggr := logger.TestLogger(t) - ctx := changeset.Context(t) - // Will load 3 chains when specified by the overrides.toml or env vars (E2E_TEST_SELECTED_NETWORK). - // See e2e-tests.yml. - e, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, &changeset.TestConfigs{ - IsUSDC: false, - IsMultiCall3: true, // needed for this test - }) + e := changeset.NewMemoryEnvironmentWithJobsAndContracts( + t, + logger.TestLogger(t), + memory.MemoryEnvironmentConfig{ + Chains: 3, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 2, + }, + &changeset.TestConfigs{ + IsMultiCall3: true, + }, + ) state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) @@ -61,251 +73,260 @@ func Test_CCIPBatching(t *testing.T) { require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, sourceChain1, destChain, false)) require.NoError(t, changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(e.Env, state, sourceChain2, destChain, false)) - const ( - numMessages = 5 - ) + return batchTestSetup{e, state, sourceChain1, sourceChain2, destChain} +} + +func Test_CCIPBatching_MaxBatchSizeEVM(t *testing.T) { + t.Parallel() + + ctx := changeset.Context(t) + setup := newBatchTestSetup(t) + sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state + var ( startSeqNum = map[uint64]ccipocr3.SeqNum{ sourceChain1: 1, sourceChain2: 1, } - ) - - t.Run("batch data only messages from single source", func(t *testing.T) { - var ( - sourceChain = sourceChain1 - ) - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChain], + sourceChain = sourceChain1 + transactors = []*bind.TransactOpts{ e.Env.Chains[sourceChain].DeployerKey, - state.Chains[sourceChain].OnRamp, - state.Chains[sourceChain].Router, - state.Chains[sourceChain].Multicall3, - destChain, - numMessages, - common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - ) - require.NoError(t, err) - - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( - t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, - ccipocr3.NewSeqNumRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), - true, - ) - require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) - - states, err := changeset.ConfirmExecWithSeqNrs( - t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, - genSeqNrRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), - ) - require.NoError(t, err) - // assert that all states are successful - for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + e.Env.Chains[sourceChain].Users[0], } + errs = make(chan error, len(transactors)) + ) - startSeqNum[sourceChain] = startSeqNum[sourceChain] + numMessages - }) - - t.Run("batch data only messages from multiple sources", func(t *testing.T) { - t.Skipf("skipping - failing consistently in CI") - var ( - wg sync.WaitGroup - sourceChains = []uint64{sourceChain1, sourceChain2} - errs = make(chan error, len(sourceChains)) - ) - - for _, srcChain := range sourceChains { - wg.Add(1) - go sendMessagesAsync( + for _, transactor := range transactors { + go func() { + err := sendMessages( ctx, t, - e, - state, - srcChain, + e.Env.Chains[sourceChain], + transactor, + state.Chains[sourceChain].OnRamp, + state.Chains[sourceChain].Router, + state.Chains[sourceChain].Multicall3, destChain, - numMessages, - &wg, - errs, + merklemulti.MaxNumberTreeLeaves/2, + common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), ) - } - - wg.Wait() - - var i int - for i < len(sourceChains) { - select { - case err := <-errs: - require.NoError(t, err) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all errors before test context was done") - } - } + t.Log("sendMessages error:", err, ", writing to channel") + errs <- err + t.Log("sent error to channel") + }() + } - // confirm the commit reports - outputErrs := make(chan outputErr[*offramp.OffRampCommitReportAccepted], len(sourceChains)) - for _, srcChain := range sourceChains { - wg.Add(1) - go assertCommitReportsAsync( - t, - e, - state, - srcChain, - destChain, - startSeqNum[srcChain], - startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1, - &wg, - outputErrs, - ) + var i = 0 + for i < len(transactors) { + select { + case err := <-errs: + require.NoError(t, err) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all errors before test context was done") } + } - t.Log("waiting for commit report") - wg.Wait() - - i = 0 - var reports []*offramp.OffRampCommitReportAccepted - for i < len(sourceChains) { - select { - case outputErr := <-outputErrs: - require.NoError(t, outputErr.err) - reports = append(reports, outputErr.output) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all commit reports before test context was done") - } - } + _, err := changeset.ConfirmCommitWithExpectedSeqNumRange( + t, + e.Env.Chains[sourceChain], + e.Env.Chains[destChain], + state.Chains[destChain].OffRamp, + nil, // startBlock + ccipocr3.NewSeqNumRange( + startSeqNum[sourceChain], + startSeqNum[sourceChain]+ccipocr3.SeqNum(merklemulti.MaxNumberTreeLeaves)-1, + ), + true, + ) + require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) +} - // the reports should be the same for both, since both roots should be batched within - // that one report. - require.Lenf(t, reports, len(sourceChains), "expected %d commit reports", len(sourceChains)) - require.NotNil(t, reports[0], "commit report should not be nil") - require.NotNil(t, reports[1], "commit report should not be nil") - // TODO: this assertion is failing, despite messages being sent at the same time. - // require.Equal(t, reports[0], reports[1], "commit reports should be the same") - - // confirm execution - execErrs := make(chan outputErr[map[uint64]int], len(sourceChains)) - for _, srcChain := range sourceChains { - wg.Add(1) - go assertExecAsync( - t, - e, - state, - srcChain, - destChain, - genSeqNrRange(startSeqNum[srcChain], startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1), - &wg, - execErrs, - ) - } +func Test_CCIPBatching_MultiSource(t *testing.T) { + // t.Skip("Exec not working, boosting not working correctly") - t.Log("waiting for exec reports") - wg.Wait() - - i = 0 - var execStates []map[uint64]int - for i < len(sourceChains) { - select { - case outputErr := <-execErrs: - require.NoError(t, outputErr.err) - execStates = append(execStates, outputErr.output) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all exec reports before test context was done") - } - } + t.Parallel() - // assert that all states are successful - for _, states := range execStates { - for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) - } - } + // Setup 3 chains, with 2 lanes going to the dest. + ctx := changeset.Context(t) + setup := newBatchTestSetup(t) + sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state - // update the start and end seq nums - for _, srcChain := range sourceChains { - startSeqNum[srcChain] = startSeqNum[srcChain] + numMessages + var ( + wg sync.WaitGroup + sourceChains = []uint64{sourceChain1, sourceChain2} + errs = make(chan error, len(sourceChains)) + startSeqNum = map[uint64]ccipocr3.SeqNum{ + sourceChain1: 1, + sourceChain2: 1, } - }) - - t.Run("max evm batch size", func(t *testing.T) { - t.Skipf("This test is flaky, skipping until the issue related to fee calculation is resolved") - var ( - sourceChain = sourceChain1 - otherSender = mustNewTransactor(t, e.Env.Chains[sourceChain]) - transactors = []*bind.TransactOpts{ - e.Env.Chains[sourceChain].DeployerKey, - otherSender, - } - errs = make(chan error, len(transactors)) - ) + ) - // transfer some eth to the other sender from the DeployerKey - sendEth( + for _, srcChain := range sourceChains { + wg.Add(1) + go sendMessagesAsync( ctx, t, - e.Env.Chains[sourceChain], - e.Env.Chains[sourceChain].DeployerKey, - otherSender.From, - assets.Ether(20).ToInt(), + e, + state, + srcChain, + destChain, + numMessages, + &wg, + errs, ) + } - for _, transactor := range transactors { - go func() { - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChain], - transactor, - state.Chains[sourceChain].OnRamp, - state.Chains[sourceChain].Router, - state.Chains[sourceChain].Multicall3, - destChain, - merklemulti.MaxNumberTreeLeaves/2, - common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - ) - t.Log("sendMessages error:", err, ", writing to channel") - errs <- err - t.Log("sent error to channel") - }() + wg.Wait() + + var i int + for i < len(sourceChains) { + select { + case err := <-errs: + require.NoError(t, err) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all errors before test context was done") } + } - var i = 0 - for i < len(transactors) { - select { - case err := <-errs: - require.NoError(t, err) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all errors before test context was done") - } + // confirm the commit reports + outputErrs := make(chan outputErr[*offramp.OffRampCommitReportAccepted], len(sourceChains)) + for _, srcChain := range sourceChains { + wg.Add(1) + go assertCommitReportsAsync( + t, + e, + state, + srcChain, + destChain, + startSeqNum[srcChain], + startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1, + &wg, + outputErrs, + ) + } + + t.Log("waiting for commit report") + wg.Wait() + + i = 0 + var reports []*offramp.OffRampCommitReportAccepted + for i < len(sourceChains) { + select { + case outputErr := <-outputErrs: + require.NoError(t, outputErr.err) + reports = append(reports, outputErr.output) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all commit reports before test context was done") } + } - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( + // the reports should be the same for both, since both roots should be batched within + // that one report. + require.Lenf(t, reports, len(sourceChains), "expected %d commit reports", len(sourceChains)) + require.NotNil(t, reports[0], "commit report should not be nil") + require.NotNil(t, reports[1], "commit report should not be nil") + // TODO: this assertion is failing, despite messages being sent at the same time. + // require.Equal(t, reports[0], reports[1], "commit reports should be the same") + + // confirm execution + execErrs := make(chan outputErr[map[uint64]int], len(sourceChains)) + for _, srcChain := range sourceChains { + wg.Add(1) + go assertExecAsync( t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, // startBlock - ccipocr3.NewSeqNumRange( - startSeqNum[sourceChain], - startSeqNum[sourceChain]+ccipocr3.SeqNum(merklemulti.MaxNumberTreeLeaves)-1, - ), - true, + e, + state, + srcChain, + destChain, + genSeqNrRange(startSeqNum[srcChain], startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1), + &wg, + execErrs, ) - require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) - }) + } + + t.Log("waiting for exec reports") + wg.Wait() + + i = 0 + var execStates []map[uint64]int + for i < len(sourceChains) { + select { + case outputErr := <-execErrs: + require.NoError(t, outputErr.err) + execStates = append(execStates, outputErr.output) + i++ + case <-ctx.Done(): + require.FailNow(t, "didn't get all exec reports before test context was done") + } + } + + // assert that all states are successful + for _, states := range execStates { + for _, state := range states { + require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + } + } +} + +func Test_CCIPBatching_SingleSource(t *testing.T) { + t.Parallel() + + // Setup 3 chains, with 2 lanes going to the dest. + ctx := changeset.Context(t) + setup := newBatchTestSetup(t) + sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state + + var ( + startSeqNum = map[uint64]ccipocr3.SeqNum{ + sourceChain1: 1, + sourceChain2: 1, + } + ) + + var ( + sourceChain = sourceChain1 + ) + err := sendMessages( + ctx, + t, + e.Env.Chains[sourceChain], + e.Env.Chains[sourceChain].DeployerKey, + state.Chains[sourceChain].OnRamp, + state.Chains[sourceChain].Router, + state.Chains[sourceChain].Multicall3, + destChain, + numMessages, + common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), + ) + require.NoError(t, err) + + _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( + t, + e.Env.Chains[sourceChain], + e.Env.Chains[destChain], + state.Chains[destChain].OffRamp, + nil, + ccipocr3.NewSeqNumRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), + true, + ) + require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) + + states, err := changeset.ConfirmExecWithSeqNrs( + t, + e.Env.Chains[sourceChain], + e.Env.Chains[destChain], + state.Chains[destChain].OffRamp, + nil, + genSeqNrRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), + ) + require.NoError(t, err) + // assert that all states are successful + for _, state := range states { + require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) + } } type outputErr[T any] struct { @@ -373,18 +394,34 @@ func sendMessagesAsync( out chan<- error, ) { defer wg.Done() - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChainSelector], - e.Env.Chains[sourceChainSelector].DeployerKey, - state.Chains[sourceChainSelector].OnRamp, - state.Chains[sourceChainSelector].Router, - state.Chains[sourceChainSelector].Multicall3, - destChainSelector, - numMessages, - common.LeftPadBytes(state.Chains[destChainSelector].Receiver.Address().Bytes(), 32), + var err error + + const ( + numRetries = 3 ) + + // we retry a bunch of times just in case there is a race b/w the prices being + // posted and the messages being sent. + for i := 0; i < numRetries; i++ { + err = sendMessages( + ctx, + t, + e.Env.Chains[sourceChainSelector], + e.Env.Chains[sourceChainSelector].DeployerKey, + state.Chains[sourceChainSelector].OnRamp, + state.Chains[sourceChainSelector].Router, + state.Chains[sourceChainSelector].Multicall3, + destChainSelector, + numMessages, + common.LeftPadBytes(state.Chains[destChainSelector].Receiver.Address().Bytes(), 32), + ) + if err == nil { + break + } + + t.Log("sendMessagesAsync error is non-nil:", err, ", retrying") + } + t.Log("sendMessagesAsync error:", err, ", writing to channel") out <- err } @@ -412,8 +449,13 @@ func sendMessages( return fmt.Errorf("generate messages: %w", err) } + currBalance, err := sourceChain.Client.BalanceAt(ctx, sourceTransactOpts.From, nil) + if err != nil { + return fmt.Errorf("get balance: %w", err) + } + // Send the tx with the messages through the multicall - t.Logf("Sending %d messages with total value %s", numMessages, totalValue.String()) + t.Logf("Sending %d messages with total value %s, current balance: %s", numMessages, totalValue.String(), currBalance.String()) tx, err := sourceMulticall3.Aggregate3Value( &bind.TransactOpts{ From: sourceTransactOpts.From, @@ -434,7 +476,9 @@ func sendMessages( if err != nil { return fmt.Errorf("get message sent event: %w", err) } - defer iter.Close() + defer func() { + require.NoError(t, iter.Close()) + }() // there should be numMessages messages emitted for i := 0; i < numMessages; i++ { @@ -461,7 +505,7 @@ func genMessages( Data: []byte(fmt.Sprintf("hello world %d", i)), TokenAmounts: nil, FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, + ExtraArgs: changeset.MakeEVMExtraArgsV2(50_000, false), } fee, err := sourceRouter.GetFee(&bind.CallOpts{Context: ctx}, destChainSelector, msg) @@ -495,51 +539,3 @@ func genSeqNrRange(start, end ccipocr3.SeqNum) []uint64 { } return seqNrs } - -func mustNewTransactor(t *testing.T, chain deployment.Chain) *bind.TransactOpts { - chainID, err := chainsel.GetChainIDFromSelector(chain.Selector) - require.NoError(t, err) - chainIDBig, ok := new(big.Int).SetString(chainID, 10) - require.True(t, ok, "evm chainID must be integral") - key, err := crypto.GenerateKey() - require.NoError(t, err) - transactor, err := bind.NewKeyedTransactorWithChainID(key, chainIDBig) - require.NoError(t, err) - return transactor -} - -func sendEth( - ctx context.Context, - t *testing.T, - chain deployment.Chain, - from *bind.TransactOpts, - to common.Address, - value *big.Int, -) { - balance, err := chain.Client.BalanceAt(ctx, from.From, nil) - require.NoError(t, err) - if balance.Cmp(value) < 0 { - t.Fatalf("insufficient balance: %s < %s", balance.String(), value.String()) - } - t.Logf("balance of from account %s: %s", from.From.String(), balance.String()) - - nonce, err := chain.Client.PendingNonceAt(ctx, from.From) - require.NoError(t, err) - gp, err := chain.Client.SuggestGasPrice(ctx) - require.NoError(t, err) - tx := gethtypes.NewTx(&gethtypes.LegacyTx{ - Nonce: nonce, - GasPrice: gp, - Gas: 21_000, - To: &to, - Value: value, - Data: nil, - }) - signedTx, err := from.Signer(from.From, tx) - require.NoError(t, err) - err = chain.Client.SendTransaction(ctx, signedTx) - require.NoError(t, err) - t.Log("sent funding tx:", signedTx.Hash().Hex()) - _, err = deployment.ConfirmIfNoError(chain, signedTx, err) - require.NoError(t, err) -} From c9496ef59fae1d3d2428b22a8390d0cfbca099a6 Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Fri, 6 Dec 2024 11:53:57 -0500 Subject: [PATCH 30/55] Add ccip to integration-tests (#15516) --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ef1c0f98913..c2d6208d0e3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -133,10 +133,10 @@ core/scripts/gateway @smartcontractkit/dev-services # Tests /integration-tests/ @smartcontractkit/test-tooling-team @smartcontractkit/core -/integration-tests/ccip-tests @smartcontractkit/ccip-offchain @smartcontractkit/core +/integration-tests/ccip-tests @smartcontractkit/ccip-offchain @smartcontractkit/core @smartcontractkit/ccip /integration-tests/**/*keeper* @smartcontractkit/dev-services @smartcontractkit/core /integration-tests/**/*automation* @smartcontractkit/dev-services @smartcontractkit/core -/integration-tests/**/*ccip* @smartcontractkit/ccip-offchain @smartcontractkit/core +/integration-tests/**/*ccip* @smartcontractkit/ccip-offchain @smartcontractkit/core @smartcontractkit/ccip # Deployment tooling /deployment @smartcontractkit/ccip @smartcontractkit/keystone @smartcontractkit/core @smartcontractkit/deployment-automation From f8a221f284ce8747a943284a647905586fa3dda0 Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Fri, 6 Dec 2024 08:54:01 -0800 Subject: [PATCH 31/55] Ccip-4506 log improvements in deployment code (#15535) * improve logging in deployment code to denote human readable chain name * fix * fix test * more logs and review comments * review comment * change to String to include chain selector * revert * more fixes * revert --- .../ccip/changeset/cs_add_chain_test.go | 1 + deployment/ccip/changeset/cs_deploy_chain.go | 69 +++++++++---------- deployment/ccip/changeset/cs_home_chain.go | 25 ++++--- .../ccip/changeset/cs_home_chain_test.go | 6 +- .../ccip/changeset/cs_initial_add_chain.go | 32 +++++++-- deployment/ccip/changeset/cs_prerequisites.go | 42 +++++------ .../changeset/internal/deploy_home_chain.go | 34 ++++++--- deployment/ccip/changeset/state.go | 34 ++++----- .../ccip/changeset/test_usdc_helpers.go | 14 ++-- .../common/changeset/deploy_link_token.go | 2 +- deployment/common/changeset/internal/mcms.go | 10 +-- deployment/common/view/nops.go | 4 +- .../common/view/types/contract_state.go | 6 +- deployment/common/view/v1_0/link_token.go | 7 +- deployment/environment.go | 20 +++++- .../environment/clo/models/models_gen.go | 10 +-- deployment/environment/devenv/chain.go | 18 ++--- deployment/environment/memory/environment.go | 15 ++-- deployment/helpers.go | 27 ++++++-- deployment/keystone/ocr3config_test.go | 8 +-- deployment/multiclient.go | 22 ++++-- 21 files changed, 235 insertions(+), 171 deletions(-) diff --git a/deployment/ccip/changeset/cs_add_chain_test.go b/deployment/ccip/changeset/cs_add_chain_test.go index c83872c0dd7..f6e1c04c469 100644 --- a/deployment/ccip/changeset/cs_add_chain_test.go +++ b/deployment/ccip/changeset/cs_add_chain_test.go @@ -227,6 +227,7 @@ func TestAddChainInbound(t *testing.T) { // verify if the configs are updated require.NoError(t, ValidateCCIPHomeConfigSetUp( + e.Env.Logger, state.Chains[e.HomeChainSel].CapabilityRegistry, state.Chains[e.HomeChainSel].CCIPHome, newChain, diff --git a/deployment/ccip/changeset/cs_deploy_chain.go b/deployment/ccip/changeset/cs_deploy_chain.go index b57c00fd796..e2762b27578 100644 --- a/deployment/ccip/changeset/cs_deploy_chain.go +++ b/deployment/ccip/changeset/cs_deploy_chain.go @@ -182,31 +182,31 @@ func deployChainContracts( } chainState, chainExists := state.Chains[chain.Selector] if !chainExists { - return fmt.Errorf("chain %d not found in existing state, deploy the prerequisites first", chain.Selector) + return fmt.Errorf("chain %s not found in existing state, deploy the prerequisites first", chain.String()) } if chainState.Weth9 == nil { - return fmt.Errorf("weth9 not found for chain %d, deploy the prerequisites first", chain.Selector) + return fmt.Errorf("weth9 not found for chain %s, deploy the prerequisites first", chain.String()) } if chainState.Timelock == nil { - return fmt.Errorf("timelock not found for chain %d, deploy the mcms contracts first", chain.Selector) + return fmt.Errorf("timelock not found for chain %s, deploy the mcms contracts first", chain.String()) } weth9Contract := chainState.Weth9 if chainState.LinkToken == nil { - return fmt.Errorf("link token not found for chain %d, deploy the prerequisites first", chain.Selector) + return fmt.Errorf("link token not found for chain %s, deploy the prerequisites first", chain.String()) } linkTokenContract := chainState.LinkToken if chainState.TokenAdminRegistry == nil { - return fmt.Errorf("token admin registry not found for chain %d, deploy the prerequisites first", chain.Selector) + return fmt.Errorf("token admin registry not found for chain %s, deploy the prerequisites first", chain.String()) } tokenAdminReg := chainState.TokenAdminRegistry if chainState.RegistryModule == nil { - return fmt.Errorf("registry module not found for chain %d, deploy the prerequisites first", chain.Selector) + return fmt.Errorf("registry module not found for chain %s, deploy the prerequisites first", chain.String()) } if chainState.Router == nil { - return fmt.Errorf("router not found for chain %d, deploy the prerequisites first", chain.Selector) + return fmt.Errorf("router not found for chain %s, deploy the prerequisites first", chain.String()) } if chainState.Receiver == nil { - ccipReceiver, err := deployment.DeployContract(e.Logger, chain, ab, + _, err := deployment.DeployContract(e.Logger, chain, ab, func(chain deployment.Chain) deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( chain.DeployerKey, @@ -221,9 +221,8 @@ func deployChainContracts( e.Logger.Errorw("Failed to deploy receiver", "err", err) return err } - e.Logger.Infow("deployed receiver", "addr", ccipReceiver.Address) } else { - e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address) + e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address, "chain", chain.String()) } rmnRemoteContract := chainState.RMNRemote if chainState.RMNRemote == nil { @@ -242,20 +241,19 @@ func deployChainContracts( } }) if err != nil { - e.Logger.Errorw("Failed to deploy RMNRemote", "err", err) + e.Logger.Errorw("Failed to deploy RMNRemote", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("deployed RMNRemote", "addr", rmnRemote.Address) rmnRemoteContract = rmnRemote.Contract } else { - e.Logger.Infow("rmn remote already deployed", "addr", chainState.RMNRemote.Address) + e.Logger.Infow("rmn remote already deployed", "chain", chain.String(), "addr", chainState.RMNRemote.Address) } activeDigest, err := rmnHome.GetActiveDigest(&bind.CallOpts{}) if err != nil { - e.Logger.Errorw("Failed to get active digest", "err", err) + e.Logger.Errorw("Failed to get active digest", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("setting active home digest to rmn remote", "digest", activeDigest) + e.Logger.Infow("setting active home digest to rmn remote", "chain", chain.String(), "digest", activeDigest) tx, err := rmnRemoteContract.SetConfig(chain.DeployerKey, rmn_remote.RMNRemoteConfig{ RmnHomeContractConfigDigest: activeDigest, @@ -265,7 +263,7 @@ func deployChainContracts( F: 0, // TODO: update when we have signers }) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm RMNRemote config", "err", err) + e.Logger.Errorw("Failed to confirm RMNRemote config", "chain", chain.String(), "err", err) return err } @@ -286,16 +284,15 @@ func deployChainContracts( } }) if err != nil { - e.Logger.Errorw("Failed to deploy RMNProxyNew", "err", err) + e.Logger.Errorw("Failed to deploy RMNProxyNew", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("deployed new RMNProxyNew", "addr", rmnProxy.Address) rmnProxyContract = rmnProxy.Contract } else { - e.Logger.Infow("rmn proxy already deployed", "addr", chainState.RMNProxyNew.Address) + e.Logger.Infow("rmn proxy already deployed", "chain", chain.String(), "addr", chainState.RMNProxyNew.Address) } if chainState.TestRouter == nil { - testRouterContract, err := deployment.DeployContract(e.Logger, chain, ab, + _, err := deployment.DeployContract(e.Logger, chain, ab, func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { routerAddr, tx2, routerC, err2 := router.DeployRouter( chain.DeployerKey, @@ -308,12 +305,11 @@ func deployChainContracts( } }) if err != nil { - e.Logger.Errorw("Failed to deploy test router", "err", err) + e.Logger.Errorw("Failed to deploy test router", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("deployed test router", "addr", testRouterContract.Address) } else { - e.Logger.Infow("test router already deployed", "addr", chainState.TestRouter.Address) + e.Logger.Infow("test router already deployed", "chain", chain.String(), "addr", chainState.TestRouter.Address) } nmContract := chainState.NonceManager @@ -330,13 +326,12 @@ func deployChainContracts( } }) if err != nil { - e.Logger.Errorw("Failed to deploy nonce manager", "err", err) + e.Logger.Errorw("Failed to deploy nonce manager", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("Deployed nonce manager", "addr", nonceManager.Address) nmContract = nonceManager.Contract } else { - e.Logger.Infow("nonce manager already deployed", "addr", chainState.NonceManager.Address) + e.Logger.Infow("nonce manager already deployed", "chain", chain.String(), "addr", chainState.NonceManager.Address) } feeQuoterContract := chainState.FeeQuoter if chainState.FeeQuoter == nil { @@ -371,13 +366,12 @@ func deployChainContracts( } }) if err != nil { - e.Logger.Errorw("Failed to deploy fee quoter", "err", err) + e.Logger.Errorw("Failed to deploy fee quoter", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("Deployed fee quoter", "addr", feeQuoter.Address) feeQuoterContract = feeQuoter.Contract } else { - e.Logger.Infow("fee quoter already deployed", "addr", chainState.FeeQuoter.Address) + e.Logger.Infow("fee quoter already deployed", "chain", chain.String(), "addr", chainState.FeeQuoter.Address) } onRampContract := chainState.OnRamp if onRampContract == nil { @@ -403,13 +397,12 @@ func deployChainContracts( } }) if err != nil { - e.Logger.Errorw("Failed to deploy onramp", "err", err) + e.Logger.Errorw("Failed to deploy onramp", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("Deployed onramp", "addr", onRamp.Address) onRampContract = onRamp.Contract } else { - e.Logger.Infow("onramp already deployed", "addr", chainState.OnRamp.Address) + e.Logger.Infow("onramp already deployed", "chain", chain.String(), "addr", chainState.OnRamp.Address) } offRampContract := chainState.OffRamp if offRampContract == nil { @@ -436,13 +429,12 @@ func deployChainContracts( } }) if err != nil { - e.Logger.Errorw("Failed to deploy offramp", "err", err) + e.Logger.Errorw("Failed to deploy offramp", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("Deployed offramp", "addr", offRamp.Address) offRampContract = offRamp.Contract } else { - e.Logger.Infow("offramp already deployed", "addr", chainState.OffRamp.Address) + e.Logger.Infow("offramp already deployed", "chain", chain.String(), "addr", chainState.OffRamp.Address) } // Basic wiring is always needed. tx, err = feeQuoterContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ @@ -451,16 +443,17 @@ func deployChainContracts( AddedCallers: []common.Address{offRampContract.Address(), chain.DeployerKey.From}, }) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "err", err) + e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "chain", chain.String(), "err", err) return err } - + e.Logger.Infow("Added fee quoter authorized callers", "chain", chain.String(), "callers", []common.Address{offRampContract.Address(), chain.DeployerKey.From}) tx, err = nmContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ AddedCallers: []common.Address{offRampContract.Address(), onRampContract.Address()}, }) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to update nonce manager with ramps", "err", err) + e.Logger.Errorw("Failed to update nonce manager with ramps", "chain", chain.String(), "err", err) return err } + e.Logger.Infow("Added nonce manager authorized callers", "chain", chain.String(), "callers", []common.Address{offRampContract.Address(), onRampContract.Address()}) return nil } diff --git a/deployment/ccip/changeset/cs_home_chain.go b/deployment/ccip/changeset/cs_home_chain.go index 0df8d87affb..750b21229aa 100644 --- a/deployment/ccip/changeset/cs_home_chain.go +++ b/deployment/ccip/changeset/cs_home_chain.go @@ -13,6 +13,7 @@ import ( "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" @@ -111,7 +112,7 @@ func deployCapReg( } }) if err != nil { - lggr.Errorw("Failed to deploy capreg", "err", err) + lggr.Errorw("Failed to deploy capreg", "chain", chain.String(), "err", err) return nil, err } return capReg, nil @@ -152,10 +153,9 @@ func deployHomeChain( } }) if err != nil { - lggr.Errorw("Failed to deploy CCIPHome", "err", err) + lggr.Errorw("Failed to deploy CCIPHome", "chain", chain.String(), "err", err) return nil, err } - lggr.Infow("deployed CCIPHome", "addr", ccipHome.Address) rmnHome, err := deployment.DeployContract( lggr, chain, ab, @@ -170,10 +170,9 @@ func deployHomeChain( }, ) if err != nil { - lggr.Errorw("Failed to deploy RMNHome", "err", err) + lggr.Errorw("Failed to deploy RMNHome", "chain", chain.String(), "err", err) return nil, err } - lggr.Infow("deployed RMNHome", "addr", rmnHome.Address) // considering the RMNHome is recently deployed, there is no digest to overwrite tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmnHomeStatic, rmnHomeDynamic, [32]byte{}) @@ -184,19 +183,19 @@ func deployHomeChain( rmnCandidateDigest, err := rmnHome.Contract.GetCandidateDigest(nil) if err != nil { - lggr.Errorw("Failed to get RMNHome candidate digest", "err", err) + lggr.Errorw("Failed to get RMNHome candidate digest", "chain", chain.String(), "err", err) return nil, err } tx, err = rmnHome.Contract.PromoteCandidateAndRevokeActive(chain.DeployerKey, rmnCandidateDigest, [32]byte{}) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "err", err) + lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "chain", chain.String(), "err", err) return nil, err } rmnActiveDigest, err := rmnHome.Contract.GetActiveDigest(nil) if err != nil { - lggr.Errorw("Failed to get RMNHome active digest", "err", err) + lggr.Errorw("Failed to get RMNHome active digest", "chain", chain.String(), "err", err) return nil, err } lggr.Infow("Got rmn home active digest", "digest", rmnActiveDigest) @@ -217,14 +216,14 @@ func deployHomeChain( }, }) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to add capabilities", "err", err) + lggr.Errorw("Failed to add capabilities", "chain", chain.String(), "err", err) return nil, err } tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, nodeOps) txBlockNum, err := deployment.ConfirmIfNoError(chain, tx, err) if err != nil { - lggr.Errorw("Failed to add node operators", "err", err) + lggr.Errorw("Failed to add node operators", "chain", chain.String(), "err", err) return nil, err } addedEvent, err := capReg.Contract.FilterNodeOperatorAdded(&bind.FilterOpts{ @@ -232,7 +231,7 @@ func deployHomeChain( Context: context.Background(), }, nil, nil) if err != nil { - lggr.Errorw("Failed to filter NodeOperatorAdded event", "err", err) + lggr.Errorw("Failed to filter NodeOperatorAdded event", "chain", chain.String(), "err", err) return capReg, err } // Need to fetch nodeoperators ids to be able to add nodes for corresponding node operators @@ -246,7 +245,7 @@ func deployHomeChain( } } if len(p2pIDsByNodeOpId) != len(nodeP2PIDsPerNodeOpAdmin) { - lggr.Errorw("Failed to add all node operators", "added", maps.Keys(p2pIDsByNodeOpId), "expected", maps.Keys(nodeP2PIDsPerNodeOpAdmin)) + lggr.Errorw("Failed to add all node operators", "added", maps.Keys(p2pIDsByNodeOpId), "expected", maps.Keys(nodeP2PIDsPerNodeOpAdmin), "chain", chain.String()) return capReg, errors.New("failed to add all node operators") } // Adds initial set of nodes to CR, who all have the CCIP capability @@ -317,7 +316,7 @@ func addNodes( } tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) if err != nil { - lggr.Errorw("Failed to add nodes", "err", deployment.MaybeDataErr(err)) + lggr.Errorw("Failed to add nodes", "chain", chain.String(), "err", deployment.MaybeDataErr(err)) return err } _, err = chain.Confirm(tx) diff --git a/deployment/ccip/changeset/cs_home_chain_test.go b/deployment/ccip/changeset/cs_home_chain_test.go index 55bc7466837..a06161f7086 100644 --- a/deployment/ccip/changeset/cs_home_chain_test.go +++ b/deployment/ccip/changeset/cs_home_chain_test.go @@ -3,7 +3,6 @@ package changeset import ( "testing" - chainsel "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -43,10 +42,7 @@ func TestDeployHomeChain(t *testing.T) { require.NotNil(t, state.Chains[homeChainSel].RMNHome) snap, err := state.View([]uint64{homeChainSel}) require.NoError(t, err) - chainid, err := chainsel.ChainIdFromSelector(homeChainSel) - require.NoError(t, err) - chainName, err := chainsel.NameFromChainId(chainid) - require.NoError(t, err) + chainName := e.Chains[homeChainSel].Name() _, ok := snap[chainName] require.True(t, ok) capRegSnap, ok := snap[chainName].CapabilityRegistry[state.Chains[homeChainSel].CapabilityRegistry.Address().String()] diff --git a/deployment/ccip/changeset/cs_initial_add_chain.go b/deployment/ccip/changeset/cs_initial_add_chain.go index 0e425aef8c7..d18116b8a74 100644 --- a/deployment/ccip/changeset/cs_initial_add_chain.go +++ b/deployment/ccip/changeset/cs_initial_add_chain.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -178,19 +179,20 @@ func configureChain( e.Logger.Errorw("Failed to load existing onchain state", "err") return err } + homeChain := e.Chains[c.HomeChainSel] capReg := existingState.Chains[c.HomeChainSel].CapabilityRegistry if capReg == nil { - e.Logger.Errorw("Failed to get capability registry") + e.Logger.Errorw("Failed to get capability registry", "chain", homeChain.String()) return fmt.Errorf("capability registry not found") } ccipHome := existingState.Chains[c.HomeChainSel].CCIPHome if ccipHome == nil { - e.Logger.Errorw("Failed to get ccip home", "err", err) + e.Logger.Errorw("Failed to get ccip home", "chain", homeChain.String(), "err", err) return fmt.Errorf("ccip home not found") } rmnHome := existingState.Chains[c.HomeChainSel].RMNHome if rmnHome == nil { - e.Logger.Errorw("Failed to get rmn home", "err", err) + e.Logger.Errorw("Failed to get rmn home", "chain", homeChain.String(), "err", err) return fmt.Errorf("rmn home not found") } @@ -267,7 +269,7 @@ func addChainConfig( if _, err := deployment.ConfirmIfNoError(h, tx, err); err != nil { return ccip_home.CCIPHomeChainConfigArgs{}, err } - lggr.Infow("Applied chain config updates", "chainConfig", chainConfig) + lggr.Infow("Applied chain config updates", "homeChain", h.String(), "addedChain", chainSelector, "chainConfig", chainConfig) return chainConfig, nil } @@ -301,17 +303,17 @@ func createDON( donID := latestDon.Id + 1 - err = internal.SetupCommitDON(donID, commitConfig, capReg, home, nodes, ccipHome) + err = internal.SetupCommitDON(lggr, donID, commitConfig, capReg, home, nodes, ccipHome) if err != nil { return fmt.Errorf("setup commit don: %w", err) } // TODO: bug in contract causing this to not work as expected. - err = internal.SetupExecDON(donID, execConfig, capReg, home, nodes, ccipHome) + err = internal.SetupExecDON(lggr, donID, execConfig, capReg, home, nodes, ccipHome) if err != nil { return fmt.Errorf("setup exec don: %w", err) } - return ValidateCCIPHomeConfigSetUp(capReg, ccipHome, newChainSel) + return ValidateCCIPHomeConfigSetUp(lggr, capReg, ccipHome, newChainSel) } func addDON( @@ -369,6 +371,15 @@ func addDON( if err != nil { return err } + lggr.Debugw("Fetched OCR3 Configs", + "MultiOCR3BaseOCRConfig.F", ocrConfig.ConfigInfo.F, + "MultiOCR3BaseOCRConfig.N", ocrConfig.ConfigInfo.N, + "MultiOCR3BaseOCRConfig.IsSignatureVerificationEnabled", ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, + "Signers", ocrConfig.Signers, + "Transmitters", ocrConfig.Transmitters, + "configDigest", hex.EncodeToString(ocrConfig.ConfigInfo.ConfigDigest[:]), + "chain", dest.String(), + ) // TODO: assertions to be done as part of full state // resprentation validation CCIP-3047 if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { @@ -400,6 +411,7 @@ func addDON( // ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly func ValidateCCIPHomeConfigSetUp( + lggr logger.Logger, capReg *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, chainSel uint64, @@ -420,10 +432,12 @@ func ValidateCCIPHomeConfigSetUp( if err != nil { return fmt.Errorf("get active commit digest: %w", err) } + lggr.Debugw("Fetched active commit digest", "commitActiveDigest", hex.EncodeToString(commitActiveDigest[:])) commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) if err != nil { return fmt.Errorf("get commit candidate digest: %w", err) } + lggr.Debugw("Fetched candidate commit digest", "commitCandidateDigest", hex.EncodeToString(commitCandidateDigest[:])) if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} { return fmt.Errorf( "active config digest is empty for commit, expected nonempty, donID: %d, cfg: %+v, config digest from GetActiveDigest call: %x, config digest from GetCandidateDigest call: %x", @@ -439,6 +453,10 @@ func ValidateCCIPHomeConfigSetUp( if err != nil { return fmt.Errorf("get all exec configs: %w", err) } + lggr.Debugw("Fetched exec configs", + "ActiveConfig.ConfigDigest", hex.EncodeToString(execConfigs.ActiveConfig.ConfigDigest[:]), + "CandidateConfig.ConfigDigest", hex.EncodeToString(execConfigs.CandidateConfig.ConfigDigest[:]), + ) if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} { return fmt.Errorf("active config digest is empty for exec, expected nonempty, cfg: %v", execConfigs.ActiveConfig) } diff --git a/deployment/ccip/changeset/cs_prerequisites.go b/deployment/ccip/changeset/cs_prerequisites.go index e610dfaaeeb..2386d3bb784 100644 --- a/deployment/ccip/changeset/cs_prerequisites.go +++ b/deployment/ccip/changeset/cs_prerequisites.go @@ -153,10 +153,9 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } }) if err != nil { - lggr.Errorw("Failed to deploy mock RMN", "err", err) + lggr.Errorw("Failed to deploy mock RMN", "chain", chain.String(), "err", err) return err } - lggr.Infow("deployed mock RMN", "addr", rmn.Address) rmnProxyContract, err := deployment.DeployContract(lggr, chain, ab, func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { rmnProxyAddr, tx2, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( @@ -169,10 +168,9 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } }) if err != nil { - lggr.Errorw("Failed to deploy RMNProxyNew", "err", err) + lggr.Errorw("Failed to deploy RMNProxyExisting", "chain", chain.String(), "err", err) return err } - lggr.Infow("deployed RMNProxyNew", "addr", rmnProxyContract.Address) rmnProxy = rmnProxyContract.Contract } if tokenAdminReg == nil { @@ -186,13 +184,12 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } }) if err != nil { - e.Logger.Errorw("Failed to deploy token admin registry", "err", err) + e.Logger.Errorw("Failed to deploy token admin registry", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("deployed tokenAdminRegistry", "addr", tokenAdminRegistry) tokenAdminReg = tokenAdminRegistry.Contract } else { - e.Logger.Infow("tokenAdminRegistry already deployed", "addr", tokenAdminReg.Address) + e.Logger.Infow("tokenAdminRegistry already deployed", "chain", chain.String(), "addr", tokenAdminReg.Address) } if registryModule == nil { customRegistryModule, err := deployment.DeployContract(e.Logger, chain, ab, @@ -206,29 +203,28 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } }) if err != nil { - e.Logger.Errorw("Failed to deploy custom registry module", "err", err) + e.Logger.Errorw("Failed to deploy custom registry module", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("deployed custom registry module", "addr", customRegistryModule) registryModule = customRegistryModule.Contract } else { - e.Logger.Infow("custom registry module already deployed", "addr", registryModule.Address) + e.Logger.Infow("custom registry module already deployed", "chain", chain.String(), "addr", registryModule.Address) } isRegistryAdded, err := tokenAdminReg.IsRegistryModule(nil, registryModule.Address()) if err != nil { - e.Logger.Errorw("Failed to check if registry module is added on token admin registry", "err", err) + e.Logger.Errorw("Failed to check if registry module is added on token admin registry", "chain", chain.String(), "err", err) return fmt.Errorf("failed to check if registry module is added on token admin registry: %w", err) } if !isRegistryAdded { tx, err := tokenAdminReg.AddRegistryModule(chain.DeployerKey, registryModule.Address()) if err != nil { - e.Logger.Errorw("Failed to assign registry module on token admin registry", "err", err) + e.Logger.Errorw("Failed to assign registry module on token admin registry", "chain", chain.String(), "err", err) return fmt.Errorf("failed to assign registry module on token admin registry: %w", err) } _, err = chain.Confirm(tx) if err != nil { - e.Logger.Errorw("Failed to confirm assign registry module on token admin registry", "err", err) + e.Logger.Errorw("Failed to confirm assign registry module on token admin registry", "chain", chain.String(), "err", err) return fmt.Errorf("failed to confirm assign registry module on token admin registry: %w", err) } e.Logger.Infow("assigned registry module on token admin registry") @@ -245,10 +241,9 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } }) if err != nil { - lggr.Errorw("Failed to deploy weth9", "err", err) + lggr.Errorw("Failed to deploy weth9", "chain", chain.String(), "err", err) return err } - lggr.Infow("deployed weth9", "addr", weth.Address) weth9Contract = weth.Contract } else { lggr.Infow("weth9 already deployed", "addr", weth9Contract.Address) @@ -268,16 +263,16 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } }) if err != nil { - e.Logger.Errorw("Failed to deploy router", "err", err) + e.Logger.Errorw("Failed to deploy router", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("deployed router", "addr", routerContract.Address) + r = routerContract.Contract } else { - e.Logger.Infow("router already deployed", "addr", chainState.Router.Address) + e.Logger.Infow("router already deployed", "chain", chain.String(), "addr", chainState.Router.Address) } if deployOpts.Multicall3Enabled && mc3 == nil { - multicall3Contract, err := deployment.DeployContract(e.Logger, chain, ab, + _, err := deployment.DeployContract(e.Logger, chain, ab, func(chain deployment.Chain) deployment.ContractDeploy[*multicall3.Multicall3] { multicall3Addr, tx2, multicall3Wrapper, err2 := multicall3.DeployMulticall3( chain.DeployerKey, @@ -288,12 +283,13 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address } }) if err != nil { - e.Logger.Errorw("Failed to deploy ccip multicall", "err", err) + e.Logger.Errorw("Failed to deploy ccip multicall", "chain", chain.String(), "err", err) return err } - e.Logger.Infow("deployed ccip multicall", "addr", multicall3Contract.Address) } else { - e.Logger.Info("ccip multicall already deployed", "addr", mc3.Address) + if mc3 != nil { + e.Logger.Info("ccip multicall already deployed", "chain", chain.String(), "addr", mc3.Address) + } } if isUSDC { token, pool, messenger, transmitter, err1 := DeployUSDC(e.Logger, chain, ab, rmnProxy.Address(), r.Address()) @@ -301,7 +297,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab deployment.Address return err1 } e.Logger.Infow("Deployed USDC contracts", - "chainSelector", chain.Selector, + "chain", chain.String(), "token", token.Address(), "pool", pool.Address(), "transmitter", transmitter.Address(), diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go index 27052b04d07..6328c329b9a 100644 --- a/deployment/ccip/changeset/internal/deploy_home_chain.go +++ b/deployment/ccip/changeset/internal/deploy_home_chain.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" @@ -173,6 +174,7 @@ func BuildSetOCR3ConfigArgs( } func SetupExecDON( + lggr logger.Logger, donID uint32, execConfig ccip_home.CCIPHomeOCR3Config, capReg *capabilities_registry.CapabilitiesRegistry, @@ -212,6 +214,7 @@ func SetupExecDON( if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { return fmt.Errorf("confirm update don w/ exec config: %w", err) } + lggr.Infow("Updated DON with exec config", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "setCandidateCall", encodedSetCandidateCall) execCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, execConfig.PluginType) if err != nil { @@ -221,7 +224,7 @@ func SetupExecDON( if execCandidateDigest == [32]byte{} { return fmt.Errorf("candidate digest is empty, expected nonempty") } - + lggr.Infow("Got exec candidate digest", "chain", home.String(), "donID", donID, "execCandidateDigest", execCandidateDigest) // promote candidate call encodedPromotionCall, err := CCIPHomeABI.Pack( "promoteCandidateAndRevokeActive", @@ -257,6 +260,7 @@ func SetupExecDON( if bn == 0 { return fmt.Errorf("UpdateDON tx not confirmed") } + lggr.Infow("Promoted exec candidate", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "promotionCall", encodedPromotionCall) // check if candidate digest is promoted pEvent, err := ccipHome.FilterConfigPromoted(&bind.FilterOpts{ Context: context.Background(), @@ -293,14 +297,20 @@ func SetupExecDON( return fmt.Errorf("get all exec configs 2nd time: %w", err) } - // print the above info - fmt.Printf("completed exec DON creation and promotion: donID: %d execCandidateDigest: %x, execActiveDigest: %x, execCandidateDigestFromGetAllConfigs: %x, execActiveDigestFromGetAllConfigs: %x\n", - donID, execCandidateDigest, execActiveDigest, execConfigs.CandidateConfig.ConfigDigest, execConfigs.ActiveConfig.ConfigDigest) + // log the above info + lggr.Infow("completed exec DON creation and promotion", + "donID", donID, + "execCandidateDigest", execCandidateDigest, + "execActiveDigest", execActiveDigest, + "execCandidateDigestFromGetAllConfigs", execConfigs.CandidateConfig.ConfigDigest, + "execActiveDigestFromGetAllConfigs", execConfigs.ActiveConfig.ConfigDigest, + ) return nil } func SetupCommitDON( + lggr logger.Logger, donID uint32, commitConfig ccip_home.CCIPHomeOCR3Config, capReg *capabilities_registry.CapabilitiesRegistry, @@ -331,7 +341,7 @@ func SetupCommitDON( if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { return fmt.Errorf("confirm add don w/ commit config: %w", err) } - + lggr.Debugw("Added DON with commit config", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "setCandidateCall", encodedSetCandidateCall) commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) if err != nil { return fmt.Errorf("get commit candidate digest: %w", err) @@ -340,7 +350,7 @@ func SetupCommitDON( if commitCandidateDigest == [32]byte{} { return fmt.Errorf("candidate digest is empty, expected nonempty") } - fmt.Printf("commit candidate digest after setCandidate: %x\n", commitCandidateDigest) + lggr.Debugw("Got commit candidate digest", "chain", home.String(), "donID", donID, "commitCandidateDigest", commitCandidateDigest) encodedPromotionCall, err := CCIPHomeABI.Pack( "promoteCandidateAndRevokeActive", @@ -373,6 +383,7 @@ func SetupCommitDON( if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { return fmt.Errorf("confirm update don w/ commit config: %w", err) } + lggr.Debugw("Promoted commit candidate", "chain", home.String(), "donID", donID, "txHash", tx.Hash().Hex(), "promotionCall", encodedPromotionCall) // check that candidate digest is empty. commitCandidateDigest, err = ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) @@ -399,9 +410,14 @@ func SetupCommitDON( return fmt.Errorf("get all commit configs 2nd time: %w", err) } - // print the above information - fmt.Printf("completed commit DON creation and promotion: donID: %d, commitCandidateDigest: %x, commitActiveDigest: %x, commitCandidateDigestFromGetAllConfigs: %x, commitActiveDigestFromGetAllConfigs: %x\n", - donID, commitCandidateDigest, commitActiveDigest, commitConfigs.CandidateConfig.ConfigDigest, commitConfigs.ActiveConfig.ConfigDigest) + // log the above information + lggr.Infow("completed commit DON creation and promotion", + "donID", donID, + "commitCandidateDigest", commitCandidateDigest, + "commitActiveDigest", commitActiveDigest, + "commitCandidateDigestFromGetAllConfigs", commitConfigs.CandidateConfig.ConfigDigest, + "commitActiveDigestFromGetAllConfigs", commitConfigs.ActiveConfig.ConfigDigest, + ) return nil } diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go index 20763523141..0820f42d0c7 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/changeset/state.go @@ -13,7 +13,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/view" @@ -134,35 +133,35 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if c.Router != nil { routerView, err := v1_2.GenerateRouterView(c.Router) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate router view for router %s", c.Router.Address().String()) } chainView.Router[c.Router.Address().Hex()] = routerView } if c.TokenAdminRegistry != nil { taView, err := v1_5.GenerateTokenAdminRegistryView(c.TokenAdminRegistry) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate token admin registry view for token admin registry %s", c.TokenAdminRegistry.Address().String()) } chainView.TokenAdminRegistry[c.TokenAdminRegistry.Address().Hex()] = taView } if c.NonceManager != nil { nmView, err := v1_6.GenerateNonceManagerView(c.NonceManager) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate nonce manager view for nonce manager %s", c.NonceManager.Address().String()) } chainView.NonceManager[c.NonceManager.Address().Hex()] = nmView } if c.RMNRemote != nil { rmnView, err := v1_6.GenerateRMNRemoteView(c.RMNRemote) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate rmn remote view for rmn remote %s", c.RMNRemote.Address().String()) } chainView.RMN[c.RMNRemote.Address().Hex()] = rmnView } if c.FeeQuoter != nil && c.Router != nil && c.TokenAdminRegistry != nil { fqView, err := v1_6.GenerateFeeQuoterView(c.FeeQuoter, c.Router, c.TokenAdminRegistry) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate fee quoter view for fee quoter %s", c.FeeQuoter.Address().String()) } chainView.FeeQuoter[c.FeeQuoter.Address().Hex()] = fqView } @@ -174,7 +173,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { c.TokenAdminRegistry, ) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate on ramp view for on ramp %s", c.OnRamp.Address().String()) } chainView.OnRamp[c.OnRamp.Address().Hex()] = onRampView } @@ -185,7 +184,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { c.Router, ) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate off ramp view for off ramp %s", c.OffRamp.Address().String()) } chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView } @@ -193,7 +192,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if c.CommitStore != nil { commitStoreView, err := v1_5.GenerateCommitStoreView(c.CommitStore) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate commit store view for commit store %s", c.CommitStore.Address().String()) } chainView.CommitStore[c.CommitStore.Address().Hex()] = commitStoreView } @@ -201,28 +200,28 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if c.RMNProxyNew != nil { rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxyNew) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate rmn proxy view for rmn proxy %s", c.RMNProxyNew.Address().String()) } chainView.RMNProxy[c.RMNProxyNew.Address().Hex()] = rmnProxyView } if c.CapabilityRegistry != nil { capRegView, err := common_v1_0.GenerateCapabilityRegistryView(c.CapabilityRegistry) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate capability registry view for capability registry %s", c.CapabilityRegistry.Address().String()) } chainView.CapabilityRegistry[c.CapabilityRegistry.Address().Hex()] = capRegView } if c.MCMSWithTimelockState.Timelock != nil { mcmsView, err := c.MCMSWithTimelockState.GenerateMCMSWithTimelockView() if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate MCMS with timelock view for MCMS with timelock %s", c.MCMSWithTimelockState.Timelock.Address().String()) } chainView.MCMSWithTimelock = mcmsView } if c.LinkToken != nil { linkTokenView, err := common_v1_0.GenerateLinkTokenView(c.LinkToken) if err != nil { - return chainView, err + return chainView, errors.Wrapf(err, "failed to generate link token view for link token %s", c.LinkToken.Address().String()) } chainView.LinkToken = linkTokenView } @@ -242,12 +241,7 @@ type CCIPOnChainState struct { func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, error) { m := make(map[string]view.ChainView) for _, chainSelector := range chains { - // TODO: Need a utility for this - chainid, err := chainsel.ChainIdFromSelector(chainSelector) - if err != nil { - return m, err - } - chainName, err := chainsel.NameFromChainId(chainid) + chainInfo, err := deployment.ChainInfo(chainSelector) if err != nil { return m, err } @@ -259,7 +253,7 @@ func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, erro if err != nil { return m, err } - m[chainName] = chainView + m[chainInfo.ChainName] = chainView } return m, nil } diff --git a/deployment/ccip/changeset/test_usdc_helpers.go b/deployment/ccip/changeset/test_usdc_helpers.go index 75994ec9356..55f1bd25a36 100644 --- a/deployment/ccip/changeset/test_usdc_helpers.go +++ b/deployment/ccip/changeset/test_usdc_helpers.go @@ -175,13 +175,13 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token", "err", err) + lggr.Errorw("Failed to deploy USDC token", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } tx, err := token.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) if err != nil { - lggr.Errorw("Failed to grant mint role", "token", token.Contract.Address(), "err", err) + lggr.Errorw("Failed to grant mint role", "chain", chain.String(), "token", token.Contract.Address(), "err", err) return nil, nil, nil, nil, err } _, err = chain.Confirm(tx) @@ -207,12 +207,10 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy mock USDC transmitter", "err", err) + lggr.Errorw("Failed to deploy mock USDC transmitter", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } - lggr.Infow("deployed mock USDC transmitter", "addr", transmitter.Address) - messenger, err := deployment.DeployContract(lggr, chain, addresses, func(chain deployment.Chain) deployment.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { messengerAddress, tx, messengerContract, err2 := mock_usdc_token_messenger.DeployMockE2EUSDCTokenMessenger( @@ -230,10 +228,9 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token messenger", "err", err) + lggr.Errorw("Failed to deploy USDC token messenger", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } - lggr.Infow("deployed mock USDC token messenger", "addr", messenger.Address) tokenPool, err := deployment.DeployContract(lggr, chain, addresses, func(chain deployment.Chain) deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool] { @@ -255,10 +252,9 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token pool", "err", err) + lggr.Errorw("Failed to deploy USDC token pool", "chain", chain.String(), "err", err) return nil, nil, nil, nil, err } - lggr.Infow("deployed USDC token pool", "addr", tokenPool.Address) return token.Contract, tokenPool.Contract, messenger.Contract, transmitter.Contract, nil } diff --git a/deployment/common/changeset/deploy_link_token.go b/deployment/common/changeset/deploy_link_token.go index 5728e977c47..292c07c93df 100644 --- a/deployment/common/changeset/deploy_link_token.go +++ b/deployment/common/changeset/deploy_link_token.go @@ -52,7 +52,7 @@ func deployLinkTokenContract( } }) if err != nil { - lggr.Errorw("Failed to deploy link token", "err", err) + lggr.Errorw("Failed to deploy link token", "chain", chain.String(), "err", err) return linkToken, err } return linkToken, nil diff --git a/deployment/common/changeset/internal/mcms.go b/deployment/common/changeset/internal/mcms.go index 5694f83786b..281f43924f4 100644 --- a/deployment/common/changeset/internal/mcms.go +++ b/deployment/common/changeset/internal/mcms.go @@ -6,6 +6,7 @@ import ( owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" @@ -30,7 +31,7 @@ func DeployMCMSWithConfig( } }) if err != nil { - lggr.Errorw("Failed to deploy mcm", "err", err) + lggr.Errorw("Failed to deploy mcm", "chain", chain.String(), "err", err) return mcm, err } mcmsTx, err := mcm.Contract.SetConfig(chain.DeployerKey, @@ -42,7 +43,7 @@ func DeployMCMSWithConfig( false, ) if _, err := deployment.ConfirmIfNoError(chain, mcmsTx, err); err != nil { - lggr.Errorw("Failed to confirm mcm config", "err", err) + lggr.Errorw("Failed to confirm mcm config", "chain", chain.String(), "err", err) return mcm, err } return mcm, nil @@ -115,15 +116,14 @@ func DeployMCMSWithTimelockContracts( } }) if err != nil { - lggr.Errorw("Failed to deploy timelock", "err", err) + lggr.Errorw("Failed to deploy timelock", "chain", chain.String(), "err", err) return nil, err } - lggr.Infow("deployed timelock", "addr", timelock.Address) // We grant the timelock the admin role on the MCMS contracts. tx, err := timelock.Contract.GrantRole(chain.DeployerKey, v1_0.ADMIN_ROLE.ID, timelock.Address) if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to grant timelock admin role", "err", err) + lggr.Errorw("Failed to grant timelock admin role", "chain", chain.String(), "err", err) return nil, err } // After the proposer cycle is validated, diff --git a/deployment/common/view/nops.go b/deployment/common/view/nops.go index 7d705f694d3..61e16d59145 100644 --- a/deployment/common/view/nops.go +++ b/deployment/common/view/nops.go @@ -4,7 +4,9 @@ import ( "context" "fmt" + "github.com/pkg/errors" nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/deployment" ) @@ -39,7 +41,7 @@ func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (map[strin // get node info nodeDetails, err := oc.GetNode(context.Background(), &nodev1.GetNodeRequest{Id: node.NodeID}) if err != nil { - return nv, err + return nv, errors.Wrapf(err, "failed to get node details from offchain client for node %s", node.NodeID) } if nodeDetails == nil || nodeDetails.Node == nil { return nv, fmt.Errorf("failed to get node details from offchain client for node %s", node.NodeID) diff --git a/deployment/common/view/types/contract_state.go b/deployment/common/view/types/contract_state.go index f65c510af53..9b63d1f4db0 100644 --- a/deployment/common/view/types/contract_state.go +++ b/deployment/common/view/types/contract_state.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) @@ -14,11 +16,11 @@ type ContractMetaData struct { func NewContractMetaData(tv Meta, addr common.Address) (ContractMetaData, error) { tvStr, err := tv.TypeAndVersion(nil) if err != nil { - return ContractMetaData{}, err + return ContractMetaData{}, fmt.Errorf("failed to get type and version addr %s: %w", addr.String(), err) } owner, err := tv.Owner(nil) if err != nil { - return ContractMetaData{}, err + return ContractMetaData{}, fmt.Errorf("failed to get owner addr %s: %w", addr.String(), err) } return ContractMetaData{ TypeAndVersion: tvStr, diff --git a/deployment/common/view/v1_0/link_token.go b/deployment/common/view/v1_0/link_token.go index 38649037592..19b1b43aa02 100644 --- a/deployment/common/view/v1_0/link_token.go +++ b/deployment/common/view/v1_0/link_token.go @@ -1,6 +1,7 @@ package v1_0 import ( + "fmt" "math/big" "github.com/smartcontractkit/chainlink/deployment" @@ -18,15 +19,15 @@ type LinkTokenView struct { func GenerateLinkTokenView(lt *link_token.LinkToken) (LinkTokenView, error) { owner, err := lt.Owner(nil) if err != nil { - return LinkTokenView{}, err + return LinkTokenView{}, fmt.Errorf("view error to get link token owner addr %s: %w", lt.Address().String(), err) } decimals, err := lt.Decimals(nil) if err != nil { - return LinkTokenView{}, err + return LinkTokenView{}, fmt.Errorf("view error to get link token decimals addr %s: %w", lt.Address().String(), err) } totalSupply, err := lt.TotalSupply(nil) if err != nil { - return LinkTokenView{}, err + return LinkTokenView{}, fmt.Errorf("view error to get link token total supply addr %s: %w", lt.Address().String(), err) } return LinkTokenView{ ContractMetaData: types.ContractMetaData{ diff --git a/deployment/environment.go b/deployment/environment.go index 2de16a32cab..b4ac3a4f3f0 100644 --- a/deployment/environment.go +++ b/deployment/environment.go @@ -59,6 +59,24 @@ type Chain struct { Users []*bind.TransactOpts } +func (c Chain) String() string { + chainInfo, err := ChainInfo(c.Selector) + if err != nil { + // we should never get here, if the selector is invalid it should not be in the environment + panic(err) + } + return fmt.Sprintf("%s (%d)", chainInfo.ChainName, chainInfo.ChainSelector) +} + +func (c Chain) Name() string { + chainInfo, err := ChainInfo(c.Selector) + if err != nil { + // we should never get here, if the selector is invalid it should not be in the environment + panic(err) + } + return chainInfo.ChainName +} + // Environment represents an instance of a deployed product // including on and offchain components. It is intended to be // cross-family to enable a coherent view of a product deployed @@ -147,7 +165,7 @@ func ConfirmIfNoError(chain Chain, tx *types.Transaction, err error) (uint64, er var d rpc.DataError ok := errors.As(err, &d) if ok { - return 0, fmt.Errorf("transaction reverted: Error %s ErrorData %v", d.Error(), d.ErrorData()) + return 0, fmt.Errorf("transaction reverted on chain %s: Error %s ErrorData %v", chain.String(), d.Error(), d.ErrorData()) } return 0, err } diff --git a/deployment/environment/clo/models/models_gen.go b/deployment/environment/clo/models/models_gen.go index baea1dbcbed..8d8f57c3b56 100644 --- a/deployment/environment/clo/models/models_gen.go +++ b/deployment/environment/clo/models/models_gen.go @@ -58,7 +58,7 @@ type AddAggregatorInput struct { type AddChainInput struct { NetworkID string `json:"networkID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } @@ -102,7 +102,7 @@ type AddLaneInput struct { ChainAid string `json:"chainAID,omitempty"` ChainBid string `json:"chainBID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } @@ -353,7 +353,7 @@ type CCIPChain struct { FeeTokens []string `json:"feeTokens,omitempty"` WrappedNativeToken string `json:"wrappedNativeToken,omitempty"` ArchivedAt *Time `json:"archivedAt,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` DeployedTemplate map[string]interface{} `json:"deployedTemplate,omitempty"` Labels map[string]interface{} `json:"labels,omitempty"` @@ -1001,7 +1001,7 @@ type ImportAggregatorInput struct { type ImportChainInput struct { NetworkID string `json:"networkID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } @@ -1047,7 +1047,7 @@ type ImportLaneInput struct { ChainAid string `json:"chainAID,omitempty"` ChainBid string `json:"chainBID,omitempty"` Template string `json:"template,omitempty"` - // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + // The Display String lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. DisplayName *string `json:"displayName,omitempty"` } diff --git a/deployment/environment/devenv/chain.go b/deployment/environment/devenv/chain.go index 407b898cb04..5c6c4336ed7 100644 --- a/deployment/environment/devenv/chain.go +++ b/deployment/environment/devenv/chain.go @@ -108,6 +108,10 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme if ec == nil { return nil, fmt.Errorf("failed to connect to chain %s", chainCfg.ChainName) } + chainInfo, err := deployment.ChainInfo(selector) + if err != nil { + return nil, fmt.Errorf("failed to get chain info for chain %s: %w", chainCfg.ChainName, err) + } chains[selector] = deployment.Chain{ Selector: selector, Client: ec, @@ -115,28 +119,24 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme Confirm: func(tx *types.Transaction) (uint64, error) { var blockNumber uint64 if tx == nil { - return 0, fmt.Errorf("tx was nil, nothing to confirm") + return 0, fmt.Errorf("tx was nil, nothing to confirm chain %s", chainInfo.ChainName) } ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) defer cancel() - chainId, err := ec.ChainID(ctx) - if err != nil { - return blockNumber, fmt.Errorf("failed to get chain id: %w", err) - } receipt, err := bind.WaitMined(ctx, ec, tx) if err != nil { - return blockNumber, fmt.Errorf("failed to get confirmed receipt for chain %d: %w", chainId, err) + return blockNumber, fmt.Errorf("failed to get confirmed receipt for chain %s: %w", chainInfo.ChainName, err) } if receipt == nil { - return blockNumber, fmt.Errorf("receipt was nil for tx %s", tx.Hash().Hex()) + return blockNumber, fmt.Errorf("receipt was nil for tx %s chain %s", tx.Hash().Hex(), chainInfo.ChainName) } blockNumber = receipt.BlockNumber.Uint64() if receipt.Status == 0 { errReason, err := deployment.GetErrorReasonFromTx(ec, chainCfg.DeployerKey.From, tx, receipt) if err == nil && errReason != "" { - return blockNumber, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) + return blockNumber, fmt.Errorf("tx %s reverted,error reason: %s chain %s", tx.Hash().Hex(), errReason, chainInfo.ChainName) } - return blockNumber, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) + return blockNumber, fmt.Errorf("tx %s reverted, could not decode error reason chain %s", tx.Hash().Hex(), chainInfo.ChainName) } return blockNumber, nil }, diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index e8f0c265101..1693834c572 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -3,6 +3,7 @@ package memory import ( "context" "fmt" + "strconv" "testing" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -66,30 +67,30 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de chains := make(map[uint64]deployment.Chain) for cid, chain := range inputs { chain := chain - sel, err := chainsel.SelectorFromChainId(cid) + chainInfo, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.FormatUint(cid, 10), chainsel.FamilyEVM) require.NoError(t, err) backend := NewBackend(chain.Backend) - chains[sel] = deployment.Chain{ - Selector: sel, + chains[chainInfo.ChainSelector] = deployment.Chain{ + Selector: chainInfo.ChainSelector, Client: backend, DeployerKey: chain.DeployerKey, Confirm: func(tx *types.Transaction) (uint64, error) { if tx == nil { - return 0, fmt.Errorf("tx was nil, nothing to confirm") + return 0, fmt.Errorf("tx was nil, nothing to confirm, chain %s", chainInfo.ChainName) } for { backend.Commit() receipt, err := backend.TransactionReceipt(context.Background(), tx.Hash()) if err != nil { - t.Log("failed to get receipt", err) + t.Log("failed to get receipt", "chain", chainInfo.ChainName, err) continue } if receipt.Status == 0 { errReason, err := deployment.GetErrorReasonFromTx(chain.Backend.Client(), chain.DeployerKey.From, tx, receipt) if err == nil && errReason != "" { - return 0, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) + return 0, fmt.Errorf("tx %s reverted,error reason: %s chain %s", tx.Hash().Hex(), errReason, chainInfo.ChainName) } - return 0, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) + return 0, fmt.Errorf("tx %s reverted, could not decode error reason chain %s", tx.Hash().Hex(), chainInfo.ChainName) } return receipt.BlockNumber.Uint64(), nil } diff --git a/deployment/helpers.go b/deployment/helpers.go index e8d2d8c8d59..50f4c404b09 100644 --- a/deployment/helpers.go +++ b/deployment/helpers.go @@ -138,17 +138,18 @@ func DeployContract[C any]( ) (*ContractDeploy[C], error) { contractDeploy := deploy(chain) if contractDeploy.Err != nil { - lggr.Errorw("Failed to deploy contract", "err", contractDeploy.Err) + lggr.Errorw("Failed to deploy contract", "chain", chain.String(), "err", contractDeploy.Err) return nil, contractDeploy.Err } _, err := chain.Confirm(contractDeploy.Tx) if err != nil { - lggr.Errorw("Failed to confirm deployment", "err", err) + lggr.Errorw("Failed to confirm deployment", "chain", chain.String(), "Contract", contractDeploy.Tv.String(), "err", err) return nil, err } + lggr.Infow("Deployed contract", "Contract", contractDeploy.Tv.String(), "addr", contractDeploy.Address, "chain", chain.Selector) err = addressBook.Save(chain.Selector, contractDeploy.Address.String(), contractDeploy.Tv) if err != nil { - lggr.Errorw("Failed to save contract address", "err", err) + lggr.Errorw("Failed to save contract address", "Contract", contractDeploy.Tv.String(), "addr", contractDeploy.Address, "chain", chain.String(), "err", err) return nil, err } return &contractDeploy, nil @@ -158,9 +159,25 @@ func IsValidChainSelector(cs uint64) error { if cs == 0 { return fmt.Errorf("chain selector must be set") } - _, err := chain_selectors.ChainIdFromSelector(cs) + _, err := chain_selectors.GetSelectorFamily(cs) if err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) + return err } return nil } + +func ChainInfo(cs uint64) (chain_selectors.ChainDetails, error) { + id, err := chain_selectors.GetChainIDFromSelector(cs) + if err != nil { + return chain_selectors.ChainDetails{}, err + } + family, err := chain_selectors.GetSelectorFamily(cs) + if err != nil { + return chain_selectors.ChainDetails{}, err + } + info, err := chain_selectors.GetChainDetailsByChainIDAndFamily(id, family) + if err != nil { + return chain_selectors.ChainDetails{}, err + } + return info, nil +} diff --git a/deployment/keystone/ocr3config_test.go b/deployment/keystone/ocr3config_test.go index 4046787724a..daf869d77e0 100644 --- a/deployment/keystone/ocr3config_test.go +++ b/deployment/keystone/ocr3config_test.go @@ -11,13 +11,14 @@ import ( "github.com/ethereum/go-ethereum/common" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/view" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" types2 "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" types3 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/test-go/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/view" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) var wantOCR3Config = `{ @@ -83,7 +84,6 @@ func Test_configureOCR3Request_generateOCR3Config(t *testing.T) { var cfg OracleConfig err := json.Unmarshal([]byte(ocr3Cfg), &cfg) require.NoError(t, err) - r := configureOCR3Request{ cfg: &OracleConfigWithSecrets{OracleConfig: cfg, OCRSecrets: deployment.XXXGenerateTestOCRSecrets()}, nodes: nodes, diff --git a/deployment/multiclient.go b/deployment/multiclient.go index dcda07ebb0b..914c1fbd9e3 100644 --- a/deployment/multiclient.go +++ b/deployment/multiclient.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/pkg/errors" + chainselectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -46,6 +47,7 @@ type MultiClient struct { Backups []*ethclient.Client RetryConfig RetryConfig lggr logger.Logger + chainName string } func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiClient)) (*MultiClient, error) { @@ -59,6 +61,17 @@ func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiCl if err != nil { return nil, fmt.Errorf("failed to dial ws url '%s': %w", rpc.WSURL, err) } + // fetch chain name if not set + if mc.chainName == "" { + id, err := client.ChainID(context.Background()) + if err == nil { + details, err := chainselectors.GetChainDetailsByChainIDAndFamily(id.String(), chainselectors.FamilyEVM) + if err == nil { + return nil, err + } + mc.chainName = details.ChainName + } + } clients = append(clients, client) } mc.Client = clients[0] @@ -134,11 +147,12 @@ func (mc *MultiClient) WaitMined(ctx context.Context, tx *types.Transaction) (*t func (mc *MultiClient) retryWithBackups(opName string, op func(*ethclient.Client) error) error { var err error - for _, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { + for i, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { err2 := retry.Do(func() error { + mc.lggr.Debugf("Trying op %s with chain %s client index %d", opName, mc.chainName, i) err = op(client) if err != nil { - mc.lggr.Warnf("retryable error '%s' for op %s with client %v", err.Error(), opName, client) + mc.lggr.Warnf("retryable error '%s' for op %s with chain %s client index %d", err.Error(), opName, mc.chainName, i) return err } return nil @@ -146,7 +160,7 @@ func (mc *MultiClient) retryWithBackups(opName string, op func(*ethclient.Client if err2 == nil { return nil } - mc.lggr.Infof("Client %v failed, trying next client", client) + mc.lggr.Infof("Client at index %d failed, trying next client chain %s", i, mc.chainName) } - return errors.Wrapf(err, "All backup clients %v failed", mc.Backups) + return errors.Wrapf(err, "All backup clients %v failed for chain %s", mc.Backups, mc.chainName) } From 4b738abd19b7765fe7fe0beeb4072b21a640c2a4 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:25:09 -0700 Subject: [PATCH 32/55] support mcms in forwarder contract config changeset (#15533) * support mcms in ocr3 contract config changeset * test working for ocr3 config with mcms * migrate deployment test to setup test env * fix test * refactor forwarder configuration changeset for mcms --- .../keystone/changeset/deploy_forwarder.go | 42 +++++- .../changeset/deploy_forwarder_test.go | 90 +++++++++++ deployment/keystone/changeset/helpers_test.go | 74 ++++----- deployment/keystone/deploy.go | 140 +++++++++--------- deployment/keystone/deploy_test.go | 5 +- deployment/keystone/forwarder_deployer.go | 41 +++++ deployment/keystone/types.go | 46 +++++- 7 files changed, 326 insertions(+), 112 deletions(-) diff --git a/deployment/keystone/changeset/deploy_forwarder.go b/deployment/keystone/changeset/deploy_forwarder.go index 5207d99aacd..cf116decd54 100644 --- a/deployment/keystone/changeset/deploy_forwarder.go +++ b/deployment/keystone/changeset/deploy_forwarder.go @@ -11,7 +11,8 @@ var _ deployment.ChangeSet[uint64] = DeployForwarder // DeployForwarder deploys the KeystoneForwarder contract to all chains in the environment // callers must merge the output addressbook with the existing one -func DeployForwarder(env deployment.Environment, registryChainSel uint64) (deployment.ChangesetOutput, error) { +// TODO: add selectors to deploy only to specific chains +func DeployForwarder(env deployment.Environment, _ uint64) (deployment.ChangesetOutput, error) { lggr := env.Logger ab := deployment.NewMemoryAddressBook() for _, chain := range env.Chains { @@ -25,3 +26,42 @@ func DeployForwarder(env deployment.Environment, registryChainSel uint64) (deplo return deployment.ChangesetOutput{AddressBook: ab}, nil } + +var _ deployment.ChangeSet[ConfigureForwardContractsRequest] = ConfigureForwardContracts + +type ConfigureForwardContractsRequest struct { + WFDonName string + // workflow don node ids in the offchain client. Used to fetch and derive the signer keys + WFNodeIDs []string + RegistryChainSel uint64 + + UseMCMS bool +} + +func (r ConfigureForwardContractsRequest) Validate() error { + if len(r.WFNodeIDs) == 0 { + return fmt.Errorf("WFNodeIDs must not be empty") + } + return nil +} + +func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardContractsRequest) (deployment.ChangesetOutput, error) { + wfDon, err := kslib.NewRegisteredDon(env, kslib.RegisteredDonConfig{ + NodeIDs: req.WFNodeIDs, + Name: req.WFDonName, + RegistryChainSel: req.RegistryChainSel, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create registered don: %w", err) + } + r, err := kslib.ConfigureForwardContracts(&env, kslib.ConfigureForwarderContractsRequest{ + Dons: []kslib.RegisteredDon{*wfDon}, + UseMCMS: req.UseMCMS, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure forward contracts: %w", err) + } + return deployment.ChangesetOutput{ + Proposals: r.Proposals, + }, nil +} diff --git a/deployment/keystone/changeset/deploy_forwarder_test.go b/deployment/keystone/changeset/deploy_forwarder_test.go index b6d8ec8f753..32a53f1cf08 100644 --- a/deployment/keystone/changeset/deploy_forwarder_test.go +++ b/deployment/keystone/changeset/deploy_forwarder_test.go @@ -1,14 +1,17 @@ package changeset_test import ( + "fmt" "testing" "go.uber.org/zap/zapcore" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -45,3 +48,90 @@ func TestDeployForwarder(t *testing.T) { require.Len(t, oaddrs, 1) }) } + +func TestConfigureForwarders(t *testing.T) { + t.Parallel() + + t.Run("no mcms ", func(t *testing.T) { + for _, nChains := range []int{1, 3} { + name := fmt.Sprintf("nChains=%d", nChains) + t.Run(name, func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: nChains, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + cfg := changeset.ConfigureForwardContractsRequest{ + WFDonName: "test-wf-don", + WFNodeIDs: wfNodes, + RegistryChainSel: te.RegistrySelector, + } + csOut, err := changeset.ConfigureForwardContracts(te.Env, cfg) + require.NoError(t, err) + require.Nil(t, csOut.AddressBook) + require.Len(t, csOut.Proposals, 0) + // check that forwarder + // TODO set up a listener to check that the forwarder is configured + contractSet := te.ContractSets() + for selector := range te.Env.Chains { + cs, ok := contractSet[selector] + require.True(t, ok) + require.NotNil(t, cs.Forwarder) + } + }) + } + }) + + t.Run("with mcms", func(t *testing.T) { + for _, nChains := range []int{1, 3} { + name := fmt.Sprintf("nChains=%d", nChains) + t.Run(name, func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: nChains, + UseMCMS: true, + }) + + var wfNodes []string + for id, _ := range te.WFNodes { + wfNodes = append(wfNodes, id) + } + + cfg := changeset.ConfigureForwardContractsRequest{ + WFDonName: "test-wf-don", + WFNodeIDs: wfNodes, + RegistryChainSel: te.RegistrySelector, + UseMCMS: true, + } + csOut, err := changeset.ConfigureForwardContracts(te.Env, cfg) + require.NoError(t, err) + require.Len(t, csOut.Proposals, nChains) + require.Nil(t, csOut.AddressBook) + + timelocks := make(map[uint64]*gethwrappers.RBACTimelock) + for selector, contractSet := range te.ContractSets() { + require.NotNil(t, contractSet.Timelock) + timelocks[selector] = contractSet.Timelock + } + _, err = commonchangeset.ApplyChangesets(t, te.Env, timelocks, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureForwardContracts), + Config: cfg, + }, + }) + require.NoError(t, err) + + }) + } + }) + +} diff --git a/deployment/keystone/changeset/helpers_test.go b/deployment/keystone/changeset/helpers_test.go index 85e69507009..d4435d8f7a6 100644 --- a/deployment/keystone/changeset/helpers_test.go +++ b/deployment/keystone/changeset/helpers_test.go @@ -96,6 +96,7 @@ func (c TestConfig) Validate() error { } type TestEnv struct { + t *testing.T Env deployment.Environment RegistrySelector uint64 @@ -104,6 +105,15 @@ type TestEnv struct { AssetNodes map[string]memory.Node } +func (te TestEnv) ContractSets() map[uint64]kslib.ContractSet { + r, err := kslib.GetContractSets(te.Env.Logger, &kslib.GetContractSetsRequest{ + Chains: te.Env.Chains, + AddressBook: te.Env.ExistingAddresses, + }) + require.NoError(te.t, err) + return r.ContractSets +} + // SetupTestEnv sets up a keystone test environment with the given configuration func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { require.NoError(t, c.Validate()) @@ -250,57 +260,51 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { if c.UseMCMS { // TODO: mcms on all the chains, currently only on the registry chain. need to fix this for forwarders - t.Logf("Enabling MCMS registry chain %d", registryChainSel) // deploy, configure and xfer ownership of MCMS + timelockCfgs := make(map[uint64]commontypes.MCMSWithTimelockConfig) + for sel := range env.Chains { + t.Logf("Enabling MCMS on chain %d", sel) + timelockCfgs[sel] = commontypes.MCMSWithTimelockConfig{ + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + } + } env, err = commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ { Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: map[uint64]commontypes.MCMSWithTimelockConfig{ - registryChainSel: { - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), - }, - }, + Config: timelockCfgs, }, }) require.NoError(t, err) // extract the MCMS address r, err := kslib.GetContractSets(lggr, &kslib.GetContractSetsRequest{ - Chains: map[uint64]deployment.Chain{ - registryChainSel: env.Chains[registryChainSel], - }, + Chains: env.Chains, AddressBook: env.ExistingAddresses, }) require.NoError(t, err) - mcms := r.ContractSets[registryChainSel].MCMSWithTimelockState - require.NotNil(t, mcms) - // transfer ownership of all contracts to the MCMS - env, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*gethwrappers.RBACTimelock{registryChainSel: mcms.Timelock}, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(kschangeset.AcceptAllOwnershipsProposal), - Config: &kschangeset.AcceptAllOwnershipRequest{ - ChainSelector: registryChainSel, - MinDelay: 0, + for sel := range env.Chains { + mcms := r.ContractSets[sel].MCMSWithTimelockState + require.NotNil(t, mcms, "MCMS not found on chain %d", sel) + require.NoError(t, mcms.Validate()) + + // transfer ownership of all contracts to the MCMS + env, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*gethwrappers.RBACTimelock{sel: mcms.Timelock}, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(kschangeset.AcceptAllOwnershipsProposal), + Config: &kschangeset.AcceptAllOwnershipRequest{ + ChainSelector: sel, + MinDelay: 0, + }, }, - }, - }) - require.NoError(t, err) - // ensure the MCMS is deployed - req = &keystone.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, + }) + require.NoError(t, err) } - contractSetsResp, err = keystone.GetContractSets(lggr, req) - require.NoError(t, err) - require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) - // check the mcms contract on registry chain - gotMCMS := contractSetsResp.ContractSets[registryChainSel].MCMSWithTimelockState - require.NoError(t, gotMCMS.Validate()) } return TestEnv{ + t: t, Env: env, RegistrySelector: registryChainSel, WFNodes: wfNodes, diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index 0370cc54ba9..da277bc3497 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -7,18 +7,23 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" "sort" "strconv" "strings" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" "golang.org/x/exp/maps" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" @@ -77,22 +82,7 @@ func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureCo return nil, fmt.Errorf("invalid request: %w", err) } - addrBook := req.Env.ExistingAddresses - // TODO: KS-rm_deploy_opt remove this option; it's not used - if req.DoContractDeploy { - contractDeployCS, err := DeployContracts(req.Env, req.RegistryChainSel) - if err != nil { - return nil, fmt.Errorf("failed to deploy contracts: %w", err) - } - addrBook = contractDeployCS.AddressBook - } else { - lggr.Debug("skipping contract deployment") - } - if addrBook == nil { - return nil, errors.New("address book is nil") - } - - cfgRegistryResp, err := ConfigureRegistry(ctx, lggr, req, addrBook) + cfgRegistryResp, err := ConfigureRegistry(ctx, lggr, req, req.Env.ExistingAddresses) if err != nil { return nil, fmt.Errorf("failed to configure registry: %w", err) } @@ -107,21 +97,22 @@ func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureCo if err != nil { return nil, fmt.Errorf("failed to assimilate registry to Dons: %w", err) } - err = ConfigureForwardContracts(req.Env, dons, addrBook) + // ignore response because we are not using mcms here and therefore no proposals are returned + _, err = ConfigureForwardContracts(req.Env, ConfigureForwarderContractsRequest{ + Dons: dons, + }) if err != nil { return nil, fmt.Errorf("failed to configure forwarder contracts: %w", err) } - err = ConfigureOCR3Contract(req.Env, req.RegistryChainSel, dons, addrBook, req.OCR3Config) + err = ConfigureOCR3Contract(req.Env, req.RegistryChainSel, dons, req.OCR3Config) if err != nil { return nil, fmt.Errorf("failed to configure OCR3 contract: %w", err) } return &ConfigureContractsResponse{ - Changeset: &deployment.ChangesetOutput{ - AddressBook: addrBook, - }, - DonInfos: cfgRegistryResp.DonInfos, + Changeset: &deployment.ChangesetOutput{}, // no new addresses, proposals etc + DonInfos: cfgRegistryResp.DonInfos, }, nil } @@ -306,47 +297,14 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon lggr.Infow("registered DONs", "dons", len(donsResp.DonInfos)) return &ConfigureContractsResponse{ - Changeset: &deployment.ChangesetOutput{ - AddressBook: addrBook, - }, - DonInfos: donsResp.DonInfos, + Changeset: &deployment.ChangesetOutput{}, // no new addresses, proposals etc + DonInfos: donsResp.DonInfos, }, nil } -// ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS -// the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment -func ConfigureForwardContracts(env *deployment.Environment, dons []RegisteredDon, addrBook deployment.AddressBook) error { - contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: addrBook, - }) - if err != nil { - return fmt.Errorf("failed to get contract sets: %w", err) - } - - // configure forwarders on all chains - for _, chain := range env.Chains { - // get the forwarder contract for the chain - contracts, ok := contractSetsResp.ContractSets[chain.Selector] - if !ok { - return fmt.Errorf("failed to get contract set for chain %d", chain.Selector) - } - fwrd := contracts.Forwarder - if fwrd == nil { - return fmt.Errorf("no forwarder contract found for chain %d", chain.Selector) - } - - err := configureForwarder(env.Logger, chain, fwrd, dons) - if err != nil { - return fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err) - } - } - return nil -} - // Depreciated: use changeset.ConfigureOCR3Contract instead // ocr3 contract on the registry chain for the wf dons -func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, addrBook deployment.AddressBook, cfg *OracleConfigWithSecrets) error { +func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, cfg *OracleConfigWithSecrets) error { registryChain, ok := env.Chains[chainSel] if !ok { return fmt.Errorf("chain %d not found in environment", chainSel) @@ -354,7 +312,7 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ Chains: env.Chains, - AddressBook: addrBook, + AddressBook: env.ExistingAddresses, }) if err != nil { return fmt.Errorf("failed to get contract sets: %w", err) @@ -978,27 +936,67 @@ func containsAllDONs(donInfos []kcr.CapabilitiesRegistryDONInfo, p2pIdsToDon map // configureForwarder sets the config for the forwarder contract on the chain for all Dons that accept workflows // dons that don't accept workflows are not registered with the forwarder -func configureForwarder(lggr logger.Logger, chain deployment.Chain, fwdr *kf.KeystoneForwarder, dons []RegisteredDon) error { - if fwdr == nil { - return errors.New("nil forwarder contract") - } +func configureForwarder(lggr logger.Logger, chain deployment.Chain, contractSet ContractSet, dons []RegisteredDon, useMCMS bool) ([]timelock.MCMSWithTimelockProposal, error) { + if contractSet.Forwarder == nil { + return nil, errors.New("nil forwarder contract") + } + var ( + fwdr = contractSet.Forwarder + proposals []timelock.MCMSWithTimelockProposal + ) for _, dn := range dons { if !dn.Info.AcceptsWorkflows { continue } ver := dn.Info.ConfigCount // note config count on the don info is the version on the forwarder - signers := dn.signers(chainsel.FamilyEVM) - tx, err := fwdr.SetConfig(chain.DeployerKey, dn.Info.Id, ver, dn.Info.F, signers) - if err != nil { - err = DecodeErr(kf.KeystoneForwarderABI, err) - return fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) + signers := dn.Signers(chainsel.FamilyEVM) + txOpts := chain.DeployerKey + if useMCMS { + txOpts = deployment.SimTransactOpts() } - _, err = chain.Confirm(tx) + tx, err := fwdr.SetConfig(txOpts, dn.Info.Id, ver, dn.Info.F, signers) if err != nil { err = DecodeErr(kf.KeystoneForwarderABI, err) - return fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) + return nil, fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) + } + if !useMCMS { + _, err = chain.Confirm(tx) + if err != nil { + err = DecodeErr(kf.KeystoneForwarderABI, err) + return nil, fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) + } + } else { + // create the mcms proposals + ops := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chain.Selector), + Batch: []mcms.Operation{ + { + To: fwdr.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + } + timelocksPerChain := map[uint64]common.Address{ + chain.Selector: contractSet.Timelock.Address(), + } + proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ + chain.Selector: contractSet.ProposerMcm, + } + + proposal, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{ops}, + "proposal to set forward config", + 0, + ) + if err != nil { + return nil, fmt.Errorf("failed to build proposal: %w", err) + } + proposals = append(proposals, *proposal) } lggr.Debugw("configured forwarder", "forwarder", fwdr.Address().String(), "donId", dn.Info.Id, "version", ver, "f", dn.Info.F, "signers", signers) } - return nil + return proposals, nil } diff --git a/deployment/keystone/deploy_test.go b/deployment/keystone/deploy_test.go index fd59f3007fd..715f8b7aba7 100644 --- a/deployment/keystone/deploy_test.go +++ b/deployment/keystone/deploy_test.go @@ -142,10 +142,7 @@ func TestDeployCLO(t *testing.T) { } deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) require.NoError(t, err) - ad := deployResp.Changeset.AddressBook - addrs, err := ad.Addresses() - require.NoError(t, err) - lggr.Infow("Deployed Keystone contracts", "address book", addrs) + ad := env.ExistingAddresses // all contracts on home chain homeChainAddrs, err := ad.AddressesForChain(registryChainSel) diff --git a/deployment/keystone/forwarder_deployer.go b/deployment/keystone/forwarder_deployer.go index cf29b20c693..d7cfa7991f4 100644 --- a/deployment/keystone/forwarder_deployer.go +++ b/deployment/keystone/forwarder_deployer.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" @@ -56,3 +57,43 @@ func (c *KeystoneForwarderDeployer) deploy(req DeployRequest) (*DeployResponse, c.contract = forwarder return resp, nil } + +type ConfigureForwarderContractsRequest struct { + Dons []RegisteredDon + + UseMCMS bool +} +type ConfigureForwarderContractsResponse struct { + Proposals []timelock.MCMSWithTimelockProposal +} + +// Depreciated: use [changeset.ConfigureForwarders] instead +// ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS +// the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment +func ConfigureForwardContracts(env *deployment.Environment, req ConfigureForwarderContractsRequest) (*ConfigureForwarderContractsResponse, error) { + contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return nil, fmt.Errorf("failed to get contract sets: %w", err) + } + + var allProposals []timelock.MCMSWithTimelockProposal + // configure forwarders on all chains + for _, chain := range env.Chains { + // get the forwarder contract for the chain + contracts, ok := contractSetsResp.ContractSets[chain.Selector] + if !ok { + return nil, fmt.Errorf("failed to get contract set for chain %d", chain.Selector) + } + proposals, err := configureForwarder(env.Logger, chain, contracts, req.Dons, req.UseMCMS) + if err != nil { + return nil, fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err) + } + allProposals = append(allProposals, proposals...) + } + return &ConfigureForwarderContractsResponse{ + Proposals: allProposals, + }, nil +} diff --git a/deployment/keystone/types.go b/deployment/keystone/types.go index 52620a52a0e..d406487043c 100644 --- a/deployment/keystone/types.go +++ b/deployment/keystone/types.go @@ -230,7 +230,51 @@ type RegisteredDon struct { Nodes []deployment.Node } -func (d RegisteredDon) signers(chainFamily string) []common.Address { +type RegisteredDonConfig struct { + Name string + NodeIDs []string // ids in the offchain client + RegistryChainSel uint64 +} + +func NewRegisteredDon(env deployment.Environment, cfg RegisteredDonConfig) (*RegisteredDon, error) { + // load the don info from the capabilities registry + r, err := GetContractSets(env.Logger, &GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return nil, fmt.Errorf("failed to get contract sets: %w", err) + } + capReg := r.ContractSets[cfg.RegistryChainSel].CapabilitiesRegistry + + di, err := capReg.GetDONs(nil) + if err != nil { + return nil, fmt.Errorf("failed to get dons: %w", err) + } + // load the nodes from the offchain client + nodes, err := deployment.NodeInfo(cfg.NodeIDs, env.Offchain) + if err != nil { + return nil, fmt.Errorf("failed to get node info: %w", err) + } + want := sortedHash(nodes.PeerIDs()) + var don *kcr.CapabilitiesRegistryDONInfo + for i, d := range di { + got := sortedHash(d.NodeP2PIds) + if got == want { + don = &di[i] + } + } + if don == nil { + return nil, fmt.Errorf("don not found in registry") + } + return &RegisteredDon{ + Name: cfg.Name, + Info: *don, + Nodes: nodes, + }, nil +} + +func (d RegisteredDon) Signers(chainFamily string) []common.Address { sort.Slice(d.Nodes, func(i, j int) bool { return d.Nodes[i].PeerID.String() < d.Nodes[j].PeerID.String() }) From f094f6c550df43b761d71fdf10cc70bf71a7a318 Mon Sep 17 00:00:00 2001 From: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com> Date: Fri, 6 Dec 2024 19:36:00 +0100 Subject: [PATCH 33/55] Fix BCFR-1075 Tx Sender go routines leak (#15425) * Do not try to send tx result into collector if SendTransaction was already done * improve comment * changeset * fix changeset --- .changeset/late-doors-battle.md | 5 ++++ common/client/transaction_sender.go | 37 +++++++++++++++++------- common/client/transaction_sender_test.go | 22 ++++++++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 .changeset/late-doors-battle.md diff --git a/.changeset/late-doors-battle.md b/.changeset/late-doors-battle.md new file mode 100644 index 00000000000..8ec64b9048e --- /dev/null +++ b/.changeset/late-doors-battle.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Fix TransactionSender go routine leak. #bugfix diff --git a/common/client/transaction_sender.go b/common/client/transaction_sender.go index cd2ce96c5b2..5f58682142f 100644 --- a/common/client/transaction_sender.go +++ b/common/client/transaction_sender.go @@ -93,6 +93,8 @@ type TransactionSender[TX any, RESULT SendTxResult, CHAIN_ID types.ID, RPC SendT // * Otherwise, returns any (effectively random) of the errors. func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ctx context.Context, tx TX) RESULT { var result RESULT + ctx, cancel := txSender.chStop.Ctx(ctx) + defer cancel() if !txSender.IfStarted(func() { txResults := make(chan RESULT) txResultsToReport := make(chan RESULT) @@ -103,8 +105,6 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct if isSendOnly { txSender.wg.Add(1) go func(ctx context.Context) { - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() defer txSender.wg.Done() // Send-only nodes' results are ignored as they tend to return false-positive responses. // Broadcast to them is necessary to speed up the propagation of TX in the network. @@ -117,8 +117,9 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct healthyNodesNum++ primaryNodeWg.Add(1) go func(ctx context.Context) { - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() + // Broadcasting transaction and results reporting for invariant detection are background jobs that must be detached from + // callers cancellation. + // Results reporting to SendTransaction caller must respect caller's context to avoid goroutine leak. defer primaryNodeWg.Done() r := txSender.broadcastTxAsync(ctx, rpc, tx) select { @@ -128,6 +129,8 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct case txResults <- r: } + ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) + defer cancel() select { case <-ctx.Done(): txSender.lggr.Debugw("Failed to send tx results to report", "err", ctx.Err()) @@ -151,8 +154,13 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct return } + if healthyNodesNum == 0 { + result = txSender.newResult(ErroringNodeError) + return + } + txSender.wg.Add(1) - go txSender.reportSendTxAnomalies(ctx, tx, txResultsToReport) + go txSender.reportSendTxAnomalies(tx, txResultsToReport) result = txSender.collectTxResults(ctx, tx, healthyNodesNum, txResults) }) { @@ -163,6 +171,9 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ct } func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) broadcastTxAsync(ctx context.Context, rpc RPC, tx TX) RESULT { + // broadcast is a background job, so always detach from caller's cancellation + ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) + defer cancel() result := rpc.SendTransaction(ctx, tx) txSender.lggr.Debugw("Node sent transaction", "tx", tx, "err", result.Error()) if !slices.Contains(sendTxSuccessfulCodes, result.Code()) && ctx.Err() == nil { @@ -171,7 +182,7 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) broadcastTxAsync(c return result } -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomalies(ctx context.Context, tx TX, txResults <-chan RESULT) { +func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomalies(tx TX, txResults <-chan RESULT) { defer txSender.wg.Done() resultsByCode := sendTxResults[RESULT]{} // txResults eventually will be closed @@ -179,8 +190,17 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomal resultsByCode[txResult.Code()] = append(resultsByCode[txResult.Code()], txResult) } + select { + case <-txSender.chStop: + // it's ok to receive no results if txSender is closing. Return early to prevent false reporting of invariant violation. + if len(resultsByCode) == 0 { + return + } + default: + } + _, criticalErr := aggregateTxResults[RESULT](resultsByCode) - if criticalErr != nil && ctx.Err() == nil { + if criticalErr != nil { txSender.lggr.Criticalw("observed invariant violation on SendTransaction", "tx", tx, "resultsByCode", resultsByCode, "err", criticalErr) PromMultiNodeInvariantViolations.WithLabelValues(txSender.chainFamily, txSender.chainID.String(), criticalErr.Error()).Inc() } @@ -218,9 +238,6 @@ func aggregateTxResults[RESULT any](resultsByCode sendTxResults[RESULT]) (result } func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan RESULT) RESULT { - if healthyNodesNum == 0 { - return txSender.newResult(ErroringNodeError) - } requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) errorsByCode := sendTxResults[RESULT]{} var softTimeoutChan <-chan time.Time diff --git a/common/client/transaction_sender_test.go b/common/client/transaction_sender_test.go index e9869610828..656791b7e86 100644 --- a/common/client/transaction_sender_test.go +++ b/common/client/transaction_sender_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -293,6 +294,27 @@ func TestTransactionSender_SendTransaction(t *testing.T) { require.NoError(t, result.Error()) require.Equal(t, Successful, result.Code()) }) + t.Run("All background jobs stop even if RPC returns result after soft timeout", func(t *testing.T) { + chainID := types.RandomID() + expectedError := errors.New("transaction failed") + fastNode := newNode(t, expectedError, nil) + + // hold reply from the node till SendTransaction returns result + sendTxContext, sendTxCancel := context.WithCancel(tests.Context(t)) + slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { + <-sendTxContext.Done() + }) + + lggr := logger.Test(t) + + _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, nil) + result := txSender.SendTransaction(sendTxContext, nil) + sendTxCancel() + require.EqualError(t, result.Error(), expectedError.Error()) + // TxSender should stop all background go routines after SendTransaction is done and before test is done. + // Otherwise, it signals that we have a goroutine leak. + txSender.wg.Wait() + }) } func TestTransactionSender_SendTransaction_aggregateTxResults(t *testing.T) { From fe8639a17e67eac2836513ce86705069ee13bacd Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 6 Dec 2024 13:46:21 -0500 Subject: [PATCH 34/55] bumping wsrpc (#15549) --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- deployment/go.mod | 2 +- deployment/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index d468907c550..0caacb11c28 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -310,7 +310,7 @@ require ( github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 225ae3b9191..42378db36de 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1168,8 +1168,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= 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= diff --git a/deployment/go.mod b/deployment/go.mod index 7908b6a8048..d8f1d6a3bf3 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -415,7 +415,7 @@ require ( github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect diff --git a/deployment/go.sum b/deployment/go.sum index fec529e51c6..a1e44825328 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1443,8 +1443,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= 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= diff --git a/go.mod b/go.mod index ad71fa75be3..63e11a3f3fe 100644 --- a/go.mod +++ b/go.mod @@ -89,7 +89,7 @@ require ( github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de - github.com/smartcontractkit/wsrpc v0.8.2 + github.com/smartcontractkit/wsrpc v0.8.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 42de8ab4a72..bb0201fd3c9 100644 --- a/go.sum +++ b/go.sum @@ -1147,8 +1147,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= 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= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index b9c6f213277..4f598a368da 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -428,7 +428,7 @@ require ( github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 6914a06501f..02fc189da83 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,8 +1466,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= 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= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 34717eea023..0da60336039 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -413,7 +413,7 @@ require ( github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index bcb3680e9c5..d2aad258e23 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1457,8 +1457,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= -github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= +github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= +github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= 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= From 4a0e8f01f93ba846a8cd8489c2e187d77c6c7f0a Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Fri, 6 Dec 2024 14:14:54 -0500 Subject: [PATCH 35/55] Static link token (#15546) * Static link token * More testing, support in CCIP * Couple smoke tests * More defense * Comments --- deployment/address_book.go | 23 ++++++ deployment/address_book_test.go | 33 ++++++++ deployment/ccip/changeset/state.go | 25 ++++-- deployment/ccip/changeset/state_test.go | 24 ++++++ deployment/ccip/changeset/view_test.go | 22 +++++ deployment/ccip/view/view.go | 1 + .../changeset/deploy_link_token_test.go | 10 +-- .../common/changeset/internal/mcms_test.go | 2 +- deployment/common/changeset/state.go | 82 +++++++++++++++++-- .../transfer_to_mcms_with_timelock_test.go | 6 +- deployment/common/types/types.go | 11 ++- deployment/common/view/v1_0/link_token.go | 24 ++++-- .../common/view/v1_0/link_token_test.go | 53 ++++++++++++ .../common/view/v1_0/static_link_token.go | 40 +++++++++ .../view/v1_0/static_link_token_test.go | 32 ++++++++ .../changeset/accept_ownership_test.go | 2 +- deployment/keystone/state.go | 2 +- 17 files changed, 360 insertions(+), 32 deletions(-) create mode 100644 deployment/ccip/changeset/state_test.go create mode 100644 deployment/ccip/changeset/view_test.go create mode 100644 deployment/common/view/v1_0/link_token_test.go create mode 100644 deployment/common/view/v1_0/static_link_token.go create mode 100644 deployment/common/view/v1_0/static_link_token_test.go diff --git a/deployment/address_book.go b/deployment/address_book.go index 28d728bf6c7..6f605013011 100644 --- a/deployment/address_book.go +++ b/deployment/address_book.go @@ -271,3 +271,26 @@ func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool, return false, nil } + +// AddressesContainBundle checks if the addresses +// contains a single instance of all the addresses in the bundle. +// It returns an error if there are more than one instance of a contract. +func AddressesContainBundle(addrs map[string]TypeAndVersion, wantTypes map[TypeAndVersion]struct{}) (bool, error) { + counts := make(map[TypeAndVersion]int) + for wantType := range wantTypes { + for _, haveType := range addrs { + if wantType == haveType { + counts[wantType]++ + if counts[wantType] > 1 { + return false, fmt.Errorf("found more than one instance of contract %s", wantType) + } + } + } + } + // Either 0 or 1, so we can just check the sum. + sum := 0 + for _, count := range counts { + sum += count + } + return sum == len(wantTypes), nil +} diff --git a/deployment/address_book_test.go b/deployment/address_book_test.go index 35efdbf8546..e022e89a9ab 100644 --- a/deployment/address_book_test.go +++ b/deployment/address_book_test.go @@ -243,3 +243,36 @@ func TestAddressBook_ConcurrencyAndDeadlock(t *testing.T) { wg.Wait() } + +func TestAddressesContainsBundle(t *testing.T) { + onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0) + onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0) + onRamp120 := NewTypeAndVersion("OnRamp", Version1_2_0) + addr1 := common.HexToAddress("0x1").String() + addr2 := common.HexToAddress("0x2").String() + addr3 := common.HexToAddress("0x3").String() + + // More than one instance should error + _, err := AddressesContainBundle(map[string]TypeAndVersion{ + addr1: onRamp100, + addr2: onRamp100, + }, map[TypeAndVersion]struct{}{onRamp100: {}}) + require.Error(t, err) + + // No such instances should be false + exists, err := AddressesContainBundle(map[string]TypeAndVersion{ + addr2: onRamp110, + addr1: onRamp110, + }, map[TypeAndVersion]struct{}{onRamp100: {}}) + require.NoError(t, err) + assert.Equal(t, exists, false) + + // 2 elements + exists, err = AddressesContainBundle(map[string]TypeAndVersion{ + addr1: onRamp100, + addr2: onRamp110, + addr3: onRamp120, + }, map[TypeAndVersion]struct{}{onRamp100: {}, onRamp110: {}}) + require.NoError(t, err) + assert.Equal(t, exists, true) +} diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go index 0820f42d0c7..22ae59fc360 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/changeset/state.go @@ -82,6 +82,7 @@ var ( type CCIPChainState struct { commoncs.MCMSWithTimelockState commoncs.LinkTokenState + commoncs.StaticLinkTokenState OnRamp *onramp.OnRamp OffRamp *offramp.OffRamp FeeQuoter *fee_quoter.FeeQuoter @@ -219,16 +220,23 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { chainView.MCMSWithTimelock = mcmsView } if c.LinkToken != nil { - linkTokenView, err := common_v1_0.GenerateLinkTokenView(c.LinkToken) + linkTokenView, err := c.GenerateLinkView() if err != nil { return chainView, errors.Wrapf(err, "failed to generate link token view for link token %s", c.LinkToken.Address().String()) } chainView.LinkToken = linkTokenView } + if c.StaticLinkToken != nil { + staticLinkTokenView, err := c.GenerateStaticLinkView() + if err != nil { + return chainView, err + } + chainView.StaticLinkToken = staticLinkTokenView + } return chainView, nil } -// Onchain state always derivable from an address book. +// CCIPOnChainState state always derivable from an address book. // Offchain state always derivable from a list of nodeIds. // Note can translate this into Go struct needed for MCMS/Docs/UI. type CCIPOnChainState struct { @@ -284,24 +292,31 @@ func LoadOnchainState(e deployment.Environment) (CCIPOnChainState, error) { // LoadChainState Loads all state for a chain into state func LoadChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (CCIPChainState, error) { var state CCIPChainState - mcmsWithTimelock, err := commoncs.LoadMCMSWithTimelockState(chain, addresses) + mcmsWithTimelock, err := commoncs.MaybeLoadMCMSWithTimelockState(chain, addresses) if err != nil { return state, err } state.MCMSWithTimelockState = *mcmsWithTimelock - linkState, err := commoncs.LoadLinkTokenState(chain, addresses) + linkState, err := commoncs.MaybeLoadLinkTokenState(chain, addresses) if err != nil { return state, err } state.LinkTokenState = *linkState + staticLinkState, err := commoncs.MaybeLoadStaticLinkTokenState(chain, addresses) + if err != nil { + return state, err + } + state.StaticLinkTokenState = *staticLinkState for address, tvStr := range addresses { switch tvStr.String() { case deployment.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0).String(), deployment.NewTypeAndVersion(commontypes.ProposerManyChainMultisig, deployment.Version1_0_0).String(), deployment.NewTypeAndVersion(commontypes.CancellerManyChainMultisig, deployment.Version1_0_0).String(), deployment.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String(): + deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String(), + deployment.NewTypeAndVersion(commontypes.StaticLinkToken, deployment.Version1_0_0).String(): + // Skip common contracts, they are already loaded. continue case deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0).String(): cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) diff --git a/deployment/ccip/changeset/state_test.go b/deployment/ccip/changeset/state_test.go new file mode 100644 index 00000000000..6e679c265dc --- /dev/null +++ b/deployment/ccip/changeset/state_test.go @@ -0,0 +1,24 @@ +package changeset + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestSmokeState(t *testing.T) { + lggr := logger.TestLogger(t) + tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 1, + }, nil) + state, err := LoadOnchainState(tenv.Env) + require.NoError(t, err) + _, err = state.View(tenv.Env.AllChainSelectors()) + require.NoError(t, err) +} diff --git a/deployment/ccip/changeset/view_test.go b/deployment/ccip/changeset/view_test.go new file mode 100644 index 00000000000..934b937f7b5 --- /dev/null +++ b/deployment/ccip/changeset/view_test.go @@ -0,0 +1,22 @@ +package changeset + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestSmokeView(t *testing.T) { + lggr := logger.TestLogger(t) + tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 1, + }, nil) + _, err := ViewCCIP(tenv.Env) + require.NoError(t, err) +} diff --git a/deployment/ccip/view/view.go b/deployment/ccip/view/view.go index 836dc9c65dd..1cacd58cc2b 100644 --- a/deployment/ccip/view/view.go +++ b/deployment/ccip/view/view.go @@ -28,6 +28,7 @@ type ChainView struct { CapabilityRegistry map[string]common_v1_0.CapabilityRegistryView `json:"capabilityRegistry,omitempty"` MCMSWithTimelock common_v1_0.MCMSWithTimelockView `json:"mcmsWithTimelock,omitempty"` LinkToken common_v1_0.LinkTokenView `json:"linkToken,omitempty"` + StaticLinkToken common_v1_0.StaticLinkTokenView `json:"staticLinkToken,omitempty"` } func NewChain() ChainView { diff --git a/deployment/common/changeset/deploy_link_token_test.go b/deployment/common/changeset/deploy_link_token_test.go index 29a9ece1478..a61743e9bf4 100644 --- a/deployment/common/changeset/deploy_link_token_test.go +++ b/deployment/common/changeset/deploy_link_token_test.go @@ -3,7 +3,6 @@ package changeset_test import ( "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -28,12 +27,9 @@ func TestDeployLinkToken(t *testing.T) { require.NoError(t, err) addrs, err := e.ExistingAddresses.AddressesForChain(chain1) require.NoError(t, err) - state, err := changeset.LoadLinkTokenState(e.Chains[chain1], addrs) + state, err := changeset.MaybeLoadLinkTokenState(e.Chains[chain1], addrs) require.NoError(t, err) - view, err := state.GenerateLinkView() + // View itself already unit tested + _, err = state.GenerateLinkView() require.NoError(t, err) - assert.Equal(t, view.Owner, e.Chains[chain1].DeployerKey.From) - assert.Equal(t, view.TypeAndVersion, "LinkToken 1.0.0") - // Initially nothing minted. - assert.Equal(t, view.Supply.String(), "0") } diff --git a/deployment/common/changeset/internal/mcms_test.go b/deployment/common/changeset/internal/mcms_test.go index 9969a0e5bc9..2269911f4cd 100644 --- a/deployment/common/changeset/internal/mcms_test.go +++ b/deployment/common/changeset/internal/mcms_test.go @@ -49,7 +49,7 @@ func TestDeployMCMSWithTimelockContracts(t *testing.T) { addresses, err := ab.AddressesForChain(chainsel.TEST_90000001.Selector) require.NoError(t, err) require.Len(t, addresses, 4) - mcmsState, err := changeset.LoadMCMSWithTimelockState(chains[chainsel.TEST_90000001.Selector], addresses) + mcmsState, err := changeset.MaybeLoadMCMSWithTimelockState(chains[chainsel.TEST_90000001.Selector], addresses) require.NoError(t, err) v, err := mcmsState.GenerateMCMSWithTimelockView() b, err := json.MarshalIndent(v, "", " ") diff --git a/deployment/common/changeset/state.go b/deployment/common/changeset/state.go index f553e124a38..0055c908f8d 100644 --- a/deployment/common/changeset/state.go +++ b/deployment/common/changeset/state.go @@ -2,6 +2,7 @@ package changeset import ( "errors" + "fmt" "github.com/ethereum/go-ethereum/common" owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" @@ -9,12 +10,14 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" ) // MCMSWithTimelockState holds the Go bindings // for a MCMSWithTimelock contract deployment. // It is public for use in product specific packages. +// Either all fields are nil or all fields are non-nil. type MCMSWithTimelockState struct { CancellerMcm *owner_helpers.ManyChainMultiSig BypasserMcm *owner_helpers.ManyChainMultiSig @@ -22,6 +25,8 @@ type MCMSWithTimelockState struct { Timelock *owner_helpers.RBACTimelock } +// Validate checks that all fields are non-nil, ensuring it's ready +// for use generating views or interactions. func (state MCMSWithTimelockState) Validate() error { if state.Timelock == nil { return errors.New("timelock not found") @@ -66,29 +71,51 @@ func (state MCMSWithTimelockState) GenerateMCMSWithTimelockView() (v1_0.MCMSWith }, nil } -func LoadMCMSWithTimelockState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*MCMSWithTimelockState, error) { +// MaybeLoadMCMSWithTimelockState looks for the addresses corresponding to +// contracts deployed with DeployMCMSWithTimelock and loads them into a +// MCMSWithTimelockState struct. If none of the contracts are found, the state struct will be nil. +// An error indicates: +// - Found but was unable to load a contract +// - It only found part of the bundle of contracts +// - If found more than one instance of a contract (we expect one bundle in the given addresses) +func MaybeLoadMCMSWithTimelockState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*MCMSWithTimelockState, error) { state := MCMSWithTimelockState{} + // We expect one of each contract on the chain. + timelock := deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0) + proposer := deployment.NewTypeAndVersion(types.ProposerManyChainMultisig, deployment.Version1_0_0) + canceller := deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0) + bypasser := deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0) + + // Ensure we either have the bundle or not. + _, err := deployment.AddressesContainBundle(addresses, + map[deployment.TypeAndVersion]struct{}{ + timelock: {}, proposer: {}, canceller: {}, bypasser: {}, + }) + if err != nil { + return nil, fmt.Errorf("unable to check MCMS contracts on chain %s error: %w", chain.Name(), err) + } + for address, tvStr := range addresses { - switch tvStr.String() { - case deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0).String(): + switch tvStr { + case timelock: tl, err := owner_helpers.NewRBACTimelock(common.HexToAddress(address), chain.Client) if err != nil { return nil, err } state.Timelock = tl - case deployment.NewTypeAndVersion(types.ProposerManyChainMultisig, deployment.Version1_0_0).String(): + case proposer: mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) if err != nil { return nil, err } state.ProposerMcm = mcms - case deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0).String(): + case bypasser: mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) if err != nil { return nil, err } state.BypasserMcm = mcms - case deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0).String(): + case canceller: mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) if err != nil { return nil, err @@ -110,10 +137,17 @@ func (s LinkTokenState) GenerateLinkView() (v1_0.LinkTokenView, error) { return v1_0.GenerateLinkTokenView(s.LinkToken) } -func LoadLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*LinkTokenState, error) { +func MaybeLoadLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*LinkTokenState, error) { state := LinkTokenState{} + linkToken := deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0) + // Perhaps revisit if we have a use case for multiple. + _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{linkToken: {}}) + if err != nil { + return nil, fmt.Errorf("unable to check link token on chain %s error: %w", chain.Name(), err) + } for address, tvStr := range addresses { - if tvStr.String() == deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0).String() { + switch tvStr { + case linkToken: lt, err := link_token.NewLinkToken(common.HexToAddress(address), chain.Client) if err != nil { return nil, err @@ -123,3 +157,35 @@ func LoadLinkTokenState(chain deployment.Chain, addresses map[string]deployment. } return &state, nil } + +type StaticLinkTokenState struct { + StaticLinkToken *link_token_interface.LinkToken +} + +func (s StaticLinkTokenState) GenerateStaticLinkView() (v1_0.StaticLinkTokenView, error) { + if s.StaticLinkToken == nil { + return v1_0.StaticLinkTokenView{}, errors.New("static link token not found") + } + return v1_0.GenerateStaticLinkTokenView(s.StaticLinkToken) +} + +func MaybeLoadStaticLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*StaticLinkTokenState, error) { + state := StaticLinkTokenState{} + staticLinkToken := deployment.NewTypeAndVersion(types.StaticLinkToken, deployment.Version1_0_0) + // Perhaps revisit if we have a use case for multiple. + _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{staticLinkToken: {}}) + if err != nil { + return nil, fmt.Errorf("unable to check static link token on chain %s error: %w", chain.Name(), err) + } + for address, tvStr := range addresses { + switch tvStr { + case staticLinkToken: + lt, err := link_token_interface.NewLinkToken(common.HexToAddress(address), chain.Client) + if err != nil { + return nil, err + } + state.StaticLinkToken = lt + } + } + return &state, nil +} diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go index f1f24cb0b05..6cdff286707 100644 --- a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go @@ -42,9 +42,9 @@ func TestTransferToMCMSWithTimelock(t *testing.T) { require.NoError(t, err) addrs, err := e.ExistingAddresses.AddressesForChain(chain1) require.NoError(t, err) - state, err := LoadMCMSWithTimelockState(e.Chains[chain1], addrs) + state, err := MaybeLoadMCMSWithTimelockState(e.Chains[chain1], addrs) require.NoError(t, err) - link, err := LoadLinkTokenState(e.Chains[chain1], addrs) + link, err := MaybeLoadLinkTokenState(e.Chains[chain1], addrs) require.NoError(t, err) e, err = ApplyChangesets(t, e, map[uint64]*owner_helpers.RBACTimelock{ chain1: state.Timelock, @@ -61,7 +61,7 @@ func TestTransferToMCMSWithTimelock(t *testing.T) { }) require.NoError(t, err) // We expect now that the link token is owned by the MCMS timelock. - link, err = LoadLinkTokenState(e.Chains[chain1], addrs) + link, err = MaybeLoadLinkTokenState(e.Chains[chain1], addrs) require.NoError(t, err) o, err := link.LinkToken.Owner(nil) require.NoError(t, err) diff --git a/deployment/common/types/types.go b/deployment/common/types/types.go index a6504d17a94..386ef8fbb36 100644 --- a/deployment/common/types/types.go +++ b/deployment/common/types/types.go @@ -16,7 +16,16 @@ const ( CancellerManyChainMultisig deployment.ContractType = "CancellerManyChainMultiSig" ProposerManyChainMultisig deployment.ContractType = "ProposerManyChainMultiSig" RBACTimelock deployment.ContractType = "RBACTimelock" - LinkToken deployment.ContractType = "LinkToken" + // LinkToken is the burn/mint link token. It should be used everywhere for + // new deployments. Corresponds to + // https://github.com/smartcontractkit/chainlink/blob/develop/core/gethwrappers/shared/generated/link_token/link_token.go#L34 + LinkToken deployment.ContractType = "LinkToken" + // StaticLinkToken represents the (very old) non-burn/mint link token. + // It is not used in new deployments, but still exists on some chains + // and has a distinct ABI from the new LinkToken. + // Corresponds to the ABI + // https://github.com/smartcontractkit/chainlink/blob/develop/core/gethwrappers/generated/link_token_interface/link_token_interface.go#L34 + StaticLinkToken deployment.ContractType = "StaticLinkToken" ) type MCMSWithTimelockConfig struct { diff --git a/deployment/common/view/v1_0/link_token.go b/deployment/common/view/v1_0/link_token.go index 19b1b43aa02..6dd1a00be3b 100644 --- a/deployment/common/view/v1_0/link_token.go +++ b/deployment/common/view/v1_0/link_token.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink/deployment" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/common/view/types" @@ -12,22 +14,32 @@ import ( type LinkTokenView struct { types.ContractMetaData - Decimals uint8 `json:"decimals"` - Supply *big.Int `json:"supply"` + Decimals uint8 `json:"decimals"` + Supply *big.Int `json:"supply"` + Minters []common.Address `json:"minters"` + Burners []common.Address `json:"burners"` } func GenerateLinkTokenView(lt *link_token.LinkToken) (LinkTokenView, error) { owner, err := lt.Owner(nil) if err != nil { - return LinkTokenView{}, fmt.Errorf("view error to get link token owner addr %s: %w", lt.Address().String(), err) + return LinkTokenView{}, fmt.Errorf("failed to get owner %s: %w", lt.Address(), err) } decimals, err := lt.Decimals(nil) if err != nil { - return LinkTokenView{}, fmt.Errorf("view error to get link token decimals addr %s: %w", lt.Address().String(), err) + return LinkTokenView{}, fmt.Errorf("failed to get decimals %s: %w", lt.Address(), err) } totalSupply, err := lt.TotalSupply(nil) if err != nil { - return LinkTokenView{}, fmt.Errorf("view error to get link token total supply addr %s: %w", lt.Address().String(), err) + return LinkTokenView{}, fmt.Errorf("failed to get total supply %s: %w", lt.Address(), err) + } + minters, err := lt.GetMinters(nil) + if err != nil { + return LinkTokenView{}, fmt.Errorf("failed to get minters %s: %w", lt.Address(), err) + } + burners, err := lt.GetBurners(nil) + if err != nil { + return LinkTokenView{}, fmt.Errorf("failed to get burners %s: %w", lt.Address(), err) } return LinkTokenView{ ContractMetaData: types.ContractMetaData{ @@ -40,5 +52,7 @@ func GenerateLinkTokenView(lt *link_token.LinkToken) (LinkTokenView, error) { }, Decimals: decimals, Supply: totalSupply, + Minters: minters, + Burners: burners, }, nil } diff --git a/deployment/common/view/v1_0/link_token_test.go b/deployment/common/view/v1_0/link_token_test.go new file mode 100644 index 00000000000..c83c0b3e3c2 --- /dev/null +++ b/deployment/common/view/v1_0/link_token_test.go @@ -0,0 +1,53 @@ +package v1_0 + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestLinkTokenView(t *testing.T) { + e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + }) + chain := e.Chains[e.AllChainSelectors()[0]] + _, tx, lt, err := link_token.DeployLinkToken(chain.DeployerKey, chain.Client) + require.NoError(t, err) + _, err = chain.Confirm(tx) + require.NoError(t, err) + v, err := GenerateLinkTokenView(lt) + require.NoError(t, err) + + assert.Equal(t, v.Owner, chain.DeployerKey.From) + assert.Equal(t, v.TypeAndVersion, "LinkToken 1.0.0") + assert.Equal(t, v.Decimals, uint8(18)) + // Initially nothing minted and no minters/burners. + assert.Equal(t, v.Supply.String(), "0") + require.Len(t, v.Minters, 0) + require.Len(t, v.Burners, 0) + + // Add some minters + tx, err = lt.GrantMintAndBurnRoles(chain.DeployerKey, chain.DeployerKey.From) + require.NoError(t, err) + _, err = chain.Confirm(tx) + require.NoError(t, err) + tx, err = lt.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(100)) + _, err = chain.Confirm(tx) + require.NoError(t, err) + + v, err = GenerateLinkTokenView(lt) + require.NoError(t, err) + + assert.Equal(t, v.Supply.String(), "100") + require.Len(t, v.Minters, 1) + require.Equal(t, v.Minters[0].String(), chain.DeployerKey.From.String()) + require.Len(t, v.Burners, 1) + require.Equal(t, v.Burners[0].String(), chain.DeployerKey.From.String()) +} diff --git a/deployment/common/view/v1_0/static_link_token.go b/deployment/common/view/v1_0/static_link_token.go new file mode 100644 index 00000000000..525f1a9f0c5 --- /dev/null +++ b/deployment/common/view/v1_0/static_link_token.go @@ -0,0 +1,40 @@ +package v1_0 + +import ( + "fmt" + "math/big" + + "github.com/smartcontractkit/chainlink/deployment" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/common/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" +) + +type StaticLinkTokenView struct { + types.ContractMetaData + Decimals uint8 `json:"decimals"` + Supply *big.Int `json:"supply"` +} + +func GenerateStaticLinkTokenView(lt *link_token_interface.LinkToken) (StaticLinkTokenView, error) { + decimals, err := lt.Decimals(nil) + if err != nil { + return StaticLinkTokenView{}, fmt.Errorf("failed to get decimals %s: %w", lt.Address(), err) + } + totalSupply, err := lt.TotalSupply(nil) + if err != nil { + return StaticLinkTokenView{}, fmt.Errorf("failed to get total supply %s: %w", lt.Address(), err) + } + return StaticLinkTokenView{ + ContractMetaData: types.ContractMetaData{ + TypeAndVersion: deployment.TypeAndVersion{ + commontypes.StaticLinkToken, + deployment.Version1_0_0, + }.String(), + Address: lt.Address(), + // No owner. + }, + Decimals: decimals, + Supply: totalSupply, + }, nil +} diff --git a/deployment/common/view/v1_0/static_link_token_test.go b/deployment/common/view/v1_0/static_link_token_test.go new file mode 100644 index 00000000000..517efac9438 --- /dev/null +++ b/deployment/common/view/v1_0/static_link_token_test.go @@ -0,0 +1,32 @@ +package v1_0 + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestStaticLinkTokenView(t *testing.T) { + e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + }) + chain := e.Chains[e.AllChainSelectors()[0]] + _, tx, lt, err := link_token_interface.DeployLinkToken(chain.DeployerKey, chain.Client) + require.NoError(t, err) + _, err = chain.Confirm(tx) + require.NoError(t, err) + v, err := GenerateStaticLinkTokenView(lt) + require.NoError(t, err) + + assert.Equal(t, v.Owner, common.HexToAddress("0x0")) // Ownerless + assert.Equal(t, v.TypeAndVersion, "StaticLinkToken 1.0.0") + assert.Equal(t, v.Decimals, uint8(18)) + assert.Equal(t, v.Supply.String(), "1000000000000000000000000000") +} diff --git a/deployment/keystone/changeset/accept_ownership_test.go b/deployment/keystone/changeset/accept_ownership_test.go index ec65ef920ac..f205adda496 100644 --- a/deployment/keystone/changeset/accept_ownership_test.go +++ b/deployment/keystone/changeset/accept_ownership_test.go @@ -54,7 +54,7 @@ func TestAcceptAllOwnership(t *testing.T) { require.NoError(t, err) addrs, err := env.ExistingAddresses.AddressesForChain(registrySel) require.NoError(t, err) - timelock, err := commonchangeset.LoadMCMSWithTimelockState(env.Chains[registrySel], addrs) + timelock, err := commonchangeset.MaybeLoadMCMSWithTimelockState(env.Chains[registrySel], addrs) require.NoError(t, err) _, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*owner_helpers.RBACTimelock{ diff --git a/deployment/keystone/state.go b/deployment/keystone/state.go index 1e6ffdd895f..cbf449c7f31 100644 --- a/deployment/keystone/state.go +++ b/deployment/keystone/state.go @@ -78,7 +78,7 @@ func GetContractSets(lggr logger.Logger, req *GetContractSetsRequest) (*GetContr func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*ContractSet, error) { var out ContractSet - mcmsWithTimelock, err := commonchangeset.LoadMCMSWithTimelockState(chain, addresses) + mcmsWithTimelock, err := commonchangeset.MaybeLoadMCMSWithTimelockState(chain, addresses) if err != nil { return nil, fmt.Errorf("failed to load mcms contract: %w", err) } From 125d98cdaf66445c025f93997b95f66783c6471f Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Fri, 6 Dec 2024 13:05:21 -0800 Subject: [PATCH 36/55] fix: install base dependencies when running changesets (#15551) --- .github/workflows/changeset.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index 331492eb74f..d6d269326c7 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -184,10 +184,16 @@ jobs: - name: Setup node uses: ./.github/actions/setup-nodejs if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} - + + - name: Install base dependencies + if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} + run: pnpm i + - name: Validate changeset files if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} working-directory: contracts + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | pnpm changeset version From 074c1f2c3fe089d9ae5a223e5fb33ce710a35d4d Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Fri, 6 Dec 2024 18:04:54 -0500 Subject: [PATCH 37/55] Fix multiclient (#15557) --- deployment/multiclient.go | 18 ++++++++---------- deployment/multiclient_test.go | 24 +++++++++++++++++++----- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/deployment/multiclient.go b/deployment/multiclient.go index 914c1fbd9e3..f1ac2f3c310 100644 --- a/deployment/multiclient.go +++ b/deployment/multiclient.go @@ -61,17 +61,15 @@ func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiCl if err != nil { return nil, fmt.Errorf("failed to dial ws url '%s': %w", rpc.WSURL, err) } - // fetch chain name if not set - if mc.chainName == "" { - id, err := client.ChainID(context.Background()) - if err == nil { - details, err := chainselectors.GetChainDetailsByChainIDAndFamily(id.String(), chainselectors.FamilyEVM) - if err == nil { - return nil, err - } - mc.chainName = details.ChainName - } + id, err := client.ChainID(context.Background()) + if err != nil { + return nil, fmt.Errorf("failed to get chain id: %w", err) + } + details, err := chainselectors.GetChainDetailsByChainIDAndFamily(id.String(), chainselectors.FamilyEVM) + if err != nil { + return nil, fmt.Errorf("failed to lookup chain details %w", err) } + mc.chainName = details.ChainName clients = append(clients, client) } mc.Client = clients[0] diff --git a/deployment/multiclient_test.go b/deployment/multiclient_test.go index 0dbebbe3a6a..2e10c46e33f 100644 --- a/deployment/multiclient_test.go +++ b/deployment/multiclient_test.go @@ -1,6 +1,7 @@ package deployment import ( + "io/ioutil" "net/http" "net/http/httptest" "testing" @@ -15,20 +16,33 @@ func TestMultiClient(t *testing.T) { lggr := logger.TestLogger(t) // Expect an error if no RPCs supplied. s := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { - writer.WriteHeader(http.StatusOK) - _, err := writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":true}`)) + b, err := ioutil.ReadAll(request.Body) require.NoError(t, err) + // TODO: Helper struct somewhere for this? + if string(b) == "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_chainId\"}" { + writer.WriteHeader(http.StatusOK) + // Respond with 1337 + _, err = writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":"0x539"}`)) + require.NoError(t, err) + return + } else { + // Dial + writer.WriteHeader(http.StatusOK) + _, err = writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":true}`)) + require.NoError(t, err) + } })) defer s.Close() - _, err := NewMultiClient(lggr, []RPC{}) - require.Error(t, err) - // Expect defaults to be set if not provided. mc, err := NewMultiClient(lggr, []RPC{{WSURL: s.URL}}) require.NoError(t, err) + require.NotNil(t, mc) assert.Equal(t, mc.RetryConfig.Attempts, uint(RPC_DEFAULT_RETRY_ATTEMPTS)) assert.Equal(t, mc.RetryConfig.Delay, RPC_DEFAULT_RETRY_DELAY) + _, err = NewMultiClient(lggr, []RPC{}) + require.Error(t, err) + // Expect second client to be set as backup. mc, err = NewMultiClient(lggr, []RPC{ {WSURL: s.URL}, From ddd012ec2969730b15019bc8373e0783eb13428b Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Fri, 6 Dec 2024 18:19:27 -0500 Subject: [PATCH 38/55] Skip ccip transfer tests (#15558) * Skip * Skip USDC * Leave USDC actually --- integration-tests/smoke/ccip/ccip_token_transfer_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go index 81920246bed..979a6b13695 100644 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -25,6 +25,7 @@ import ( ) func TestTokenTransfer(t *testing.T) { + t.Skip("need to deflake and optimize") lggr := logger.TestLogger(t) ctx := tests.Context(t) config := &changeset.TestConfigs{} From 49b77048d1b5480a07b9f77b32b005379c679c44 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Mon, 9 Dec 2024 09:18:27 +0100 Subject: [PATCH 39/55] CCIP-4447 Llo promwrapper (#15539) * Adding OCR3 metrics promwrapper to LLO * Changeset bump * Added some logging * Added some logging * Added some logging --- .changeset/clean-files-beg.md | 5 +++++ .../capabilities/ccip/oraclecreator/plugin.go | 4 ++-- core/services/llo/delegate.go | 19 +++++++++++++++++-- core/services/ocr2/delegate.go | 1 + core/services/ocr3/promwrapper/factory.go | 9 +++++++++ .../services/ocr3/promwrapper/factory_test.go | 6 ++++-- 6 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 .changeset/clean-files-beg.md diff --git a/.changeset/clean-files-beg.md b/.changeset/clean-files-beg.md new file mode 100644 index 00000000000..1357a044cb0 --- /dev/null +++ b/.changeset/clean-files-beg.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Adding OCR3 promwrapper to LLO #internal diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 1b8c6344349..a716d96418a 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -270,7 +270,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( rmnPeerClient, rmnCrypto, ) - factory = promwrapper.NewReportingPluginFactory[[]byte](factory, chainID, "CCIPCommit") + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPCommit") transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? @@ -291,7 +291,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( contractReaders, chainWriters, ) - factory = promwrapper.NewReportingPluginFactory[[]byte](factory, chainID, "CCIPExec") + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPExec") transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index d305fe0e948..ba4ddbb8fb0 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -21,6 +21,7 @@ import ( corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) @@ -59,6 +60,7 @@ type DelegateConfig struct { ShouldRetireCache datastreamsllo.ShouldRetireCache EAMonitoringEndpoint ocrcommontypes.MonitoringEndpoint DonID uint32 + ChainID string // OCR3 TraceLogging bool @@ -151,8 +153,21 @@ func (d *delegate) Start(ctx context.Context) error { OffchainConfigDigester: d.cfg.OffchainConfigDigester, OffchainKeyring: d.cfg.OffchainKeyring, OnchainKeyring: d.cfg.OnchainKeyring, - ReportingPluginFactory: datastreamsllo.NewPluginFactory( - d.cfg.ReportingPluginConfig, psrrc, d.src, d.cfg.RetirementReportCodec, d.cfg.ChannelDefinitionCache, d.ds, logger.Named(lggr, "ReportingPlugin"), llo.EVMOnchainConfigCodec{}, d.reportCodecs, + ReportingPluginFactory: promwrapper.NewReportingPluginFactory( + datastreamsllo.NewPluginFactory( + d.cfg.ReportingPluginConfig, + psrrc, + d.src, + d.cfg.RetirementReportCodec, + d.cfg.ChannelDefinitionCache, + d.ds, + logger.Named(lggr, "ReportingPlugin"), + llo.EVMOnchainConfigCodec{}, + d.reportCodecs, + ), + lggr, + d.cfg.ChainID, + "llo", ), MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": d.cfg.JobName.ValueOrZero()}, prometheus.DefaultRegisterer), }) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index e7a5a1c3a92..edcc816bf04 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -1048,6 +1048,7 @@ func (d *Delegate) newServicesLLO( RetirementReportCodec: datastreamsllo.StandardRetirementReportCodec{}, EAMonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, telemetryContractID, synchronization.EnhancedEAMercury), DonID: pluginCfg.DonID, + ChainID: rid.ChainID, TraceLogging: d.cfg.OCR2().TraceLogging(), BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, diff --git a/core/services/ocr3/promwrapper/factory.go b/core/services/ocr3/promwrapper/factory.go index 0dabd346112..84269cf3779 100644 --- a/core/services/ocr3/promwrapper/factory.go +++ b/core/services/ocr3/promwrapper/factory.go @@ -3,6 +3,8 @@ package promwrapper import ( "context" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ) @@ -10,17 +12,20 @@ var _ ocr3types.ReportingPluginFactory[any] = &ReportingPluginFactory[any]{} type ReportingPluginFactory[RI any] struct { origin ocr3types.ReportingPluginFactory[RI] + lggr logger.Logger chainID string plugin string } func NewReportingPluginFactory[RI any]( origin ocr3types.ReportingPluginFactory[RI], + lggr logger.Logger, chainID string, plugin string, ) *ReportingPluginFactory[RI] { return &ReportingPluginFactory[RI]{ origin: origin, + lggr: lggr, chainID: chainID, plugin: plugin, } @@ -31,6 +36,10 @@ func (r ReportingPluginFactory[RI]) NewReportingPlugin(ctx context.Context, conf if err != nil { return nil, ocr3types.ReportingPluginInfo{}, err } + r.lggr.Infow("Wrapping ReportingPlugin with prometheus metrics reporter", + "configDigest", config.ConfigDigest, + "oracleID", config.OracleID, + ) wrapped := newReportingPlugin( plugin, r.chainID, diff --git a/core/services/ocr3/promwrapper/factory_test.go b/core/services/ocr3/promwrapper/factory_test.go index 72f35aad172..fb68c039b78 100644 --- a/core/services/ocr3/promwrapper/factory_test.go +++ b/core/services/ocr3/promwrapper/factory_test.go @@ -10,11 +10,13 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/logger" ) func Test_WrapperFactory(t *testing.T) { - validFactory := NewReportingPluginFactory(fakeFactory[uint]{}, "solana", "plugin") - failingFactory := NewReportingPluginFactory(fakeFactory[uint]{err: errors.New("error")}, "123", "plugin") + validFactory := NewReportingPluginFactory(fakeFactory[uint]{}, logger.TestLogger(t), "solana", "plugin") + failingFactory := NewReportingPluginFactory(fakeFactory[uint]{err: errors.New("error")}, logger.TestLogger(t), "123", "plugin") plugin, _, err := validFactory.NewReportingPlugin(tests.Context(t), ocr3types.ReportingPluginConfig{}) require.NoError(t, err) From 036cb20d43b8f2d3cdb4de79d11f97ff63831025 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Mon, 9 Dec 2024 12:18:32 +0100 Subject: [PATCH 40/55] CCIP-4447 Publishing status of the OCR3 plugin (based on the config digest) (#15544) * Publishing status of the OCR3 plugin (based on the config digest) * Publishing status of the OCR3 plugin (based on the config digest) --- .changeset/dull-readers-rush.md | 5 ++++ core/services/ocr3/promwrapper/factory.go | 2 ++ core/services/ocr3/promwrapper/plugin.go | 28 +++++++++++++++---- core/services/ocr3/promwrapper/plugin_test.go | 19 +++++++++---- core/services/ocr3/promwrapper/types.go | 7 +++++ 5 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 .changeset/dull-readers-rush.md diff --git a/.changeset/dull-readers-rush.md b/.changeset/dull-readers-rush.md new file mode 100644 index 00000000000..3b6f2ae8758 --- /dev/null +++ b/.changeset/dull-readers-rush.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Reporting number of OCR3 instances running using promwrapper #internal diff --git a/core/services/ocr3/promwrapper/factory.go b/core/services/ocr3/promwrapper/factory.go index 84269cf3779..6518cea3c0d 100644 --- a/core/services/ocr3/promwrapper/factory.go +++ b/core/services/ocr3/promwrapper/factory.go @@ -44,8 +44,10 @@ func (r ReportingPluginFactory[RI]) NewReportingPlugin(ctx context.Context, conf plugin, r.chainID, r.plugin, + config.ConfigDigest.String(), promOCR3ReportsGenerated, promOCR3Durations, + promOCR3PluginStatus, ) return wrapped, info, err } diff --git a/core/services/ocr3/promwrapper/plugin.go b/core/services/ocr3/promwrapper/plugin.go index e4e0c3d35d5..dcee5050d1e 100644 --- a/core/services/ocr3/promwrapper/plugin.go +++ b/core/services/ocr3/promwrapper/plugin.go @@ -14,27 +14,33 @@ var _ ocr3types.ReportingPlugin[any] = &reportingPlugin[any]{} type reportingPlugin[RI any] struct { ocr3types.ReportingPlugin[RI] - chainID string - plugin string + chainID string + plugin string + configDigest string // Prometheus components for tracking metrics reportsGenerated *prometheus.CounterVec durations *prometheus.HistogramVec + status *prometheus.GaugeVec } func newReportingPlugin[RI any]( origin ocr3types.ReportingPlugin[RI], chainID string, plugin string, + configDigest string, reportsGenerated *prometheus.CounterVec, durations *prometheus.HistogramVec, + status *prometheus.GaugeVec, ) *reportingPlugin[RI] { return &reportingPlugin[RI]{ ReportingPlugin: origin, chainID: chainID, plugin: plugin, + configDigest: configDigest, reportsGenerated: reportsGenerated, durations: durations, + status: status, } } @@ -88,15 +94,23 @@ func (p *reportingPlugin[RI]) ShouldTransmitAcceptedReport(ctx context.Context, return result, err } -func (p *reportingPlugin[RI]) trackReports( - function functionType, - count int, -) { +func (p *reportingPlugin[RI]) Close() error { + p.updateStatus(false) + return p.ReportingPlugin.Close() +} + +func (p *reportingPlugin[RI]) trackReports(function functionType, count int) { p.reportsGenerated. WithLabelValues(p.chainID, p.plugin, string(function)). Add(float64(count)) } +func (p *reportingPlugin[RI]) updateStatus(status bool) { + p.status. + WithLabelValues(p.chainID, p.plugin, p.configDigest). + Set(float64(boolToInt(status))) +} + func boolToInt(arg bool) int { if arg { return 1 @@ -118,5 +132,7 @@ func withObservedExecution[RI, R any]( WithLabelValues(p.chainID, p.plugin, string(function), strconv.FormatBool(success)). Observe(float64(time.Since(start))) + p.updateStatus(true) + return result, err } diff --git a/core/services/ocr3/promwrapper/plugin_test.go b/core/services/ocr3/promwrapper/plugin_test.go index 35a97d109aa..9a7b6f2e648 100644 --- a/core/services/ocr3/promwrapper/plugin_test.go +++ b/core/services/ocr3/promwrapper/plugin_test.go @@ -19,15 +19,15 @@ import ( func Test_ReportsGeneratedGauge(t *testing.T) { plugin1 := newReportingPlugin( fakePlugin[uint]{reports: make([]ocr3types.ReportPlus[uint], 2)}, - "123", "empty", promOCR3ReportsGenerated, promOCR3Durations, + "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, ) plugin2 := newReportingPlugin( fakePlugin[bool]{reports: make([]ocr3types.ReportPlus[bool], 10)}, - "solana", "different_plugin", promOCR3ReportsGenerated, promOCR3Durations, + "solana", "different_plugin", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, ) plugin3 := newReportingPlugin( fakePlugin[string]{err: errors.New("error")}, - "1234", "empty", promOCR3ReportsGenerated, promOCR3Durations, + "1234", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, ) r1, err := plugin1.Reports(tests.Context(t), 1, nil) @@ -57,20 +57,27 @@ func Test_ReportsGeneratedGauge(t *testing.T) { g4 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("1234", "empty", "reports")) require.Equal(t, 0, int(g4)) + + pluginHealth := testutil.ToFloat64(promOCR3PluginStatus.WithLabelValues("123", "empty", "abc")) + require.Equal(t, 1, int(pluginHealth)) + + require.NoError(t, plugin1.Close()) + pluginHealth = testutil.ToFloat64(promOCR3PluginStatus.WithLabelValues("123", "empty", "abc")) + require.Equal(t, 0, int(pluginHealth)) } func Test_DurationHistograms(t *testing.T) { plugin1 := newReportingPlugin( fakePlugin[uint]{}, - "123", "empty", promOCR3ReportsGenerated, promOCR3Durations, + "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, ) plugin2 := newReportingPlugin( fakePlugin[uint]{err: errors.New("error")}, - "123", "empty", promOCR3ReportsGenerated, promOCR3Durations, + "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, ) plugin3 := newReportingPlugin( fakePlugin[uint]{}, - "solana", "commit", promOCR3ReportsGenerated, promOCR3Durations, + "solana", "commit", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3PluginStatus, ) for _, p := range []*reportingPlugin[uint]{plugin1, plugin2, plugin3} { diff --git a/core/services/ocr3/promwrapper/types.go b/core/services/ocr3/promwrapper/types.go index bf6a1b2a39c..2fa29dcdf20 100644 --- a/core/services/ocr3/promwrapper/types.go +++ b/core/services/ocr3/promwrapper/types.go @@ -48,4 +48,11 @@ var ( }, []string{"chainID", "plugin", "function", "success"}, ) + promOCR3PluginStatus = promauto.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "ocr3_reporting_plugin_status", + Help: "Gauge indicating whether plugin is up and running or not", + }, + []string{"chainID", "plugin", "configDigest"}, + ) ) From a4b0c1914697e56ef05f12b97bf423b58c31ff04 Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Mon, 9 Dec 2024 04:15:12 -0800 Subject: [PATCH 41/55] Upgrade chain selectors (#15561) * chain-selector upgrade * more --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- deployment/go.mod | 2 +- deployment/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 0caacb11c28..8f9e458b8e2 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -297,7 +297,7 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect - github.com/smartcontractkit/chain-selectors v1.0.31 // indirect + github.com/smartcontractkit/chain-selectors v1.0.34 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 42378db36de..3b8c5987c00 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1136,8 +1136,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= diff --git a/deployment/go.mod b/deployment/go.mod index d8f1d6a3bf3..b9a2fdb255f 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -23,7 +23,7 @@ require ( github.com/rs/zerolog v1.33.0 github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 - github.com/smartcontractkit/chain-selectors v1.0.31 + github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 diff --git a/deployment/go.sum b/deployment/go.sum index a1e44825328..7513309dddf 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1405,8 +1405,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= diff --git a/go.mod b/go.mod index 63e11a3f3fe..35069d38bbf 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/scylladb/go-reflectx v1.0.1 github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chain-selectors v1.0.31 + github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f diff --git a/go.sum b/go.sum index bb0201fd3c9..caa877d66fa 100644 --- a/go.sum +++ b/go.sum @@ -1119,8 +1119,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 4f598a368da..f4e6a9720e8 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -38,7 +38,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 - github.com/smartcontractkit/chain-selectors v1.0.31 + github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 02fc189da83..9e0e176190d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1426,8 +1426,8 @@ github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0 github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 0da60336039..23f840a67f3 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -399,7 +399,7 @@ require ( github.com/shoenig/test v0.6.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chain-selectors v1.0.31 // indirect + github.com/smartcontractkit/chain-selectors v1.0.34 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index d2aad258e23..e9eaaf81dad 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1417,8 +1417,8 @@ github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0 github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.31 h1:oRHyK88KnsCh4OdU2hr0u70pm3KUgyMDyK0v0aOtUk4= -github.com/smartcontractkit/chain-selectors v1.0.31/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= +github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= From 077971ef1ab19e15b066722cbb7b774dea4d225d Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Mon, 9 Dec 2024 13:53:42 +0100 Subject: [PATCH 42/55] Memorize longer tests (#15566) --- .github/e2e-tests.yml | 39 --------- .github/integration-in-memory-tests.yml | 24 ++++++ .../smoke/ccip/ccip_ooo_execution_test.go | 11 ++- .../smoke/ccip/ccip_token_transfer_test.go | 82 +++---------------- .../smoke/ccip/ccip_usdc_test.go | 15 ++-- 5 files changed, 51 insertions(+), 120 deletions(-) diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index 3b394293378..d40d375f860 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -948,45 +948,6 @@ runner-test-matrix: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_token_transfer_test.go:* - path: integration-tests/smoke/ccip/ccip_token_transfer_test.go - test_env_type: docker - runs_on: ubuntu-latest - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_token_transfer_test.go -timeout 16m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - - - id: smoke/ccip/ccip_ooo_execution_test.go:* - path: integration-tests/smoke/ccip/ccip_ooo_execution_test.go - test_env_type: docker - runs_on: ubuntu-latest - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_ooo_execution_test.go -timeout 16m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - - - id: smoke/ccip/ccip_usdc_test.go:* - path: integration-tests/smoke/ccip/ccip_usdc_test.go - test_env_type: docker - runs_on: ubuntu-latest - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_usdc_test.go -timeout 18m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2,SIMULATED_3 - E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_message_limitations_test.go:* path: integration-tests/smoke/ccip/ccip_message_limitations_test.go test_env_type: docker diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 4b4fd71258d..b7522274d85 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -48,4 +48,28 @@ runner-test-matrix: - PR Integration CCIP Tests test_cmd: cd integration-tests/contracts && go test ccipreader_test.go -timeout 5m -test.parallel=1 -count=1 -json + - id: smoke/ccip/ccip_usdc_test.go:* + path: integration-tests/smoke/ccip/ccip_usdc_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/smoke/ccip && go test ccip_usdc_test.go -timeout 18m -test.parallel=1 -count=1 -json + + - id: smoke/ccip/ccip_ooo_execution_test.go:* + path: integration-tests/smoke/ccip/ccip_ooo_execution_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_ooo_execution_test.go -timeout 16m -test.parallel=1 -count=1 -json + + - id: smoke/ccip/ccip_token_transfer_test.go:* + path: integration-tests/smoke/ccip/ccip_token_transfer_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_token_transfer_test.go -timeout 16m -test.parallel=1 -count=1 -json + # END: CCIP tests diff --git a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go index 6a3a6b869cd..86ddd07ec85 100644 --- a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go +++ b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go @@ -14,7 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -36,9 +36,12 @@ func Test_OutOfOrderExecution(t *testing.T) { IsUSDC: true, IsUSDCAttestationMissing: true, } - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - // Inmemory setup used for debugging and development, use instead of docker when needed - //tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 2, + }, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go index 979a6b13695..13abe33fe7c 100644 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -1,56 +1,50 @@ package smoke import ( - "context" "math/big" "testing" "golang.org/x/exp/maps" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" - sel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" ) func TestTokenTransfer(t *testing.T) { - t.Skip("need to deflake and optimize") lggr := logger.TestLogger(t) ctx := tests.Context(t) config := &changeset.TestConfigs{} - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - inMemoryEnv := false - // use this if you are testing locally in memory - // tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, 2, 4, config) - // inMemoryEnv := true + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + NumOfUsersPerChain: 3, + }, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) require.NoError(t, err) + require.GreaterOrEqual(t, len(e.Chains), 2) allChainSelectors := maps.Keys(e.Chains) sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] ownerSourceChain := e.Chains[sourceChain].DeployerKey ownerDestChain := e.Chains[destChain].DeployerKey - oneE18 := new(big.Int).SetUint64(1e18) - funds := new(big.Int).Mul(oneE18, new(big.Int).SetUint64(10)) + require.GreaterOrEqual(t, len(tenv.Users[sourceChain]), 2) + require.GreaterOrEqual(t, len(tenv.Users[destChain]), 2) + selfServeSrcTokenPoolDeployer := tenv.Users[sourceChain][1] + selfServeDestTokenPoolDeployer := tenv.Users[destChain][1] - // Deploy and fund self-serve actors - selfServeSrcTokenPoolDeployer := createAndFundSelfServeActor(ctx, t, ownerSourceChain, e.Chains[sourceChain], funds, inMemoryEnv) - selfServeDestTokenPoolDeployer := createAndFundSelfServeActor(ctx, t, ownerDestChain, e.Chains[destChain], funds, inMemoryEnv) + oneE18 := new(big.Int).SetUint64(1e18) // Deploy tokens and pool by CCIP Owner srcToken, _, destToken, _, err := changeset.DeployTransferableToken( @@ -227,53 +221,3 @@ func TestTokenTransfer(t *testing.T) { changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) } - -func createAndFundSelfServeActor( - ctx context.Context, - t *testing.T, - deployer *bind.TransactOpts, - chain deployment.Chain, - amountToFund *big.Int, - isInMemory bool, -) *bind.TransactOpts { - key, err := crypto.GenerateKey() - require.NoError(t, err) - - // Simulated backend sets chainID to 1337 always - chainID := big.NewInt(1337) - if !isInMemory { - // Docker environment runs real geth so chainID has to be set accordingly - stringChainID, err1 := sel.GetChainIDFromSelector(chain.Selector) - require.NoError(t, err1) - chainID, _ = new(big.Int).SetString(stringChainID, 10) - } - - actor, err := bind.NewKeyedTransactorWithChainID(key, chainID) - require.NoError(t, err) - - nonce, err := chain.Client.PendingNonceAt(ctx, deployer.From) - require.NoError(t, err) - - gasPrice, err := chain.Client.SuggestGasPrice(ctx) - require.NoError(t, err) - - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &actor.From, - Value: amountToFund, - Gas: uint64(21000), - GasPrice: gasPrice, - Data: nil, - }) - - signedTx, err := deployer.Signer(deployer.From, tx) - require.NoError(t, err) - - err = chain.Client.SendTransaction(ctx, signedTx) - require.NoError(t, err) - - _, err = chain.Confirm(signedTx) - require.NoError(t, err) - - return actor -} diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index eacf03df926..2dae3f3c48e 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" @@ -34,13 +34,12 @@ func TestUSDCTokenTransfer(t *testing.T) { config := &changeset.TestConfigs{ IsUSDC: true, } - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - //tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ - // Chains: 3, - // NumOfUsersPerChain: 3, - // Nodes: 5, - // Bootstraps: 1, - //}, config) + tenv := changeset.NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ + Chains: 3, + NumOfUsersPerChain: 3, + Nodes: 4, + Bootstraps: 1, + }, config) e := tenv.Env state, err := changeset.LoadOnchainState(e) From 54938d4ad2b430d4941eaae711abe5e1e6a7686a Mon Sep 17 00:00:00 2001 From: Graham Goh Date: Tue, 10 Dec 2024 01:20:04 +1100 Subject: [PATCH 43/55] fix: include OCR secrets as part of deployment.Environment (#15470) There are many cases where a changeset requires access to the OCR secrets and because it is not accessible via `deployment.Environment`, users are left no choice but to pass secrets as config in a changesets. By plumbing OCR secrets in `deployment.Environment`, user will no longer need to do the workaround. Update code to use OCR secrets from the env instead of from requests. JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1357 --- .changeset/hot-islands-dress.md | 5 ++++ .../keystone/src/88_gen_ocr3_config.go | 3 +- .../ccip/changeset/cs_active_candidate.go | 2 +- .../changeset/cs_active_candidate_test.go | 2 +- deployment/ccip/changeset/cs_add_chain.go | 6 ++-- .../ccip/changeset/cs_add_chain_test.go | 3 -- .../ccip/changeset/cs_initial_add_chain.go | 8 ++--- deployment/ccip/changeset/test_helpers.go | 1 - deployment/common/changeset/test_helpers.go | 1 + deployment/environment.go | 3 ++ deployment/environment/devenv/environment.go | 1 + deployment/environment/memory/environment.go | 2 ++ .../keystone/changeset/configure_contracts.go | 3 +- deployment/keystone/changeset/deploy_ocr3.go | 3 +- .../keystone/changeset/deploy_ocr3_test.go | 11 +++---- deployment/keystone/changeset/helpers_test.go | 17 +++++------ deployment/keystone/deploy.go | 10 ++++--- deployment/keystone/deploy_test.go | 8 ++--- deployment/keystone/ocr3config.go | 29 +++++++++---------- deployment/keystone/ocr3config_test.go | 3 +- .../testsetups/ccip/test_helpers.go | 1 - 21 files changed, 60 insertions(+), 62 deletions(-) create mode 100644 .changeset/hot-islands-dress.md diff --git a/.changeset/hot-islands-dress.md b/.changeset/hot-islands-dress.md new file mode 100644 index 00000000000..82e34ecf42b --- /dev/null +++ b/.changeset/hot-islands-dress.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal refactor: inject ocr secrets via env instead of config diff --git a/core/scripts/keystone/src/88_gen_ocr3_config.go b/core/scripts/keystone/src/88_gen_ocr3_config.go index f4292e9a1d4..707616b833b 100644 --- a/core/scripts/keystone/src/88_gen_ocr3_config.go +++ b/core/scripts/keystone/src/88_gen_ocr3_config.go @@ -13,9 +13,8 @@ func mustReadConfig(fileName string) (output ksdeploy.TopLevelConfigSource) { func generateOCR3Config(nodeList string, configFile string, chainID int64, pubKeysPath string) ksdeploy.OCR2OracleConfig { topLevelCfg := mustReadConfig(configFile) cfg := topLevelCfg.OracleConfig - cfg.OCRSecrets = deployment.XXXGenerateTestOCRSecrets() nca := downloadNodePubKeys(nodeList, chainID, pubKeysPath) - c, err := ksdeploy.GenerateOCR3Config(cfg, nca) + c, err := ksdeploy.GenerateOCR3Config(cfg, nca, deployment.XXXGenerateTestOCRSecrets()) helpers.PanicErr(err) return c } diff --git a/deployment/ccip/changeset/cs_active_candidate.go b/deployment/ccip/changeset/cs_active_candidate.go index b2aad3889ec..ecd87e2d399 100644 --- a/deployment/ccip/changeset/cs_active_candidate.go +++ b/deployment/ccip/changeset/cs_active_candidate.go @@ -137,7 +137,7 @@ func SetCandidatePluginChangeset( } newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - cfg.OCRSecrets, + e.OCRSecrets, state.Chains[cfg.NewChainSelector].OffRamp, e.Chains[cfg.NewChainSelector], nodes.NonBootstraps(), diff --git a/deployment/ccip/changeset/cs_active_candidate_test.go b/deployment/ccip/changeset/cs_active_candidate_test.go index 4bd0c9fd7a4..0fb29242794 100644 --- a/deployment/ccip/changeset/cs_active_candidate_test.go +++ b/deployment/ccip/changeset/cs_active_candidate_test.go @@ -144,7 +144,7 @@ func TestActiveCandidate(t *testing.T) { nil, ) ocr3ConfigMap, err := internal.BuildOCR3ConfigForCCIPHome( - deployment.XXXGenerateTestOCRSecrets(), + e.OCRSecrets, state.Chains[tenv.FeedChainSel].OffRamp, e.Chains[tenv.FeedChainSel], nodes.NonBootstraps(), diff --git a/deployment/ccip/changeset/cs_add_chain.go b/deployment/ccip/changeset/cs_add_chain.go index 9c19517260f..d589d16b779 100644 --- a/deployment/ccip/changeset/cs_add_chain.go +++ b/deployment/ccip/changeset/cs_add_chain.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chainconfig" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" @@ -142,7 +143,6 @@ type AddDonAndSetCandidateChangesetConfig struct { PluginType types.PluginType NodeIDs []string CCIPOCRParams CCIPOCRParams - OCRSecrets deployment.OCRSecrets } func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (deployment.Nodes, error) { @@ -191,7 +191,7 @@ func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, return nil, fmt.Errorf("invalid ccip ocr params: %w", err) } - if a.OCRSecrets.IsEmpty() { + if e.OCRSecrets.IsEmpty() { return nil, fmt.Errorf("OCR secrets must be set") } @@ -215,7 +215,7 @@ func AddDonAndSetCandidateChangeset( } newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - cfg.OCRSecrets, + e.OCRSecrets, state.Chains[cfg.NewChainSelector].OffRamp, e.Chains[cfg.NewChainSelector], nodes.NonBootstraps(), diff --git a/deployment/ccip/changeset/cs_add_chain_test.go b/deployment/ccip/changeset/cs_add_chain_test.go index f6e1c04c469..c8d872236c2 100644 --- a/deployment/ccip/changeset/cs_add_chain_test.go +++ b/deployment/ccip/changeset/cs_add_chain_test.go @@ -84,7 +84,6 @@ func TestAddChainInbound(t *testing.T) { HomeChainSel: e.HomeChainSel, FeedChainSel: e.FeedChainSel, ChainConfigByChain: chainConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), }) require.NoError(t, err) @@ -191,7 +190,6 @@ func TestAddChainInbound(t *testing.T) { NewChainSelector: newChain, PluginType: types.PluginTypeCCIPCommit, NodeIDs: nodeIDs, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), CCIPOCRParams: DefaultOCRParams( e.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), @@ -207,7 +205,6 @@ func TestAddChainInbound(t *testing.T) { NewChainSelector: newChain, PluginType: types.PluginTypeCCIPExec, NodeIDs: nodeIDs, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), CCIPOCRParams: DefaultOCRParams( e.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[newChain].LinkToken, state.Chains[newChain].Weth9), diff --git a/deployment/ccip/changeset/cs_initial_add_chain.go b/deployment/ccip/changeset/cs_initial_add_chain.go index d18116b8a74..13aee106e5a 100644 --- a/deployment/ccip/changeset/cs_initial_add_chain.go +++ b/deployment/ccip/changeset/cs_initial_add_chain.go @@ -76,7 +76,6 @@ type NewChainsConfig struct { // Common to all chains HomeChainSel uint64 FeedChainSel uint64 - OCRSecrets deployment.OCRSecrets // Per chain config ChainConfigByChain map[uint64]CCIPOCRParams } @@ -96,9 +95,6 @@ func (c NewChainsConfig) Validate() error { if err := deployment.IsValidChainSelector(c.FeedChainSel); err != nil { return fmt.Errorf("invalid feed chain selector: %d - %w", c.FeedChainSel, err) } - if c.OCRSecrets.IsEmpty() { - return fmt.Errorf("no OCR secrets provided") - } // Validate chain config for chain, cfg := range c.ChainConfigByChain { if err := cfg.Validate(); err != nil { @@ -166,7 +162,7 @@ func configureChain( e deployment.Environment, c NewChainsConfig, ) error { - if c.OCRSecrets.IsEmpty() { + if e.OCRSecrets.IsEmpty() { return fmt.Errorf("OCR secrets are empty") } nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) @@ -217,7 +213,7 @@ func configureChain( // For each chain, we create a DON on the home chain (2 OCR instances) if err := addDON( e.Logger, - c.OCRSecrets, + e.OCRSecrets, capReg, ccipHome, rmnHome.Address(), diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index 1ee8b0d0e42..49edb275526 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -379,7 +379,6 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, Config: NewChainsConfig{ HomeChainSel: e.HomeChainSel, FeedChainSel: e.FeedChainSel, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), ChainConfigByChain: chainConfigs, }, }, diff --git a/deployment/common/changeset/test_helpers.go b/deployment/common/changeset/test_helpers.go index 913b4544f30..2d5295282f5 100644 --- a/deployment/common/changeset/test_helpers.go +++ b/deployment/common/changeset/test_helpers.go @@ -90,6 +90,7 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelocksPerChain m Chains: e.Chains, NodeIDs: e.NodeIDs, Offchain: e.Offchain, + OCRSecrets: e.OCRSecrets, } } return currentEnv, nil diff --git a/deployment/environment.go b/deployment/environment.go index b4ac3a4f3f0..3d120adbbf1 100644 --- a/deployment/environment.go +++ b/deployment/environment.go @@ -98,6 +98,7 @@ type Environment struct { NodeIDs []string Offchain OffchainClient GetContext func() context.Context + OCRSecrets OCRSecrets } func NewEnvironment( @@ -108,6 +109,7 @@ func NewEnvironment( nodeIDs []string, offchain OffchainClient, ctx func() context.Context, + secrets OCRSecrets, ) *Environment { return &Environment{ Name: name, @@ -117,6 +119,7 @@ func NewEnvironment( NodeIDs: nodeIDs, Offchain: offchain, GetContext: ctx, + OCRSecrets: secrets, } } diff --git a/deployment/environment/devenv/environment.go b/deployment/environment/devenv/environment.go index 094eba99adf..121caea43bb 100644 --- a/deployment/environment/devenv/environment.go +++ b/deployment/environment/devenv/environment.go @@ -52,5 +52,6 @@ func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config Envir nodeIDs, offChain, ctx, + deployment.XXXGenerateTestOCRSecrets(), ), jd.don, nil } diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index 1693834c572..d6c80a92a44 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -142,6 +142,7 @@ func NewMemoryEnvironmentFromChainsNodes( nodeIDs, // Note these have the p2p_ prefix. NewMemoryJobClient(nodes), ctx, + deployment.XXXGenerateTestOCRSecrets(), ) } @@ -161,5 +162,6 @@ func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Lev nodeIDs, NewMemoryJobClient(nodes), func() context.Context { return tests.Context(t) }, + deployment.XXXGenerateTestOCRSecrets(), ) } diff --git a/deployment/keystone/changeset/configure_contracts.go b/deployment/keystone/changeset/configure_contracts.go index 17635a42ed1..3a92782e12b 100644 --- a/deployment/keystone/changeset/configure_contracts.go +++ b/deployment/keystone/changeset/configure_contracts.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) @@ -14,7 +15,7 @@ var _ deployment.ChangeSet[InitialContractsCfg] = ConfigureInitialContractsChang type InitialContractsCfg struct { RegistryChainSel uint64 Dons []kslib.DonCapabilities - OCR3Config *kslib.OracleConfigWithSecrets + OCR3Config *kslib.OracleConfig } func ConfigureInitialContractsChangeset(e deployment.Environment, cfg InitialContractsCfg) (deployment.ChangesetOutput, error) { diff --git a/deployment/keystone/changeset/deploy_ocr3.go b/deployment/keystone/changeset/deploy_ocr3.go index fdf51e644be..0ce3d02844b 100644 --- a/deployment/keystone/changeset/deploy_ocr3.go +++ b/deployment/keystone/changeset/deploy_ocr3.go @@ -6,6 +6,7 @@ import ( "io" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) @@ -33,7 +34,7 @@ var _ deployment.ChangeSet[ConfigureOCR3Config] = ConfigureOCR3Contract type ConfigureOCR3Config struct { ChainSel uint64 NodeIDs []string - OCR3Config *kslib.OracleConfigWithSecrets + OCR3Config *kslib.OracleConfig DryRun bool WriteGeneratedConfig io.Writer // if not nil, write the generated config to this writer as JSON [OCR2OracleConfig] diff --git a/deployment/keystone/changeset/deploy_ocr3_test.go b/deployment/keystone/changeset/deploy_ocr3_test.go index 0d49af68823..0e5fea6b7c6 100644 --- a/deployment/keystone/changeset/deploy_ocr3_test.go +++ b/deployment/keystone/changeset/deploy_ocr3_test.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" @@ -48,12 +48,9 @@ func TestConfigureOCR3(t *testing.T) { t.Parallel() lggr := logger.Test(t) - c := kslib.OracleConfigWithSecrets{ - OracleConfig: kslib.OracleConfig{ - MaxFaultyOracles: 1, - DeltaProgressMillis: 12345, - }, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + c := kslib.OracleConfig{ + MaxFaultyOracles: 1, + DeltaProgressMillis: 12345, } t.Run("no mcms", func(t *testing.T) { diff --git a/deployment/keystone/changeset/helpers_test.go b/deployment/keystone/changeset/helpers_test.go index d4435d8f7a6..faf112867ce 100644 --- a/deployment/keystone/changeset/helpers_test.go +++ b/deployment/keystone/changeset/helpers_test.go @@ -7,16 +7,19 @@ import ( "encoding/hex" "errors" "fmt" + "math" "math/big" "sort" - - "math" "testing" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink/deployment" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -26,9 +29,6 @@ import ( kschangeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" ) func TestSetupTestEnv(t *testing.T) { @@ -215,11 +215,8 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { err = env.ExistingAddresses.Merge(e.ExistingAddresses) require.NoError(t, err) - var ocr3Config = keystone.OracleConfigWithSecrets{ - OracleConfig: keystone.OracleConfig{ - MaxFaultyOracles: len(wfNodes) / 3, - }, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + var ocr3Config = keystone.OracleConfig{ + MaxFaultyOracles: len(wfNodes) / 3, } var allDons = []keystone.DonCapabilities{wfDon, cwDon, assetDon} diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index da277bc3497..9bd291e9c1e 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -44,8 +44,8 @@ type ConfigureContractsRequest struct { RegistryChainSel uint64 Env *deployment.Environment - Dons []DonCapabilities // externally sourced based on the environment - OCR3Config *OracleConfigWithSecrets // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config + Dons []DonCapabilities // externally sourced based on the environment + OCR3Config *OracleConfig // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config // TODO rm this option; unused DoContractDeploy bool // if false, the contracts are assumed to be deployed and the address book is used @@ -304,7 +304,7 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon // Depreciated: use changeset.ConfigureOCR3Contract instead // ocr3 contract on the registry chain for the wf dons -func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, cfg *OracleConfigWithSecrets) error { +func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, cfg *OracleConfig) error { registryChain, ok := env.Chains[chainSel] if !ok { return fmt.Errorf("chain %d not found in environment", chainSel) @@ -338,6 +338,7 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] contract: contract, nodes: don.Nodes, contractSet: &contracts, + ocrSecrets: env.OCRSecrets, }) if err != nil { return fmt.Errorf("failed to configure OCR3 contract for don %s: %w", don.Name, err) @@ -354,7 +355,7 @@ type ConfigureOCR3Resp struct { type ConfigureOCR3Config struct { ChainSel uint64 NodeIDs []string - OCR3Config *OracleConfigWithSecrets + OCR3Config *OracleConfig DryRun bool UseMCMS bool @@ -398,6 +399,7 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C dryRun: cfg.DryRun, contractSet: &contracts, useMCMS: cfg.UseMCMS, + ocrSecrets: env.OCRSecrets, }) if err != nil { return nil, err diff --git a/deployment/keystone/deploy_test.go b/deployment/keystone/deploy_test.go index 715f8b7aba7..eb167ed60fb 100644 --- a/deployment/keystone/deploy_test.go +++ b/deployment/keystone/deploy_test.go @@ -107,6 +107,7 @@ func TestDeployCLO(t *testing.T) { Offchain: clo.NewJobClient(lggr, clo.JobClientConfig{Nops: allNops}), Chains: allChains, Logger: lggr, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), } // assume that all the nodes in the provided input nops are part of the don for _, nop := range allNops { @@ -119,11 +120,8 @@ func TestDeployCLO(t *testing.T) { registryChainSel, err := chainsel.SelectorFromChainId(11155111) require.NoError(t, err) - var ocr3Config = keystone.OracleConfigWithSecrets{ - OracleConfig: keystone.OracleConfig{ - MaxFaultyOracles: len(wfNops) / 3, - }, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + var ocr3Config = keystone.OracleConfig{ + MaxFaultyOracles: len(wfNops) / 3, } ctx := tests.Context(t) diff --git a/deployment/keystone/ocr3config.go b/deployment/keystone/ocr3config.go index c4f8714b113..ccd738636ed 100644 --- a/deployment/keystone/ocr3config.go +++ b/deployment/keystone/ocr3config.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" @@ -30,12 +31,9 @@ import ( ) type TopLevelConfigSource struct { - OracleConfig OracleConfigWithSecrets -} -type OracleConfigWithSecrets struct { - OracleConfig - deployment.OCRSecrets `json:"-" toml:"-"` // don't spill secrets + OracleConfig OracleConfig } + type OracleConfig struct { MaxQueryLengthBytes uint32 MaxObservationLengthBytes uint32 @@ -151,10 +149,10 @@ func (c *OCR2OracleConfig) UnmarshalJSON(data []byte) error { return nil } -func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (OCR2OracleConfig, error) { +func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCRSecrets) (OCR2OracleConfig, error) { onchainPubKeys := [][]byte{} allPubKeys := map[string]any{} - if cfg.OCRSecrets.IsEmpty() { + if secrets.IsEmpty() { return OCR2OracleConfig{}, errors.New("OCRSecrets is required") } for _, n := range nca { @@ -236,8 +234,8 @@ func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (OCR2Oracle } signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsDeterministic( - cfg.EphemeralSk, - cfg.SharedSecret, + secrets.EphemeralSk, + secrets.SharedSecret, time.Duration(cfg.DeltaProgressMillis)*time.Millisecond, time.Duration(cfg.DeltaResendMillis)*time.Millisecond, time.Duration(cfg.DeltaInitialMillis)*time.Millisecond, @@ -284,11 +282,12 @@ func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (OCR2Oracle } type configureOCR3Request struct { - cfg *OracleConfigWithSecrets - chain deployment.Chain - contract *kocr3.OCR3Capability - nodes []deployment.Node - dryRun bool + cfg *OracleConfig + chain deployment.Chain + contract *kocr3.OCR3Capability + nodes []deployment.Node + dryRun bool + ocrSecrets deployment.OCRSecrets useMCMS bool contractSet *ContractSet @@ -296,7 +295,7 @@ type configureOCR3Request struct { func (r configureOCR3Request) generateOCR3Config() (OCR2OracleConfig, error) { nks := makeNodeKeysSlice(r.nodes, r.chain.Selector) - return GenerateOCR3Config(*r.cfg, nks) + return GenerateOCR3Config(*r.cfg, nks, r.ocrSecrets) } type configureOCR3Response struct { diff --git a/deployment/keystone/ocr3config_test.go b/deployment/keystone/ocr3config_test.go index daf869d77e0..55fa16af68c 100644 --- a/deployment/keystone/ocr3config_test.go +++ b/deployment/keystone/ocr3config_test.go @@ -85,11 +85,12 @@ func Test_configureOCR3Request_generateOCR3Config(t *testing.T) { err := json.Unmarshal([]byte(ocr3Cfg), &cfg) require.NoError(t, err) r := configureOCR3Request{ - cfg: &OracleConfigWithSecrets{OracleConfig: cfg, OCRSecrets: deployment.XXXGenerateTestOCRSecrets()}, + cfg: &cfg, nodes: nodes, chain: deployment.Chain{ Selector: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, }, + ocrSecrets: deployment.XXXGenerateTestOCRSecrets(), } got, err := r.generateOCR3Config() require.NoError(t, err) diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/testsetups/ccip/test_helpers.go index 4d51093d419..3112d738869 100644 --- a/integration-tests/testsetups/ccip/test_helpers.go +++ b/integration-tests/testsetups/ccip/test_helpers.go @@ -244,7 +244,6 @@ func NewLocalDevEnvironment( Config: changeset.NewChainsConfig{ HomeChainSel: homeChainSel, FeedChainSel: feedSel, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), ChainConfigByChain: chainConfigs, }, }, From 398e5834cbdbb1258c854d397599501cf803361f Mon Sep 17 00:00:00 2001 From: Makram Date: Mon, 9 Dec 2024 17:04:17 +0200 Subject: [PATCH 44/55] deployment/ccip/changeset: rm TestInitialDeploy (#15568) This test is now a relic as we have more granular test cases in other test files. --- .github/e2e-tests.yml | 13 --- .../ccip/changeset/initial_deploy_test.go | 82 ------------------ deployment/environment/devenv/README.md | 12 +-- integration-tests/smoke/ccip/ccip_test.go | 83 ------------------- 4 files changed, 6 insertions(+), 184 deletions(-) delete mode 100644 deployment/ccip/changeset/initial_deploy_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_test.go diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index d40d375f860..ebe5b62a709 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -935,19 +935,6 @@ runner-test-matrix: # START: CCIPv1.6 tests - - id: smoke/ccip/ccip_test.go:* - path: integration-tests/smoke/ccip/ccip_test.go - test_env_type: docker - runs_on: ubuntu-latest - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_test.go -timeout 25m -test.parallel=2 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - - id: smoke/ccip/ccip_message_limitations_test.go:* path: integration-tests/smoke/ccip/ccip_message_limitations_test.go test_env_type: docker diff --git a/deployment/ccip/changeset/initial_deploy_test.go b/deployment/ccip/changeset/initial_deploy_test.go deleted file mode 100644 index 97e516c8f94..00000000000 --- a/deployment/ccip/changeset/initial_deploy_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/logger" - - "github.com/stretchr/testify/require" -) - -func TestInitialDeploy(t *testing.T) { - lggr := logger.TestLogger(t) - tenv := NewMemoryEnvironmentWithJobsAndContracts(t, lggr, memory.MemoryEnvironmentConfig{ - Chains: 3, - Nodes: 4, - Bootstraps: 1, - NumOfUsersPerChain: 1, - }, nil) - e := tenv.Env - state, err := LoadOnchainState(e) - require.NoError(t, err) - // Add all lanes - require.NoError(t, AddLanesForAll(e, state)) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNum := make(map[SourceDestPair]uint64) - expectedSeqNumExec := make(map[SourceDestPair][]uint64) - - for src := range e.Chains { - for dest, destChain := range e.Chains { - if src == dest { - continue - } - latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[dest] = &block - require.GreaterOrEqual(t, len(tenv.Users[src]), 1) - msgSentEvent, err := DoSendRequest(t, e, state, - WithTestRouter(false), - WithSourceChain(src), - WithDestChain(dest), - WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), - Data: []byte("hello"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }), - WithSender(tenv.Users[src][0]), - ) - require.NoError(t, err) - expectedSeqNum[SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = []uint64{msgSentEvent.SequenceNumber} - } - } - - // Wait for all commit reports to land. - ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) - - // Confirm token and gas prices are updated - ConfirmTokenPriceUpdatedForAll(t, e, state, startBlocks, - DefaultInitialPrices.LinkPrice, DefaultInitialPrices.WethPrice) - // TODO: Fix gas prices? - //ConfirmGasPriceUpdatedForAll(t, e, state, startBlocks) - // - //// Wait for all exec reports to land - ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks) -} diff --git a/deployment/environment/devenv/README.md b/deployment/environment/devenv/README.md index f5e11f0475e..e6f5bc1b5ac 100644 --- a/deployment/environment/devenv/README.md +++ b/deployment/environment/devenv/README.md @@ -14,11 +14,11 @@ Pre-requisites: #### Setting Up Testconfig with Simulated Private Ethereum Network -To run tests (e.g., [ccip-test](../../integration-tests/smoke/ccip_test.go)), -you need to set up the testconfig following the [testconfig setup instructions](../../integration-tests/testconfig/README.md). +To run tests (e.g., [ccip-test](../../../integration-tests/ccip-tests/smoke/ccip_test.go)), +you need to set up the testconfig following the [testconfig setup instructions](../../../integration-tests/testconfig/README.md). The testconfig specifies the details of the different configurations to set up the environment and run the tests. -Generally, tests are run with the [default](../../integration-tests/testconfig/default.toml) config unless overridden by product-specific config. -For example, the [ccip-test](../../integration-tests/smoke/ccip_test.go) uses [ccip.toml](../../integration-tests/testconfig/ccip/ccip.toml) to specify +Generally, tests are run with the [default](../../../integration-tests/testconfig/default.toml) config unless overridden by product-specific config. +For example, the [ccip-test](../../../integration-tests/ccip-tests/smoke/ccip_test.go) uses [ccip.toml](../../../integration-tests/testconfig/ccip/ccip.toml) to specify CCIP-specific test environment details. There are additional secret configuration parameters required by the `devenv` environment that are not stored in the testconfig. @@ -37,7 +37,7 @@ By default, tests are run with private Ethereum network containers set up in the the Chainlink nodes and job distributor. To run tests against existing testnet/mainnet, set the `selected_network` field in the testconfig with the specific network names. -For example, if running [ccip-smoke](../../integration-tests/smoke/ccip_test.go) tests with Sepolia, Avax, and Binance testnets, +For example, if running [ccip-smoke](../../../integration-tests/ccip-tests/smoke/ccip_test.go) tests with Sepolia, Avax, and Binance testnets, copy the contents of [sepolia_avax_binance.toml](../../integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml) to the `overrides.toml` file. @@ -48,4 +48,4 @@ provide necessary secrets applicable to the network you are running the tests ag - `E2E_TEST__RPC_HTTP_URL_` - `E2E_TEST__RPC_WS_URL_` -Now you are all set to run the tests with the existing testnet/mainnet. \ No newline at end of file +Now you are all set to run the tests with the existing testnet/mainnet. diff --git a/integration-tests/smoke/ccip/ccip_test.go b/integration-tests/smoke/ccip/ccip_test.go deleted file mode 100644 index ca30c9281c4..00000000000 --- a/integration-tests/smoke/ccip/ccip_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package smoke - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestInitialDeployOnLocal(t *testing.T) { - t.Parallel() - lggr := logger.TestLogger(t) - config := &changeset.TestConfigs{} - tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr, config) - e := tenv.Env - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - - // Add all lanes - require.NoError(t, changeset.AddLanesForAll(e, state)) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - for src := range e.Chains { - for dest, destChain := range e.Chains { - if src == dest { - continue - } - latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[dest] = &block - require.GreaterOrEqual(t, len(tenv.Users[src]), 2) - msgSentEvent, err := changeset.DoSendRequest(t, e, state, - changeset.WithSender(tenv.Users[src][1]), - changeset.WithSourceChain(src), - changeset.WithDestChain(dest), - changeset.WithTestRouter(false), - changeset.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - })) - require.NoError(t, err) - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ - SourceChainSelector: src, - DestChainSelector: dest, - }] = []uint64{msgSentEvent.SequenceNumber} - } - } - - // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) - - // After commit is reported on all chains, token prices should be updated in FeeQuoter. - for dest := range e.Chains { - linkAddress := state.Chains[dest].LinkToken.Address() - feeQuoter := state.Chains[dest].FeeQuoter - timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) - require.NoError(t, err) - require.Equal(t, changeset.MockLinkPrice, timestampedPrice.Value) - } - - // Wait for all exec reports to land - changeset.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks) - - // TODO: Apply the proposal. -} From b6bf8f2bdd4d6613ec7e29748f42fa229fdd065c Mon Sep 17 00:00:00 2001 From: Makram Date: Mon, 9 Dec 2024 17:51:53 +0200 Subject: [PATCH 45/55] core/services/ocr2/plugins/ccip: skip racey TestIntegration_CCIP (#15569) Also delete TestIntegration_legacy_CCIP since v1.5 has been live for a bit. --- .../plugins/ccip/integration_legacy_test.go | 594 ------------------ .../ocr2/plugins/ccip/integration_test.go | 2 + 2 files changed, 2 insertions(+), 594 deletions(-) delete mode 100644 core/services/ocr2/plugins/ccip/integration_legacy_test.go diff --git a/core/services/ocr2/plugins/ccip/integration_legacy_test.go b/core/services/ocr2/plugins/ccip/integration_legacy_test.go deleted file mode 100644 index 12a117d47c4..00000000000 --- a/core/services/ocr2/plugins/ccip/integration_legacy_test.go +++ /dev/null @@ -1,594 +0,0 @@ -package ccip_test - -import ( - "context" - "encoding/json" - "fmt" - "math/big" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - evm_2_evm_onramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" - testhelpers_new "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" - testhelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0" -) - -func TestIntegration_legacy_CCIP(t *testing.T) { - // Run the batches of tests for both pipeline and dynamic price getter setups. - // We will remove the pipeline batch once the feature is deleted from the code. - tests := []struct { - name string - withPipeline bool - }{ - { - name: "with pipeline", - withPipeline: true, - }, - { - name: "with dynamic price getter", - withPipeline: false, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - ccipTH := testhelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) - - tokenPricesUSDPipeline := "" - priceGetterConfigJson := "" - - if test.withPipeline { - // Set up a test pipeline. - testPricePipeline, linkUSD, ethUSD := ccipTH.CreatePricesPipeline(t) - defer linkUSD.Close() - defer ethUSD.Close() - tokenPricesUSDPipeline = testPricePipeline - } else { - // Set up a test price getter. - // Set up the aggregators here to avoid modifying ccipTH. - aggSrcNatAddr, _, aggSrcNat, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Source.User, ccipTH.Source.Chain.Client(), 18, big.NewInt(2e18)) - require.NoError(t, err) - _, err = aggSrcNat.UpdateRoundData(ccipTH.Source.User, big.NewInt(50), big.NewInt(17000000), big.NewInt(1000), big.NewInt(1000)) - require.NoError(t, err) - ccipTH.Source.Chain.Commit() - - aggDstLnkAddr, _, aggDstLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Dest.User, ccipTH.Dest.Chain.Client(), 18, big.NewInt(3e18)) - require.NoError(t, err) - ccipTH.Dest.Chain.Commit() - _, err = aggDstLnk.UpdateRoundData(ccipTH.Dest.User, big.NewInt(50), big.NewInt(8000000), big.NewInt(1000), big.NewInt(1000)) - require.NoError(t, err) - ccipTH.Dest.Chain.Commit() - - priceGetterConfig := config.DynamicPriceGetterConfig{ - AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ - ccipTH.Source.WrappedNative.Address(): { - ChainID: ccipTH.Source.ChainID, - AggregatorContractAddress: aggSrcNatAddr, - }, - ccipTH.Dest.LinkToken.Address(): { - ChainID: ccipTH.Dest.ChainID, - AggregatorContractAddress: aggDstLnkAddr, - }, - ccipTH.Dest.WrappedNative.Address(): { - ChainID: ccipTH.Dest.ChainID, - AggregatorContractAddress: aggDstLnkAddr, - }, - }, - StaticPrices: map[common.Address]config.StaticPriceConfig{}, - } - priceGetterConfigBytes, err := json.MarshalIndent(priceGetterConfig, "", " ") - require.NoError(t, err) - priceGetterConfigJson = string(priceGetterConfigBytes) - } - - jobParams := ccipTH.SetUpNodesAndJobs(t, tokenPricesUSDPipeline, priceGetterConfigJson, "") - - currentSeqNum := 1 - - t.Run("single", func(t *testing.T) { - tokenAmount := big.NewInt(500000003) // prime number - gasLimit := big.NewInt(200_003) // prime number - - extraArgs, err2 := testhelpers.GetEVMExtraArgsV1(gasLimit, false) - require.NoError(t, err2) - - sourceBalances, err2 := testhelpers.GetBalances(t, []testhelpers.BalanceReq{ - {Name: testhelpers.SourcePool, Addr: ccipTH.Source.LinkTokenPool.Address(), Getter: ccipTH.GetSourceLinkBalance}, - {Name: testhelpers.OnRamp, Addr: ccipTH.Source.OnRamp.Address(), Getter: ccipTH.GetSourceLinkBalance}, - {Name: testhelpers.SourceRouter, Addr: ccipTH.Source.Router.Address(), Getter: ccipTH.GetSourceLinkBalance}, - {Name: testhelpers.SourcePriceRegistry, Addr: ccipTH.Source.PriceRegistry.Address(), Getter: ccipTH.GetSourceLinkBalance}, - }) - require.NoError(t, err2) - destBalances, err2 := testhelpers.GetBalances(t, []testhelpers.BalanceReq{ - {Name: testhelpers.Receiver, Addr: ccipTH.Dest.Receivers[0].Receiver.Address(), Getter: ccipTH.GetDestLinkBalance}, - {Name: testhelpers.DestPool, Addr: ccipTH.Dest.LinkTokenPool.Address(), Getter: ccipTH.GetDestLinkBalance}, - {Name: testhelpers.OffRamp, Addr: ccipTH.Dest.OffRamp.Address(), Getter: ccipTH.GetDestLinkBalance}, - }) - require.NoError(t, err2) - - ccipTH.Source.User.Value = tokenAmount - _, err2 = ccipTH.Source.WrappedNative.Deposit(ccipTH.Source.User) - require.NoError(t, err2) - ccipTH.Source.Chain.Commit() - ccipTH.Source.User.Value = nil - - msg := router.ClientEVM2AnyMessage{ - Receiver: testhelpers.MustEncodeAddress(t, ccipTH.Dest.Receivers[0].Receiver.Address()), - Data: []byte("hello"), - TokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: ccipTH.Source.LinkToken.Address(), - Amount: tokenAmount, - }, - { - Token: ccipTH.Source.WrappedNative.Address(), - Amount: tokenAmount, - }, - }, - FeeToken: ccipTH.Source.LinkToken.Address(), - ExtraArgs: extraArgs, - } - fee, err2 := ccipTH.Source.Router.GetFee(nil, testhelpers.DestChainSelector, msg) - require.NoError(t, err2) - // Currently no overhead and 10gwei dest gas price. So fee is simply (gasLimit * gasPrice)* link/native - // require.Equal(t, new(big.Int).Mul(gasLimit, gasPrice).String(), fee.String()) - // Approve the fee amount + the token amount - _, err2 = ccipTH.Source.LinkToken.Approve(ccipTH.Source.User, ccipTH.Source.Router.Address(), new(big.Int).Add(fee, tokenAmount)) - require.NoError(t, err2) - ccipTH.Source.Chain.Commit() - _, err2 = ccipTH.Source.WrappedNative.Approve(ccipTH.Source.User, ccipTH.Source.Router.Address(), tokenAmount) - require.NoError(t, err2) - ccipTH.Source.Chain.Commit() - - ccipTH.SendRequest(t, msg) - // Should eventually see this executed. - ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum) - ccipTH.EventuallyReportCommitted(t, currentSeqNum) - - executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum) - assert.Len(t, executionLogs, 1) - ccipTH.AssertExecState(t, executionLogs[0], testhelpers.ExecutionStateSuccess) - - // Asserts - // 1) The total pool input == total pool output - // 2) Pool flow equals tokens sent - // 3) Sent tokens arrive at the receiver - ccipTH.AssertBalances(t, []testhelpers.BalanceAssertion{ - { - Name: testhelpers.SourcePool, - Address: ccipTH.Source.LinkTokenPool.Address(), - Expected: testhelpers.MustAddBigInt(sourceBalances[testhelpers.SourcePool], tokenAmount.String()).String(), - Getter: ccipTH.GetSourceLinkBalance, - }, - { - Name: testhelpers.SourcePriceRegistry, - Address: ccipTH.Source.PriceRegistry.Address(), - Expected: sourceBalances[testhelpers.SourcePriceRegistry].String(), - Getter: ccipTH.GetSourceLinkBalance, - }, - { - // Fees end up in the onramp. - Name: testhelpers.OnRamp, - Address: ccipTH.Source.OnRamp.Address(), - Expected: testhelpers.MustAddBigInt(sourceBalances[testhelpers.SourcePriceRegistry], fee.String()).String(), - Getter: ccipTH.GetSourceLinkBalance, - }, - { - Name: testhelpers.SourceRouter, - Address: ccipTH.Source.Router.Address(), - Expected: sourceBalances[testhelpers.SourceRouter].String(), - Getter: ccipTH.GetSourceLinkBalance, - }, - { - Name: testhelpers.Receiver, - Address: ccipTH.Dest.Receivers[0].Receiver.Address(), - Expected: testhelpers.MustAddBigInt(destBalances[testhelpers.Receiver], tokenAmount.String()).String(), - Getter: ccipTH.GetDestLinkBalance, - }, - { - Name: testhelpers.DestPool, - Address: ccipTH.Dest.LinkTokenPool.Address(), - Expected: testhelpers.MustSubBigInt(destBalances[testhelpers.DestPool], tokenAmount.String()).String(), - Getter: ccipTH.GetDestLinkBalance, - }, - { - Name: testhelpers.OffRamp, - Address: ccipTH.Dest.OffRamp.Address(), - Expected: destBalances[testhelpers.OffRamp].String(), - Getter: ccipTH.GetDestLinkBalance, - }, - }) - currentSeqNum++ - }) - - t.Run("multiple batches", func(t *testing.T) { - tokenAmount := big.NewInt(500000003) - gasLimit := big.NewInt(250_000) - - var txs []*gethtypes.Transaction - // Enough to require batched executions as gasLimit per tx is 250k -> 500k -> 750k .... - // The actual gas usage of executing 15 messages is higher than the gas limit for - // a single tx. This means that when batching is turned off, and we simply include - // all txs without checking gas, this also fails. - n := 15 - for i := 0; i < n; i++ { - txGasLimit := new(big.Int).Mul(gasLimit, big.NewInt(int64(i+1))) - extraArgs, err2 := testhelpers.GetEVMExtraArgsV1(txGasLimit, false) - require.NoError(t, err2) - msg := router.ClientEVM2AnyMessage{ - Receiver: testhelpers.MustEncodeAddress(t, ccipTH.Dest.Receivers[0].Receiver.Address()), - Data: []byte("hello"), - TokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: ccipTH.Source.LinkToken.Address(), - Amount: tokenAmount, - }, - }, - FeeToken: ccipTH.Source.LinkToken.Address(), - ExtraArgs: extraArgs, - } - fee, err2 := ccipTH.Source.Router.GetFee(nil, testhelpers.DestChainSelector, msg) - require.NoError(t, err2) - // Currently no overhead and 1gwei dest gas price. So fee is simply gasLimit * gasPrice. - // require.Equal(t, new(big.Int).Mul(txGasLimit, gasPrice).String(), fee.String()) - // Approve the fee amount + the token amount - _, err2 = ccipTH.Source.LinkToken.Approve(ccipTH.Source.User, ccipTH.Source.Router.Address(), new(big.Int).Add(fee, tokenAmount)) - require.NoError(t, err2) - ccipTH.Source.Chain.Commit() - tx, err2 := ccipTH.Source.Router.CcipSend(ccipTH.Source.User, ccipTH.Dest.ChainSelector, msg) - require.NoError(t, err2) - ccipTH.Source.Chain.Commit() - txs = append(txs, tx) - } - - // Send a batch of requests in a single block - testhelpers_new.ConfirmTxs(t, txs, ccipTH.Source.Chain) - for i := 0; i < n; i++ { - ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum+i) - } - // Should see a report with the full range - ccipTH.EventuallyReportCommitted(t, currentSeqNum+n-1) - // Should all be executed - executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum+n-1) - for _, execLog := range executionLogs { - ccipTH.AssertExecState(t, execLog, testhelpers.ExecutionStateSuccess) - } - - currentSeqNum += n - }) - - // Deploy new on ramp,Commit store,off ramp - // Delete v1 jobs - // Send a number of requests - // Upgrade the router with new contracts - // create new jobs - // Verify all pending requests are sent after the contracts are upgraded - t.Run("upgrade contracts and verify requests can be sent with upgraded contract", func(t *testing.T) { - ctx := testutils.Context(t) - gasLimit := big.NewInt(200_003) // prime number - tokenAmount := big.NewInt(100) - commitStoreV1 := ccipTH.Dest.CommitStore - offRampV1 := ccipTH.Dest.OffRamp - onRampV1 := ccipTH.Source.OnRamp - // deploy v2 contracts - ccipTH.DeployNewOnRamp(t) - ccipTH.DeployNewCommitStore(t) - ccipTH.DeployNewOffRamp(t) - - // send a request as the v2 contracts are not enabled in router it should route through the v1 contracts - t.Logf("sending request for seqnum %d", currentSeqNum) - ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) - ccipTH.Source.Chain.Commit() - ccipTH.Dest.Chain.Commit() - t.Logf("verifying seqnum %d on previous onRamp %s", currentSeqNum, onRampV1.Address().Hex()) - ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum, onRampV1.Address()) - ccipTH.EventuallyReportCommitted(t, currentSeqNum, commitStoreV1.Address()) - executionLog := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum, offRampV1.Address()) - ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess, offRampV1.Address()) - - nonceAtOnRampV1, err := onRampV1.GetSenderNonce(nil, ccipTH.Source.User.From) - require.NoError(t, err, "getting nonce from onRamp") - require.Equal(t, currentSeqNum, int(nonceAtOnRampV1)) - nonceAtOffRampV1, err := offRampV1.GetSenderNonce(nil, ccipTH.Source.User.From) - require.NoError(t, err, "getting nonce from offRamp") - require.Equal(t, currentSeqNum, int(nonceAtOffRampV1)) - - // enable the newly deployed contracts - newConfigBlock, err := ccipTH.Dest.Chain.Client().BlockNumber(ctx) - require.NoError(t, err) - ccipTH.EnableOnRamp(t) - ccipTH.EnableCommitStore(t) - ccipTH.EnableOffRamp(t) - srcStartBlock, err := ccipTH.Source.Chain.Client().BlockNumber(ctx) - require.NoError(t, err) - - // send a number of requests, the requests should not be delivered yet as the previous contracts are not configured - // with the router anymore - startSeq := 1 - noOfRequests := 5 - endSeqNum := startSeq + noOfRequests - for i := startSeq; i <= endSeqNum; i++ { - t.Logf("sending request for seqnum %d", i) - ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) - ccipTH.Source.Chain.Commit() - ccipTH.Dest.Chain.Commit() - ccipTH.EventuallySendRequested(t, uint64(i)) - } - - // delete v1 jobs - for _, node := range ccipTH.Nodes { - id := node.FindJobIDForContract(t, commitStoreV1.Address()) - require.Greater(t, id, int32(0)) - t.Logf("deleting job %d", id) - err = node.App.DeleteJob(context.Background(), id) - require.NoError(t, err) - id = node.FindJobIDForContract(t, offRampV1.Address()) - require.Greater(t, id, int32(0)) - t.Logf("deleting job %d", id) - err = node.App.DeleteJob(context.Background(), id) - require.NoError(t, err) - } - - // Commit on both chains to reach Finality - ccipTH.Source.Chain.Commit() - ccipTH.Dest.Chain.Commit() - - // create new jobs - jobParams = ccipTH.NewCCIPJobSpecParams(tokenPricesUSDPipeline, priceGetterConfigJson, newConfigBlock, "") - jobParams.Version = "v2" - jobParams.SourceStartBlock = srcStartBlock - ccipTH.AddAllJobs(t, jobParams) - committedSeqNum := uint64(0) - // Now the requests should be delivered - for i := startSeq; i <= endSeqNum; i++ { - t.Logf("verifying seqnum %d", i) - ccipTH.AllNodesHaveReqSeqNum(t, i) - if committedSeqNum < uint64(i+1) { - committedSeqNum = ccipTH.EventuallyReportCommitted(t, i) - } - ccipTH.EventuallyExecutionStateChangedToSuccess(t, []uint64{uint64(i)}, uint64(newConfigBlock)) - } - - // nonces should be correctly synced from v1 contracts for the sender - nonceAtOnRampV2, err := ccipTH.Source.OnRamp.GetSenderNonce(nil, ccipTH.Source.User.From) - require.NoError(t, err, "getting nonce from onRamp") - nonceAtOffRampV2, err := ccipTH.Dest.OffRamp.GetSenderNonce(nil, ccipTH.Source.User.From) - require.NoError(t, err, "getting nonce from offRamp") - require.Equal(t, nonceAtOnRampV1+uint64(noOfRequests)+1, nonceAtOnRampV2, "nonce should be synced from v1 onRamps") - require.Equal(t, nonceAtOffRampV1+uint64(noOfRequests)+1, nonceAtOffRampV2, "nonce should be synced from v1 offRamps") - currentSeqNum = endSeqNum + 1 - }) - - t.Run("pay nops", func(t *testing.T) { - linkToTransferToOnRamp := big.NewInt(1e18) - - // transfer some link to onramp to pay the nops - _, err := ccipTH.Source.LinkToken.Transfer(ccipTH.Source.User, ccipTH.Source.OnRamp.Address(), linkToTransferToOnRamp) - require.NoError(t, err) - ccipTH.Source.Chain.Commit() - - srcBalReq := []testhelpers.BalanceReq{ - { - Name: testhelpers.Sender, - Addr: ccipTH.Source.User.From, - Getter: ccipTH.GetSourceWrappedTokenBalance, - }, - { - Name: testhelpers.OnRampNative, - Addr: ccipTH.Source.OnRamp.Address(), - Getter: ccipTH.GetSourceWrappedTokenBalance, - }, - { - Name: testhelpers.OnRamp, - Addr: ccipTH.Source.OnRamp.Address(), - Getter: ccipTH.GetSourceLinkBalance, - }, - { - Name: testhelpers.SourceRouter, - Addr: ccipTH.Source.Router.Address(), - Getter: ccipTH.GetSourceWrappedTokenBalance, - }, - } - - var nopsAndWeights []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight - var totalWeight uint16 - nodes := ccipTH.Nodes - for i := range nodes { - // For now set the transmitter addresses to be the same as the payee addresses - nodes[i].PaymentReceiver = nodes[i].Transmitter - nopsAndWeights = append(nopsAndWeights, evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{ - Nop: nodes[i].PaymentReceiver, - Weight: 5, - }) - totalWeight += 5 - srcBalReq = append(srcBalReq, testhelpers.BalanceReq{ - Name: fmt.Sprintf("node %d", i), - Addr: nodes[i].PaymentReceiver, - Getter: ccipTH.GetSourceLinkBalance, - }) - } - srcBalances, err := testhelpers.GetBalances(t, srcBalReq) - require.NoError(t, err) - - // set nops on the onramp - ccipTH.SetNopsOnRamp(t, nopsAndWeights) - - // send a message - extraArgs, err := testhelpers.GetEVMExtraArgsV1(big.NewInt(200_000), true) - require.NoError(t, err) - - // FeeToken is empty, indicating it should use native token - msg := router.ClientEVM2AnyMessage{ - Receiver: testhelpers.MustEncodeAddress(t, ccipTH.Dest.Receivers[1].Receiver.Address()), - Data: []byte("hello"), - TokenAmounts: []router.ClientEVMTokenAmount{}, - ExtraArgs: extraArgs, - FeeToken: common.Address{}, - } - fee, err := ccipTH.Source.Router.GetFee(nil, testhelpers.DestChainSelector, msg) - require.NoError(t, err) - - // verify message is sent - ccipTH.Source.User.Value = fee - ccipTH.SendRequest(t, msg) - ccipTH.Source.User.Value = nil - ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum) - ccipTH.EventuallyReportCommitted(t, currentSeqNum) - - executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum) - assert.Len(t, executionLogs, 1) - ccipTH.AssertExecState(t, executionLogs[0], testhelpers.ExecutionStateSuccess) - currentSeqNum++ - - // get the nop fee - nopFee, err := ccipTH.Source.OnRamp.GetNopFeesJuels(nil) - require.NoError(t, err) - t.Log("nopFee", nopFee) - - // withdraw fees and verify there is still fund left for nop payment - _, err = ccipTH.Source.OnRamp.WithdrawNonLinkFees( - ccipTH.Source.User, - ccipTH.Source.WrappedNative.Address(), - ccipTH.Source.User.From, - ) - require.NoError(t, err) - ccipTH.Source.Chain.Commit() - - // pay nops - _, err = ccipTH.Source.OnRamp.PayNops(ccipTH.Source.User) - require.NoError(t, err) - ccipTH.Source.Chain.Commit() - - srcBalanceAssertions := []testhelpers.BalanceAssertion{ - { - // Onramp should not have any balance left in wrapped native - Name: testhelpers.OnRampNative, - Address: ccipTH.Source.OnRamp.Address(), - Expected: big.NewInt(0).String(), - Getter: ccipTH.GetSourceWrappedTokenBalance, - }, - { - // Onramp should have the remaining link after paying nops - Name: testhelpers.OnRamp, - Address: ccipTH.Source.OnRamp.Address(), - Expected: new(big.Int).Sub(srcBalances[testhelpers.OnRamp], nopFee).String(), - Getter: ccipTH.GetSourceLinkBalance, - }, - { - Name: testhelpers.SourceRouter, - Address: ccipTH.Source.Router.Address(), - Expected: srcBalances[testhelpers.SourceRouter].String(), - Getter: ccipTH.GetSourceWrappedTokenBalance, - }, - // onRamp's balance (of previously sent fee during message sending) should have been transferred to - // the owner as a result of WithdrawNonLinkFees - { - Name: testhelpers.Sender, - Address: ccipTH.Source.User.From, - Expected: fee.String(), - Getter: ccipTH.GetSourceWrappedTokenBalance, - }, - } - - // the nodes should be paid according to the weights assigned - for i, node := range nodes { - paymentWeight := float64(nopsAndWeights[i].Weight) / float64(totalWeight) - paidInFloat := paymentWeight * float64(nopFee.Int64()) - paid, _ := new(big.Float).SetFloat64(paidInFloat).Int64() - bal := new(big.Int).Add( - new(big.Int).SetInt64(paid), - srcBalances[fmt.Sprintf("node %d", i)]).String() - srcBalanceAssertions = append(srcBalanceAssertions, testhelpers.BalanceAssertion{ - Name: fmt.Sprintf("node %d", i), - Address: node.PaymentReceiver, - Expected: bal, - Getter: ccipTH.GetSourceLinkBalance, - }) - } - ccipTH.AssertBalances(t, srcBalanceAssertions) - }) - - // Keep on sending a bunch of messages - // In the meantime update onchainConfig with new price registry address - // Verify if the jobs can pick up updated config - // Verify if all the messages are sent - t.Run("config change or price registry update while requests are inflight", func(t *testing.T) { - gasLimit := big.NewInt(200_003) // prime number - tokenAmount := big.NewInt(100) - msgWg := &sync.WaitGroup{} - msgWg.Add(1) - ticker := time.NewTicker(100 * time.Millisecond) - defer ticker.Stop() - startSeq := currentSeqNum - endSeq := currentSeqNum + 20 - - // send message with the old configs - ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) - ccipTH.Source.Chain.Commit() - - go func(ccipContracts testhelpers.CCIPContracts, currentSeqNum int) { - seqNumber := currentSeqNum + 1 - defer msgWg.Done() - for { - <-ticker.C // wait for ticker - t.Logf("sending request for seqnum %d", seqNumber) - ccipContracts.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) - ccipContracts.Source.Chain.Commit() - seqNumber++ - if seqNumber == endSeq { - return - } - } - }(ccipTH.CCIPContracts, currentSeqNum) - - ccipTH.DeployNewPriceRegistry(t) - commitOnchainConfig := ccipTH.CreateDefaultCommitOnchainConfig(t) - commitOffchainConfig := ccipTH.CreateDefaultCommitOffchainConfig(t) - execOnchainConfig := ccipTH.CreateDefaultExecOnchainConfig(t) - execOffchainConfig := ccipTH.CreateDefaultExecOffchainConfig(t) - - ccipTH.SetupOnchainConfig(t, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig) - - // wait for all requests to be complete - msgWg.Wait() - for i := startSeq; i < endSeq; i++ { - ccipTH.AllNodesHaveReqSeqNum(t, i) - ccipTH.EventuallyReportCommitted(t, i) - - executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, i, i) - assert.Len(t, executionLogs, 1) - ccipTH.AssertExecState(t, executionLogs[0], testhelpers.ExecutionStateSuccess) - } - - for i, node := range ccipTH.Nodes { - t.Logf("verifying node %d", i) - node.EventuallyNodeUsesNewCommitConfig(t, ccipTH, ccipdata.CommitOnchainConfig{ - PriceRegistry: ccipTH.Dest.PriceRegistry.Address(), - }) - node.EventuallyNodeUsesNewExecConfig(t, ccipTH, v1_2_0.ExecOnchainConfig{ - PermissionLessExecutionThresholdSeconds: testhelpers.PermissionLessExecutionThresholdSeconds, - Router: ccipTH.Dest.Router.Address(), - PriceRegistry: ccipTH.Dest.PriceRegistry.Address(), - MaxDataBytes: 1e5, - MaxNumberOfTokensPerMsg: 5, - MaxPoolReleaseOrMintGas: 200_000, - }) - node.EventuallyNodeUsesUpdatedPriceRegistry(t, ccipTH) - } - currentSeqNum = endSeq - }) - }) - } -} diff --git a/core/services/ocr2/plugins/ccip/integration_test.go b/core/services/ocr2/plugins/ccip/integration_test.go index e644a3e6f4a..15934a261c5 100644 --- a/core/services/ocr2/plugins/ccip/integration_test.go +++ b/core/services/ocr2/plugins/ccip/integration_test.go @@ -29,6 +29,8 @@ import ( ) func TestIntegration_CCIP(t *testing.T) { + t.Skip("racey test, need to sync backend.Commit() calls") + // Run tke batches of tests for both pipeline and dynamic price getter setups. // We will remove the pipeline batch once the feature is deleted from the code. tests := []struct { From 7b7815e9746562f6def8a2306f2a15572242f52c Mon Sep 17 00:00:00 2001 From: Matthew Pendrey Date: Mon, 9 Dec 2024 17:16:02 +0000 Subject: [PATCH 46/55] evm implementation of contract reader query keys API (#15336) * evm implementation of query keys api * lint * test fix * review --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- core/services/relay/evm/chain_reader.go | 36 +++ .../evm/evmtesting/bindings_test_adapter.go | 7 + core/services/relay/evm/read/errors.go | 52 +++++ .../services/relay/evm/read/multieventtype.go | 216 ++++++++++++++++++ .../relay/evm/read/multieventtype_test.go | 119 ++++++++++ deployment/go.mod | 2 +- deployment/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 +- 15 files changed, 445 insertions(+), 15 deletions(-) create mode 100644 core/services/relay/evm/read/multieventtype.go create mode 100644 core/services/relay/evm/read/multieventtype_test.go diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 8f9e458b8e2..8f57442c8a1 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -26,7 +26,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 3b8c5987c00..2a777f569b1 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1142,8 +1142,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 h1:NATQA1LfrEPXCdtEed9/G4SxaVuF8EZp5O2ucOK5C98= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index 4de739a44b4..99be89eae17 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "iter" "maps" "slices" "strings" @@ -298,6 +299,41 @@ func (cr *chainReader) QueryKey( return sequenceOfValues, nil } +func (cr *chainReader) QueryKeys(ctx context.Context, filters []commontypes.ContractKeyFilter, + limitAndSort query.LimitAndSort) (iter.Seq2[string, commontypes.Sequence], error) { + eventQueries := make([]read.EventQuery, 0, len(filters)) + for _, filter := range filters { + binding, address, err := cr.bindings.GetReader(filter.Contract.ReadIdentifier(filter.KeyFilter.Key)) + if err != nil { + return nil, err + } + + sequenceDataType := filter.SequenceDataType + _, isValuePtr := filter.SequenceDataType.(*values.Value) + if isValuePtr { + sequenceDataType, err = cr.CreateContractType(filter.Contract.ReadIdentifier(filter.Key), false) + if err != nil { + return nil, err + } + } + + eventBinding, ok := binding.(*read.EventBinding) + if !ok { + return nil, fmt.Errorf("query key %s is not an event", filter.KeyFilter.Key) + } + + eventQueries = append(eventQueries, read.EventQuery{ + Filter: filter.KeyFilter, + SequenceDataType: sequenceDataType, + IsValuePtr: isValuePtr, + EventBinding: eventBinding, + Address: common.HexToAddress(address), + }) + } + + return read.MultiEventTypeQuery(ctx, cr.lp, eventQueries, limitAndSort) +} + func (cr *chainReader) CreateContractType(readIdentifier string, forEncoding bool) (any, error) { return cr.codec.CreateType(cr.bindings.ReadTypeIdentifier(readIdentifier, forEncoding), forEncoding) } diff --git a/core/services/relay/evm/evmtesting/bindings_test_adapter.go b/core/services/relay/evm/evmtesting/bindings_test_adapter.go index 6c391aa0a7f..408acb0d5a8 100644 --- a/core/services/relay/evm/evmtesting/bindings_test_adapter.go +++ b/core/services/relay/evm/evmtesting/bindings_test_adapter.go @@ -36,6 +36,8 @@ func WrapContractReaderTesterWithBindings(t *testing.T, wrapped *EVMChainCompone interfacetests.ContractReaderBatchGetLatestValueSetsErrorsProperly, interfacetests.ContractReaderBatchGetLatestValueNoArgumentsWithSliceReturn, interfacetests.ContractReaderBatchGetLatestValueWithModifiersOwnMapstructureOverride, interfacetests.ContractReaderQueryKeyNotFound, interfacetests.ContractReaderQueryKeyReturnsData, interfacetests.ContractReaderQueryKeyReturnsDataAsValuesDotValue, interfacetests.ContractReaderQueryKeyReturnsDataAsValuesDotValue, interfacetests.ContractReaderQueryKeyCanFilterWithValueComparator, interfacetests.ContractReaderQueryKeyCanLimitResultsWithCursor, + interfacetests.ContractReaderQueryKeysNotFound, interfacetests.ContractReaderQueryKeysReturnsData, interfacetests.ContractReaderQueryKeysReturnsDataTwoEventTypes, interfacetests.ContractReaderQueryKeysReturnsDataAsValuesDotValue, + interfacetests.ContractReaderQueryKeysCanFilterWithValueComparator, interfacetests.ContractReaderQueryKeysCanLimitResultsWithCursor, ContractReaderQueryKeyFilterOnDataWordsWithValueComparator, ContractReaderQueryKeyOnDataWordsWithValueComparatorOnNestedField, ContractReaderQueryKeyFilterOnDataWordsWithValueComparatorOnDynamicField, ContractReaderQueryKeyFilteringOnDataWordsUsingValueComparatorsOnFieldsWithManualIndex, // TODO BCFR-1073 - Fix flaky tests @@ -71,6 +73,7 @@ func newBindingsMapping() bindingsMapping { interfacetests.MethodSettingStruct: "AddTestStruct", interfacetests.MethodSettingUint64: "SetAlterablePrimitiveValue", interfacetests.MethodTriggeringEvent: "TriggerEvent", + interfacetests.MethodTriggeringEventWithDynamicTopic: "TriggerEventWithDynamicTopic", } methodNameMappingByContract[interfacetests.AnySecondContractName] = map[string]string{ interfacetests.MethodReturningUint64: "GetDifferentPrimitiveValue", @@ -249,6 +252,10 @@ func (b bindingChainWriterProxy) SubmitTransaction(ctx context.Context, contract bindingsInput := bindings.TriggerEventInput{} _ = convertStruct(args, &bindingsInput) return chainReaderTesters.TriggerEvent(ctx, bindingsInput, transactionID, toAddress, meta) + case interfacetests.MethodTriggeringEventWithDynamicTopic: + bindingsInput := bindings.TriggerEventWithDynamicTopicInput{} + _ = convertStruct(args, &bindingsInput) + return chainReaderTesters.TriggerEventWithDynamicTopic(ctx, bindingsInput, transactionID, toAddress, meta) default: return errors.New("No logic implemented for method: " + method) } diff --git a/core/services/relay/evm/read/errors.go b/core/services/relay/evm/read/errors.go index 422b7ded1d8..e767da495e7 100644 --- a/core/services/relay/evm/read/errors.go +++ b/core/services/relay/evm/read/errors.go @@ -75,6 +75,58 @@ func (e Error) Unwrap() error { return e.Err } +type MultiCallError struct { + Err error + Type readType + Detail *callsReadDetail + Result *string +} + +type callsReadDetail struct { + Calls []Call + Block string +} + +func newErrorFromCalls(err error, calls []Call, block string, tp readType) MultiCallError { + return MultiCallError{ + Err: err, + Type: tp, + Detail: &callsReadDetail{ + Calls: calls, + Block: block, + }, + } +} + +func (e MultiCallError) Error() string { + var builder strings.Builder + + builder.WriteString("[read error]") + builder.WriteString(fmt.Sprintf(" err: %s;", e.Err.Error())) + builder.WriteString(fmt.Sprintf(" type: %s;", e.Type)) + + if e.Detail != nil { + builder.WriteString(fmt.Sprintf(" block: %s;", e.Detail.Block)) + for _, call := range e.Detail.Calls { + builder.WriteString(fmt.Sprintf(" address: %s;", call.ContractAddress.Hex())) + builder.WriteString(fmt.Sprintf(" contract-name: %s;", call.ContractName)) + builder.WriteString(fmt.Sprintf(" read-name: %s;", call.ReadName)) + builder.WriteString(fmt.Sprintf(" params: %+v;", call.Params)) + builder.WriteString(fmt.Sprintf(" expected return type: %s;", reflect.TypeOf(call.ReturnVal))) + } + + if e.Result != nil { + builder.WriteString(fmt.Sprintf("encoded result: %s;", *e.Result)) + } + } + + return builder.String() +} + +func (e MultiCallError) Unwrap() error { + return e.Err +} + type ConfigError struct { Msg string } diff --git a/core/services/relay/evm/read/multieventtype.go b/core/services/relay/evm/read/multieventtype.go new file mode 100644 index 00000000000..1b561912d18 --- /dev/null +++ b/core/services/relay/evm/read/multieventtype.go @@ -0,0 +1,216 @@ +package read + +import ( + "context" + "errors" + "fmt" + "iter" + "reflect" + "sort" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" +) + +type EventQuery struct { + Filter query.KeyFilter + EventBinding *EventBinding + SequenceDataType any + IsValuePtr bool + Address common.Address +} + +func MultiEventTypeQuery(ctx context.Context, lp logpoller.LogPoller, eventQueries []EventQuery, limitAndSort query.LimitAndSort) (iter.Seq2[string, commontypes.Sequence], error) { + seqIter, err := multiEventTypeQueryWithoutErrorWrapping(ctx, lp, eventQueries, limitAndSort) + if err != nil { + if len(eventQueries) > 0 { + var calls []Call + for _, eq := range eventQueries { + calls = append(calls, Call{ + ContractAddress: eq.Address, + ContractName: eq.EventBinding.contractName, + ReadName: eq.EventBinding.eventName, + ReturnVal: eq.SequenceDataType, + }) + } + + err = newErrorFromCalls(err, calls, "", eventReadType) + } else { + err = fmt.Errorf("no event queries provided: %w", err) + } + } + + return seqIter, err +} + +func multiEventTypeQueryWithoutErrorWrapping(ctx context.Context, lp logpoller.LogPoller, eventQueries []EventQuery, limitAndSort query.LimitAndSort) (iter.Seq2[string, commontypes.Sequence], error) { + if err := validateEventQueries(eventQueries); err != nil { + return nil, fmt.Errorf("error validating event queries: %w", err) + } + + for _, eq := range eventQueries { + if err := eq.EventBinding.validateBound(eq.Address); err != nil { + return nil, err + } + } + + allFilterExpressions := make([]query.Expression, 0, len(eventQueries)) + for _, eq := range eventQueries { + var expressions []query.Expression + + defaultExpressions := []query.Expression{ + logpoller.NewAddressFilter(eq.Address), + logpoller.NewEventSigFilter(eq.EventBinding.hash), + } + expressions = append(expressions, defaultExpressions...) + + remapped, remapErr := eq.EventBinding.remap(eq.Filter) + if remapErr != nil { + return nil, fmt.Errorf("error remapping filter: %w", remapErr) + } + expressions = append(expressions, remapped.Expressions...) + + filterExpression := query.And(expressions...) + + allFilterExpressions = append(allFilterExpressions, filterExpression) + } + + eventQuery := query.Or(allFilterExpressions...) + + queryName := createQueryName(eventQueries) + + logs, err := lp.FilteredLogs(ctx, []query.Expression{eventQuery}, limitAndSort, queryName) + if err != nil { + return nil, wrapInternalErr(err) + } + + seqIter, err := decodeMultiEventTypeLogsIntoSequences(ctx, logs, eventQueries) + if err != nil { + return nil, wrapInternalErr(err) + } + + return seqIter, nil +} + +func createQueryName(eventQueries []EventQuery) string { + queryName := "" + contractToEvents := map[string][]string{} + for _, eq := range eventQueries { + contractName := eq.EventBinding.contractName + "-" + eq.Address.String() + + if _, exists := contractToEvents[contractName]; !exists { + contractToEvents[contractName] = []string{} + } + contractToEvents[contractName] = append(contractToEvents[contractName], eq.EventBinding.eventName) + } + + contractNames := make([]string, 0, len(contractToEvents)) + for contractName := range contractToEvents { + contractNames = append(contractNames, contractName) + } + + sort.Strings(contractNames) + + for _, contractName := range contractNames { + queryName += contractName + "-" + for _, event := range contractToEvents[contractName] { + queryName += event + "-" + } + } + + queryName = strings.TrimSuffix(queryName, "-") + return queryName +} + +func validateEventQueries(eventQueries []EventQuery) error { + duplicateCheck := map[common.Hash]EventQuery{} + for _, eq := range eventQueries { + if eq.EventBinding == nil { + return errors.New("event binding is nil") + } + + if eq.SequenceDataType == nil { + return errors.New("sequence data type is nil") + } + + // TODO support queries with the same event signature but different filters + if _, exists := duplicateCheck[eq.EventBinding.hash]; exists { + return fmt.Errorf("duplicate event query for event signature %s, event name %s", eq.EventBinding.hash, eq.EventBinding.eventName) + } + duplicateCheck[eq.EventBinding.hash] = eq + } + return nil +} + +func decodeMultiEventTypeLogsIntoSequences(ctx context.Context, logs []logpoller.Log, eventQueries []EventQuery) (iter.Seq2[string, commontypes.Sequence], error) { + type sequenceWithKey struct { + Key string + Sequence commontypes.Sequence + } + sequenceWithKeys := make([]sequenceWithKey, 0, len(logs)) + eventSigToEventQuery := map[common.Hash]EventQuery{} + for _, eq := range eventQueries { + eventSigToEventQuery[eq.EventBinding.hash] = eq + } + + for _, logEntry := range logs { + eventSignatureHash := logEntry.EventSig + + eq, exists := eventSigToEventQuery[eventSignatureHash] + if !exists { + return nil, fmt.Errorf("no event query found for log with event signature %s", eventSignatureHash) + } + + seqWithKey := sequenceWithKey{ + Key: eq.Filter.Key, + Sequence: commontypes.Sequence{ + Cursor: logpoller.FormatContractReaderCursor(logEntry), + Head: commontypes.Head{ + Height: strconv.FormatInt(logEntry.BlockNumber, 10), + Hash: logEntry.BlockHash.Bytes(), + Timestamp: uint64(logEntry.BlockTimestamp.Unix()), //nolint:gosec // G115 false positive + }, + }, + } + + var typeVal reflect.Value + + typeInto := reflect.TypeOf(eq.SequenceDataType) + if typeInto.Kind() == reflect.Pointer { + typeVal = reflect.New(typeInto.Elem()) + } else { + typeVal = reflect.Indirect(reflect.New(typeInto)) + } + + // create a new value of the same type as 'into' for the data to be extracted to + seqWithKey.Sequence.Data = typeVal.Interface() + + if err := eq.EventBinding.decodeLog(ctx, &logEntry, seqWithKey.Sequence.Data); err != nil { + return nil, err + } + + if eq.IsValuePtr { + wrappedValue, err := values.Wrap(seqWithKey.Sequence.Data) + if err != nil { + return nil, err + } + seqWithKey.Sequence.Data = &wrappedValue + } + + sequenceWithKeys = append(sequenceWithKeys, seqWithKey) + } + + return func(yield func(string, commontypes.Sequence) bool) { + for _, s := range sequenceWithKeys { + if !yield(s.Key, s.Sequence) { + return + } + } + }, nil +} diff --git a/core/services/relay/evm/read/multieventtype_test.go b/core/services/relay/evm/read/multieventtype_test.go new file mode 100644 index 00000000000..8fb39ecc526 --- /dev/null +++ b/core/services/relay/evm/read/multieventtype_test.go @@ -0,0 +1,119 @@ +package read + +import ( + "github.com/ethereum/go-ethereum/common" + + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-common/pkg/types/query" +) + +func TestCreateQueryName(t *testing.T) { + eventQueries := []EventQuery{ + { + Filter: query.KeyFilter{Key: "key1"}, + EventBinding: &EventBinding{ + contractName: "ContractA", + eventName: "EventA", + hash: common.HexToHash("0x1"), + }, + SequenceDataType: "dataType1", + Address: common.HexToAddress("0x123"), + }, + { + Filter: query.KeyFilter{Key: "key2"}, + EventBinding: &EventBinding{ + contractName: "ContractB", + eventName: "EventB", + hash: common.HexToHash("0x2"), + }, + SequenceDataType: "dataType2", + Address: common.HexToAddress("0x456"), + }, + { + Filter: query.KeyFilter{Key: "key1"}, + EventBinding: &EventBinding{ + contractName: "ContractA", + eventName: "EventA1", + hash: common.HexToHash("0x1"), + }, + SequenceDataType: "dataType1", + Address: common.HexToAddress("0x123"), + }, + } + + expectedQueryName := "ContractA-0x0000000000000000000000000000000000000123-EventA-EventA1-ContractB-0x0000000000000000000000000000000000000456-EventB" + queryName := createQueryName(eventQueries) + + assert.Equal(t, expectedQueryName, queryName) +} + +func TestValidateEventQueries(t *testing.T) { + tests := []struct { + name string + eventQueries []EventQuery + expectedError string + }{ + { + name: "valid event queries", + eventQueries: []EventQuery{ + { + EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, + SequenceDataType: "dataType1", + }, + { + EventBinding: &EventBinding{hash: common.HexToHash("0x2")}, + SequenceDataType: "dataType2", + }, + }, + expectedError: "", + }, + { + name: "nil event binding", + eventQueries: []EventQuery{ + { + EventBinding: nil, + SequenceDataType: "dataType1", + }, + }, + expectedError: "event binding is nil", + }, + { + name: "nil sequence data type", + eventQueries: []EventQuery{ + { + EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, + SequenceDataType: nil, + }, + }, + expectedError: "sequence data type is nil", + }, + { + name: "duplicate event query", + eventQueries: []EventQuery{ + { + EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, + SequenceDataType: "dataType1", + }, + { + EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, + SequenceDataType: "dataType2", + }, + }, + expectedError: "duplicate event query for event signature 0x0000000000000000000000000000000000000000000000000000000000000001, event name ", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validateEventQueries(tt.eventQueries) + if tt.expectedError == "" { + assert.NoError(t, err) + } else { + assert.EqualError(t, err, tt.expectedError) + } + }) + } +} diff --git a/deployment/go.mod b/deployment/go.mod index b9a2fdb255f..058df5d2a29 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -25,7 +25,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/deployment/go.sum b/deployment/go.sum index 7513309dddf..00e0aab077b 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1411,8 +1411,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 h1:NATQA1LfrEPXCdtEed9/G4SxaVuF8EZp5O2ucOK5C98= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/go.mod b/go.mod index 35069d38bbf..2dd7d3fcfe5 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db github.com/smartcontractkit/chainlink-feeds v0.1.1 diff --git a/go.sum b/go.sum index caa877d66fa..b8941bc7d01 100644 --- a/go.sum +++ b/go.sum @@ -1125,8 +1125,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 h1:NATQA1LfrEPXCdtEed9/G4SxaVuF8EZp5O2ucOK5C98= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index f4e6a9720e8..58b2a6fa1c4 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -41,7 +41,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 9e0e176190d..4f31dd61871 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1432,8 +1432,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 h1:NATQA1LfrEPXCdtEed9/G4SxaVuF8EZp5O2ucOK5C98= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 23f840a67f3..47b128c7f60 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -19,7 +19,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index e9eaaf81dad..59a4e9e64ad 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1423,8 +1423,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e h1:GnM6ZWV6vlk2+n6c6o+v/R1LtXzBGVVx7r37nt/h6Uc= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241204015713-8956bb614e9e/go.mod h1:80vGBbOfertJig0xFKsRfm+i17FkjdKkk1dAaGE45Os= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f h1:hH+cAG2zt+WK4I2m572LXAnAJg3wtGEAwzBKR8FiXo8= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241206011233-b6684ee6508f/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776 h1:NATQA1LfrEPXCdtEed9/G4SxaVuF8EZp5O2ucOK5C98= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241209151352-70300ddcc776/go.mod h1:bQktEJf7sJ0U3SmIcXvbGUox7SmXcnSEZ4kUbT8R5Nk= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= From a7074338e708ee79b9a8d5baa2223b84ccc70347 Mon Sep 17 00:00:00 2001 From: Makram Date: Mon, 9 Dec 2024 20:01:08 +0200 Subject: [PATCH 47/55] core/services/ocr2/plugins/ccip: fix racey TestIntegration_CCIP (#15572) Wrap simulated backend with an object that synchronizes Commit() calls --- .../ocr2/plugins/ccip/integration_test.go | 2 - .../ccip/testhelpers/ccip_contracts.go | 28 +- .../ccip/testhelpers/integration/chainlink.go | 3 +- .../ccip/testhelpers/simulated_backend.go | 2 +- .../testhelpers_1_4_0/ccip_contracts_1_4_0.go | 1620 ----------------- .../testhelpers_1_4_0/chainlink.go | 1053 ----------- .../testhelpers_1_4_0/config_1_4_0.go | 75 - .../ccip-tests/contracts/contract_deployer.go | 31 - 8 files changed, 27 insertions(+), 2787 deletions(-) delete mode 100644 core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go delete mode 100644 core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go delete mode 100644 core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go diff --git a/core/services/ocr2/plugins/ccip/integration_test.go b/core/services/ocr2/plugins/ccip/integration_test.go index 15934a261c5..e644a3e6f4a 100644 --- a/core/services/ocr2/plugins/ccip/integration_test.go +++ b/core/services/ocr2/plugins/ccip/integration_test.go @@ -29,8 +29,6 @@ import ( ) func TestIntegration_CCIP(t *testing.T) { - t.Skip("racey test, need to sync backend.Commit() calls") - // Run tke batches of tests for both pipeline and dynamic price getter setups. // We will remove the pipeline batch once the feature is deleted from the code. tests := []struct { diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go index 6a220ececf7..c2fec2903e8 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "math/big" + "sync" "testing" "time" @@ -168,11 +169,32 @@ type MaybeRevertReceiver struct { Strict bool } +// Backend wraps a simulated backend with a mutex to make it safe for concurrent use +// Commit() in particular has caused races. +type Backend struct { + mu sync.Mutex + *simulated.Backend +} + +func NewBackend(sim *simulated.Backend) *Backend { + return &Backend{ + mu: sync.Mutex{}, + Backend: sim, + } +} + +func (b *Backend) Commit() common.Hash { + b.mu.Lock() + defer b.mu.Unlock() + + return b.Backend.Commit() +} + type Common struct { ChainID uint64 ChainSelector uint64 User *bind.TransactOpts - Chain *simulated.Backend + Chain *Backend LinkToken *link_token_interface.LinkToken LinkTokenPool *lock_release_token_pool.LockReleaseTokenPool CustomToken *link_token_interface.LinkToken @@ -1194,7 +1216,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh ChainID: sourceChainID, ChainSelector: sourceChainSelector, User: sourceUser, - Chain: sourceChain, + Chain: NewBackend(sourceChain), LinkToken: sourceLinkToken, LinkTokenPool: sourceLinkPool, CustomToken: sourceCustomToken, @@ -1214,7 +1236,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh ChainID: destChainID, ChainSelector: destChainSelector, User: destUser, - Chain: destChain, + Chain: NewBackend(destChain), LinkToken: destLinkToken, LinkTokenPool: destLinkPool, CustomToken: destCustomToken, diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index ddae5241883..d21c5b12513 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" types3 "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient/simulated" "github.com/google/uuid" "github.com/hashicorp/consul/sdk/freeport" "github.com/jmoiron/sqlx" @@ -369,7 +368,7 @@ func setupNodeCCIP( owner *bind.TransactOpts, port int64, dbName string, - sourceChain *simulated.Backend, destChain *simulated.Backend, + sourceChain *testhelpers.Backend, destChain *testhelpers.Backend, sourceChainID *big.Int, destChainID *big.Int, bootstrapPeerID string, bootstrapPort int64, diff --git a/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go b/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go index 58206d37427..699af7e14dc 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go @@ -56,7 +56,7 @@ func (ks EthKeyStoreSim) Eth() keystore.Eth { var _ keystore.Eth = EthKeyStoreSim{}.ETHKS -func ConfirmTxs(t *testing.T, txs []*ethtypes.Transaction, chain *simulated.Backend) { +func ConfirmTxs(t *testing.T, txs []*ethtypes.Transaction, chain *Backend) { chain.Commit() ctx := tests.Context(t) for _, tx := range txs { diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go deleted file mode 100644 index 5ed20875498..00000000000 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go +++ /dev/null @@ -1,1620 +0,0 @@ -package testhelpers_1_4_0 - -import ( - "context" - "fmt" - "math" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/pkg/errors" - "github.com/rs/zerolog/log" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types" - ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/hashutil" - "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_2_0" - evm_2_evm_offramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" - evm_2_evm_onramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_0_0" - lock_release_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_4_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" - "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/testhelpers" -) - -var ( - // Source - SourcePool = "source Link pool" - SourcePriceRegistry = "source PriceRegistry" - OnRamp = "onramp" - OnRampNative = "onramp-native" - SourceRouter = "source router" - - // Dest - OffRamp = "offramp" - DestPool = "dest Link pool" - - Receiver = "receiver" - Sender = "sender" - Link = func(amount int64) *big.Int { return new(big.Int).Mul(big.NewInt(1e18), big.NewInt(amount)) } - HundredLink = Link(100) - LinkUSDValue = func(amount int64) *big.Int { return new(big.Int).Mul(big.NewInt(1e18), big.NewInt(amount)) } - SourceChainID = uint64(1000) - SourceChainSelector = uint64(11787463284727550157) - DestChainID = uint64(1337) - DestChainSelector = uint64(3379446385462418246) -) - -// Backwards compat, in principle these statuses are version dependent -// TODO: Adjust integration tests to be version agnostic using readers -var ( - ExecutionStateSuccess = MessageExecutionState(cciptypes.ExecutionStateSuccess) - ExecutionStateFailure = MessageExecutionState(cciptypes.ExecutionStateFailure) -) - -type MessageExecutionState cciptypes.MessageExecutionState -type CommitOffchainConfig struct { - v1_2_0.JSONCommitOffchainConfig -} - -func (c CommitOffchainConfig) Encode() ([]byte, error) { - return ccipconfig.EncodeOffchainConfig(c.JSONCommitOffchainConfig) -} - -func NewCommitOffchainConfig( - GasPriceHeartBeat config.Duration, - DAGasPriceDeviationPPB uint32, - ExecGasPriceDeviationPPB uint32, - TokenPriceHeartBeat config.Duration, - TokenPriceDeviationPPB uint32, - InflightCacheExpiry config.Duration, - priceReportingDisabled bool) CommitOffchainConfig { - return CommitOffchainConfig{v1_2_0.JSONCommitOffchainConfig{ - GasPriceHeartBeat: GasPriceHeartBeat, - DAGasPriceDeviationPPB: DAGasPriceDeviationPPB, - ExecGasPriceDeviationPPB: ExecGasPriceDeviationPPB, - TokenPriceHeartBeat: TokenPriceHeartBeat, - TokenPriceDeviationPPB: TokenPriceDeviationPPB, - InflightCacheExpiry: InflightCacheExpiry, - PriceReportingDisabled: priceReportingDisabled, - }} -} - -type CommitOnchainConfig struct { - ccipdata.CommitOnchainConfig -} - -func NewCommitOnchainConfig( - PriceRegistry common.Address, -) CommitOnchainConfig { - return CommitOnchainConfig{ccipdata.CommitOnchainConfig{ - PriceRegistry: PriceRegistry, - }} -} - -type ExecOnchainConfig struct { - v1_2_0.ExecOnchainConfig -} - -func NewExecOnchainConfig( - PermissionLessExecutionThresholdSeconds uint32, - Router common.Address, - PriceRegistry common.Address, - MaxNumberOfTokensPerMsg uint16, - MaxDataBytes uint32, - MaxPoolReleaseOrMintGas uint32, -) ExecOnchainConfig { - return ExecOnchainConfig{v1_2_0.ExecOnchainConfig{ - PermissionLessExecutionThresholdSeconds: PermissionLessExecutionThresholdSeconds, - Router: Router, - PriceRegistry: PriceRegistry, - MaxNumberOfTokensPerMsg: MaxNumberOfTokensPerMsg, - MaxDataBytes: MaxDataBytes, - MaxPoolReleaseOrMintGas: MaxPoolReleaseOrMintGas, - }} -} - -type ExecOffchainConfig struct { - v1_2_0.JSONExecOffchainConfig -} - -func (c ExecOffchainConfig) Encode() ([]byte, error) { - return ccipconfig.EncodeOffchainConfig(c.JSONExecOffchainConfig) -} - -func NewExecOffchainConfig( - DestOptimisticConfirmations uint32, - BatchGasLimit uint32, - RelativeBoostPerWaitHour float64, - InflightCacheExpiry config.Duration, - RootSnoozeTime config.Duration, - BatchingStrategyID uint32, -) ExecOffchainConfig { - return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ - DestOptimisticConfirmations: DestOptimisticConfirmations, - BatchGasLimit: BatchGasLimit, - RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, - InflightCacheExpiry: InflightCacheExpiry, - RootSnoozeTime: RootSnoozeTime, - BatchingStrategyID: BatchingStrategyID, - }} -} - -type MaybeRevertReceiver struct { - Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver - Strict bool -} - -type Common struct { - ChainID uint64 - ChainSelector uint64 - User *bind.TransactOpts - Chain *simulated.Backend - LinkToken *link_token_interface.LinkToken - LinkTokenPool *lock_release_token_pool.LockReleaseTokenPool - CustomToken *link_token_interface.LinkToken - WrappedNative *weth9.WETH9 - WrappedNativePool *lock_release_token_pool_1_0_0.LockReleaseTokenPool - ARM *mock_rmn_contract.MockRMNContract - ARMProxy *rmn_proxy_contract.RMNProxyContract - PriceRegistry *price_registry_1_2_0.PriceRegistry -} - -type SourceChain struct { - Common - Router *router.Router - OnRamp *evm_2_evm_onramp.EVM2EVMOnRamp -} - -type DestinationChain struct { - Common - - CommitStore *commit_store_1_2_0.CommitStore - Router *router.Router - OffRamp *evm_2_evm_offramp.EVM2EVMOffRamp - Receivers []MaybeRevertReceiver -} - -type OCR2Config struct { - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte -} - -type BalanceAssertion struct { - Name string - Address common.Address - Expected string - Getter func(t *testing.T, addr common.Address) *big.Int - Within string -} - -type BalanceReq struct { - Name string - Addr common.Address - Getter func(t *testing.T, addr common.Address) *big.Int -} - -type CCIPContracts struct { - Source SourceChain - Dest DestinationChain - Oracles []confighelper.OracleIdentityExtra - - commitOCRConfig, execOCRConfig *OCR2Config -} - -func (c *CCIPContracts) DeployNewOffRamp(t *testing.T) { - prevOffRamp := common.HexToAddress("") - if c.Dest.OffRamp != nil { - prevOffRamp = c.Dest.OffRamp.Address() - } - offRampAddress, _, _, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( - c.Dest.User, - c.Dest.Chain.Client(), - evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ - CommitStore: c.Dest.CommitStore.Address(), - ChainSelector: c.Dest.ChainSelector, - SourceChainSelector: c.Source.ChainSelector, - OnRamp: c.Source.OnRamp.Address(), - PrevOffRamp: prevOffRamp, - ArmProxy: c.Dest.ARMProxy.Address(), - }, - []common.Address{c.Source.LinkToken.Address()}, // source tokens - []common.Address{c.Dest.LinkTokenPool.Address()}, // pools - evm_2_evm_offramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: LinkUSDValue(100), - Rate: LinkUSDValue(1), - }, - ) - require.NoError(t, err) - c.Dest.Chain.Commit() - - c.Dest.OffRamp, err = evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampAddress, c.Dest.Chain.Client()) - require.NoError(t, err) - - c.Dest.Chain.Commit() - c.Source.Chain.Commit() -} - -func (c *CCIPContracts) EnableOffRamp(t *testing.T) { - _, err := c.Dest.Router.ApplyRampUpdates(c.Dest.User, nil, nil, []router.RouterOffRamp{{SourceChainSelector: SourceChainSelector, OffRamp: c.Dest.OffRamp.Address()}}) - require.NoError(t, err) - c.Dest.Chain.Commit() - - onChainConfig := c.CreateDefaultExecOnchainConfig(t) - offChainConfig := c.CreateDefaultExecOffchainConfig(t) - - c.SetupExecOCR2Config(t, onChainConfig, offChainConfig) -} - -func (c *CCIPContracts) EnableCommitStore(t *testing.T) { - onChainConfig := c.CreateDefaultCommitOnchainConfig(t) - offChainConfig := c.CreateDefaultCommitOffchainConfig(t) - - c.SetupCommitOCR2Config(t, onChainConfig, offChainConfig) - - _, err := c.Dest.PriceRegistry.ApplyPriceUpdatersUpdates(c.Dest.User, []common.Address{c.Dest.CommitStore.Address()}, []common.Address{}) - require.NoError(t, err) - c.Dest.Chain.Commit() -} - -func (c *CCIPContracts) DeployNewOnRamp(t *testing.T) { - t.Log("Deploying new onRamp") - // find the last onRamp - prevOnRamp := common.HexToAddress("") - if c.Source.OnRamp != nil { - prevOnRamp = c.Source.OnRamp.Address() - } - onRampAddress, _, _, err := evm_2_evm_onramp.DeployEVM2EVMOnRamp( - c.Source.User, // user - c.Source.Chain.Client(), // client - evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ - LinkToken: c.Source.LinkToken.Address(), - ChainSelector: c.Source.ChainSelector, - DestChainSelector: c.Dest.ChainSelector, - DefaultTxGasLimit: 200_000, - MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), - PrevOnRamp: prevOnRamp, - ArmProxy: c.Source.ARM.Address(), // ARM - }, - evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ - Router: c.Source.Router.Address(), - MaxNumberOfTokensPerMsg: 5, - DestGasOverhead: 350_000, - DestGasPerPayloadByte: 16, - DestDataAvailabilityOverheadGas: 33_596, - DestGasPerDataAvailabilityByte: 16, - DestDataAvailabilityMultiplierBps: 6840, // 0.684 - PriceRegistry: c.Source.PriceRegistry.Address(), - MaxDataBytes: 1e5, - MaxPerMsgGasLimit: 4_000_000, - }, - []evm_2_evm_onramp.InternalPoolUpdate{ - { - Token: c.Source.LinkToken.Address(), - Pool: c.Source.LinkTokenPool.Address(), - }, - }, - evm_2_evm_onramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: LinkUSDValue(100), - Rate: LinkUSDValue(1), - }, - []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ - { - Token: c.Source.LinkToken.Address(), - NetworkFeeUSDCents: 1_00, - GasMultiplierWeiPerEth: 1e18, - PremiumMultiplierWeiPerEth: 9e17, - Enabled: true, - }, - { - Token: c.Source.WrappedNative.Address(), - NetworkFeeUSDCents: 1_00, - GasMultiplierWeiPerEth: 1e18, - PremiumMultiplierWeiPerEth: 1e18, - Enabled: true, - }, - }, - []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ - { - Token: c.Source.LinkToken.Address(), - MinFeeUSDCents: 50, // $0.5 - MaxFeeUSDCents: 1_000_000_00, // $ 1 million - DeciBps: 5_0, // 5 bps - DestGasOverhead: 34_000, - DestBytesOverhead: 32, - }, - }, - []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, - ) - - require.NoError(t, err) - c.Source.Chain.Commit() - c.Dest.Chain.Commit() - c.Source.OnRamp, err = evm_2_evm_onramp.NewEVM2EVMOnRamp(onRampAddress, c.Source.Chain.Client()) - require.NoError(t, err) - c.Source.Chain.Commit() - c.Dest.Chain.Commit() -} - -func (c *CCIPContracts) EnableOnRamp(t *testing.T) { - t.Log("Setting onRamp on source router") - _, err := c.Source.Router.ApplyRampUpdates(c.Source.User, []router.RouterOnRamp{{DestChainSelector: c.Dest.ChainSelector, OnRamp: c.Source.OnRamp.Address()}}, nil, nil) - require.NoError(t, err) - c.Source.Chain.Commit() - c.Dest.Chain.Commit() -} - -func (c *CCIPContracts) DeployNewCommitStore(t *testing.T) { - commitStoreAddress, _, _, err := commit_store_1_2_0.DeployCommitStore( - c.Dest.User, // user - c.Dest.Chain.Client(), // client - commit_store_1_2_0.CommitStoreStaticConfig{ - ChainSelector: c.Dest.ChainSelector, - SourceChainSelector: c.Source.ChainSelector, - OnRamp: c.Source.OnRamp.Address(), - ArmProxy: c.Dest.ARMProxy.Address(), - }, - ) - require.NoError(t, err) - c.Dest.Chain.Commit() - // since CommitStoreHelper derives from CommitStore, it's safe to instantiate both on same address - c.Dest.CommitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreAddress, c.Dest.Chain.Client()) - require.NoError(t, err) -} - -func (c *CCIPContracts) DeployNewPriceRegistry(t *testing.T) { - t.Log("Deploying new Price Registry") - destPricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( - c.Dest.User, - c.Dest.Chain.Client(), - []common.Address{c.Dest.CommitStore.Address()}, - []common.Address{c.Dest.LinkToken.Address()}, - 60*60*24*14, // two weeks - ) - require.NoError(t, err) - c.Source.Chain.Commit() - c.Dest.Chain.Commit() - c.Dest.PriceRegistry, err = price_registry_1_2_0.NewPriceRegistry(destPricesAddress, c.Dest.Chain.Client()) - require.NoError(t, err) - - priceUpdates := price_registry_1_2_0.InternalPriceUpdates{ - TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ - { - SourceToken: c.Dest.LinkToken.Address(), - UsdPerToken: big.NewInt(8e18), // 8usd - }, - { - SourceToken: c.Dest.WrappedNative.Address(), - UsdPerToken: big.NewInt(1e18), // 1usd - }, - }, - GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ - { - DestChainSelector: c.Source.ChainSelector, - UsdPerUnitGas: big.NewInt(2000e9), // $2000 per eth * 1gwei = 2000e9 - }, - }, - } - _, err = c.Dest.PriceRegistry.UpdatePrices(c.Dest.User, priceUpdates) - require.NoError(t, err) - - c.Source.Chain.Commit() - c.Dest.Chain.Commit() - - t.Logf("New Price Registry deployed at %s", destPricesAddress.String()) -} - -func (c *CCIPContracts) SetNopsOnRamp(t *testing.T, nopsAndWeights []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight) { - tx, err := c.Source.OnRamp.SetNops(c.Source.User, nopsAndWeights) - require.NoError(t, err) - c.Source.Chain.Commit() - _, err = bind.WaitMined(tests.Context(t), c.Source.Chain.Client(), tx) - require.NoError(t, err) -} - -func (c *CCIPContracts) GetSourceLinkBalance(t *testing.T, addr common.Address) *big.Int { - return GetBalance(t, c.Source.Chain.Client(), c.Source.LinkToken.Address(), addr) -} - -func (c *CCIPContracts) GetDestLinkBalance(t *testing.T, addr common.Address) *big.Int { - return GetBalance(t, c.Dest.Chain.Client(), c.Dest.LinkToken.Address(), addr) -} - -func (c *CCIPContracts) GetSourceWrappedTokenBalance(t *testing.T, addr common.Address) *big.Int { - return GetBalance(t, c.Source.Chain.Client(), c.Source.WrappedNative.Address(), addr) -} - -func (c *CCIPContracts) GetDestWrappedTokenBalance(t *testing.T, addr common.Address) *big.Int { - return GetBalance(t, c.Dest.Chain.Client(), c.Dest.WrappedNative.Address(), addr) -} - -func (c *CCIPContracts) AssertBalances(t *testing.T, bas []BalanceAssertion) { - for _, b := range bas { - actual := b.Getter(t, b.Address) - t.Log("Checking balance for", b.Name, "at", b.Address.Hex(), "got", actual) - require.NotNil(t, actual, "%v getter return nil", b.Name) - if b.Within == "" { - require.Equal(t, b.Expected, actual.String(), "wrong balance for %s got %s want %s", b.Name, actual, b.Expected) - } else { - bi, _ := big.NewInt(0).SetString(b.Expected, 10) - withinI, _ := big.NewInt(0).SetString(b.Within, 10) - high := big.NewInt(0).Add(bi, withinI) - low := big.NewInt(0).Sub(bi, withinI) - require.Equal(t, -1, actual.Cmp(high), "wrong balance for %s got %s outside expected range [%s, %s]", b.Name, actual, low, high) - require.Equal(t, 1, actual.Cmp(low), "wrong balance for %s got %s outside expected range [%s, %s]", b.Name, actual, low, high) - } - } -} - -func AccountToAddress(accounts []ocr2types.Account) (addresses []common.Address, err error) { - for _, signer := range accounts { - bytes, err := hexutil.Decode(string(signer)) - if err != nil { - return []common.Address{}, errors.Wrap(err, fmt.Sprintf("given address is not valid %s", signer)) - } - if len(bytes) != 20 { - return []common.Address{}, errors.Errorf("address is not 20 bytes %s", signer) - } - addresses = append(addresses, common.BytesToAddress(bytes)) - } - return addresses, nil -} - -func OnchainPublicKeyToAddress(publicKeys []ocrtypes.OnchainPublicKey) (addresses []common.Address, err error) { - for _, signer := range publicKeys { - if len(signer) != 20 { - return []common.Address{}, errors.Errorf("address is not 20 bytes %s", signer) - } - addresses = append(addresses, common.BytesToAddress(signer)) - } - return addresses, nil -} - -func (c *CCIPContracts) DeriveOCR2Config(t *testing.T, oracles []confighelper.OracleIdentityExtra, rawOnchainConfig []byte, rawOffchainConfig []byte) *OCR2Config { - signers, transmitters, threshold, onchainConfig, offchainConfigVersion, offchainConfig, err := confighelper.ContractSetConfigArgsForTests( - 2*time.Second, // deltaProgress - 1*time.Second, // deltaResend - 1*time.Second, // deltaRound - 500*time.Millisecond, // deltaGrace - 2*time.Second, // deltaStage - 3, - []int{1, 1, 1, 1}, - oracles, - rawOffchainConfig, - nil, - 50*time.Millisecond, // Max duration query - 1*time.Second, // Max duration observation - 100*time.Millisecond, - 100*time.Millisecond, - 100*time.Millisecond, - 1, // faults - rawOnchainConfig, - ) - require.NoError(t, err) - lggr := logger.TestLogger(t) - lggr.Infow("Setting Config on Oracle Contract", - "signers", signers, - "transmitters", transmitters, - "threshold", threshold, - "onchainConfig", onchainConfig, - "encodedConfigVersion", offchainConfigVersion, - ) - signerAddresses, err := OnchainPublicKeyToAddress(signers) - require.NoError(t, err) - transmitterAddresses, err := AccountToAddress(transmitters) - require.NoError(t, err) - - return &OCR2Config{ - Signers: signerAddresses, - Transmitters: transmitterAddresses, - F: threshold, - OnchainConfig: onchainConfig, - OffchainConfigVersion: offchainConfigVersion, - OffchainConfig: offchainConfig, - } -} - -func (c *CCIPContracts) SetupCommitOCR2Config(t *testing.T, commitOnchainConfig, commitOffchainConfig []byte) { - c.commitOCRConfig = c.DeriveOCR2Config(t, c.Oracles, commitOnchainConfig, commitOffchainConfig) - // Set the DON on the commit store - _, err := c.Dest.CommitStore.SetOCR2Config( - c.Dest.User, - c.commitOCRConfig.Signers, - c.commitOCRConfig.Transmitters, - c.commitOCRConfig.F, - c.commitOCRConfig.OnchainConfig, - c.commitOCRConfig.OffchainConfigVersion, - c.commitOCRConfig.OffchainConfig, - ) - require.NoError(t, err) - c.Dest.Chain.Commit() -} - -func (c *CCIPContracts) SetupExecOCR2Config(t *testing.T, execOnchainConfig, execOffchainConfig []byte) { - c.execOCRConfig = c.DeriveOCR2Config(t, c.Oracles, execOnchainConfig, execOffchainConfig) - // Same DON on the offramp - _, err := c.Dest.OffRamp.SetOCR2Config( - c.Dest.User, - c.execOCRConfig.Signers, - c.execOCRConfig.Transmitters, - c.execOCRConfig.F, - c.execOCRConfig.OnchainConfig, - c.execOCRConfig.OffchainConfigVersion, - c.execOCRConfig.OffchainConfig, - ) - require.NoError(t, err) - c.Dest.Chain.Commit() -} - -func (c *CCIPContracts) SetupOnchainConfig(t *testing.T, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig []byte) int64 { - // Note We do NOT set the payees, payment is done in the OCR2Base implementation - blockBeforeConfig, err := c.Dest.Chain.Client().BlockByNumber(tests.Context(t), nil) - require.NoError(t, err) - - c.SetupCommitOCR2Config(t, commitOnchainConfig, commitOffchainConfig) - c.SetupExecOCR2Config(t, execOnchainConfig, execOffchainConfig) - - return blockBeforeConfig.Number().Int64() -} - -func (c *CCIPContracts) SetupLockAndMintTokenPool( - sourceTokenAddress common.Address, - wrappedTokenName, - wrappedTokenSymbol string) (common.Address, *burn_mint_erc677.BurnMintERC677, error) { - // Deploy dest token & pool - destTokenAddress, _, _, err := burn_mint_erc677.DeployBurnMintERC677(c.Dest.User, c.Dest.Chain.Client(), wrappedTokenName, wrappedTokenSymbol, 18, big.NewInt(0)) - if err != nil { - return [20]byte{}, nil, err - } - c.Dest.Chain.Commit() - - destToken, err := burn_mint_erc677.NewBurnMintERC677(destTokenAddress, c.Dest.Chain.Client()) - if err != nil { - return [20]byte{}, nil, err - } - - destPoolAddress, _, destPool, err := burn_mint_token_pool.DeployBurnMintTokenPool( - c.Dest.User, - c.Dest.Chain.Client(), - destTokenAddress, - []common.Address{}, // pool originalSender allowList - c.Dest.ARMProxy.Address(), - c.Dest.Router.Address(), - ) - if err != nil { - return [20]byte{}, nil, err - } - c.Dest.Chain.Commit() - - _, err = destToken.GrantMintAndBurnRoles(c.Dest.User, destPoolAddress) - if err != nil { - return [20]byte{}, nil, err - } - - _, err = destPool.ApplyChainUpdates(c.Dest.User, - []burn_mint_token_pool.TokenPoolChainUpdate{ - { - RemoteChainSelector: c.Source.ChainSelector, - Allowed: true, - OutboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - InboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - }, - }) - if err != nil { - return [20]byte{}, nil, err - } - c.Dest.Chain.Commit() - - sourcePoolAddress, _, sourcePool, err := lock_release_token_pool.DeployLockReleaseTokenPool( - c.Source.User, - c.Source.Chain.Client(), - sourceTokenAddress, - []common.Address{}, // empty allowList at deploy time indicates pool has no original sender restrictions - c.Source.ARMProxy.Address(), - true, - c.Source.Router.Address(), - ) - if err != nil { - return [20]byte{}, nil, err - } - c.Source.Chain.Commit() - - // set onRamp as valid caller for source pool - _, err = sourcePool.ApplyChainUpdates(c.Source.User, []lock_release_token_pool.TokenPoolChainUpdate{ - { - RemoteChainSelector: c.Dest.ChainSelector, - Allowed: true, - OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - }, - }) - if err != nil { - return [20]byte{}, nil, err - } - c.Source.Chain.Commit() - - wrappedNativeAddress, err := c.Source.Router.GetWrappedNative(nil) - if err != nil { - return [20]byte{}, nil, err - } - - // native token is used as fee token - _, err = c.Source.PriceRegistry.UpdatePrices(c.Source.User, price_registry_1_2_0.InternalPriceUpdates{ - TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ - { - SourceToken: sourceTokenAddress, - UsdPerToken: big.NewInt(5), - }, - }, - GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{}, - }) - if err != nil { - return [20]byte{}, nil, err - } - c.Source.Chain.Commit() - - _, err = c.Source.PriceRegistry.ApplyFeeTokensUpdates(c.Source.User, []common.Address{wrappedNativeAddress}, nil) - if err != nil { - return [20]byte{}, nil, err - } - c.Source.Chain.Commit() - - // add new token pool created above - _, err = c.Source.OnRamp.ApplyPoolUpdates(c.Source.User, nil, []evm_2_evm_onramp.InternalPoolUpdate{ - { - Token: sourceTokenAddress, - Pool: sourcePoolAddress, - }, - }) - if err != nil { - return [20]byte{}, nil, err - } - - _, err = c.Dest.OffRamp.ApplyPoolUpdates(c.Dest.User, nil, []evm_2_evm_offramp.InternalPoolUpdate{ - { - Token: sourceTokenAddress, - Pool: destPoolAddress, - }, - }) - if err != nil { - return [20]byte{}, nil, err - } - c.Dest.Chain.Commit() - - return sourcePoolAddress, destToken, err -} - -func (c *CCIPContracts) SendMessage(t *testing.T, gasLimit, tokenAmount *big.Int, receiverAddr common.Address) { - extraArgs, err := GetEVMExtraArgsV1(gasLimit, false) - require.NoError(t, err) - msg := router.ClientEVM2AnyMessage{ - Receiver: MustEncodeAddress(t, receiverAddr), - Data: []byte("hello"), - TokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: c.Source.LinkToken.Address(), - Amount: tokenAmount, - }, - }, - FeeToken: c.Source.LinkToken.Address(), - ExtraArgs: extraArgs, - } - fee, err := c.Source.Router.GetFee(nil, c.Dest.ChainSelector, msg) - require.NoError(t, err) - // Currently no overhead and 1gwei dest gas price. So fee is simply gasLimit * gasPrice. - // require.Equal(t, new(big.Int).Mul(gasLimit, gasPrice).String(), fee.String()) - // Approve the fee amount + the token amount - _, err = c.Source.LinkToken.Approve(c.Source.User, c.Source.Router.Address(), new(big.Int).Add(fee, tokenAmount)) - require.NoError(t, err) - c.Source.Chain.Commit() - c.SendRequest(t, msg) -} - -func GetBalances(t *testing.T, brs []BalanceReq) (map[string]*big.Int, error) { - m := make(map[string]*big.Int) - for _, br := range brs { - m[br.Name] = br.Getter(t, br.Addr) - if m[br.Name] == nil { - return nil, fmt.Errorf("%v getter return nil", br.Name) - } - } - return m, nil -} - -func MustAddBigInt(a *big.Int, b string) *big.Int { - bi, _ := big.NewInt(0).SetString(b, 10) - return big.NewInt(0).Add(a, bi) -} - -func MustSubBigInt(a *big.Int, b string) *big.Int { - bi, _ := big.NewInt(0).SetString(b, 10) - return big.NewInt(0).Sub(a, bi) -} - -func MustEncodeAddress(t *testing.T, address common.Address) []byte { - bts, err := utils.ABIEncode(`[{"type":"address"}]`, address) - require.NoError(t, err) - return bts -} - -func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64) CCIPContracts { - sourceChain, sourceUser := testhelpers.SetupChain(t) - destChain, destUser := testhelpers.SetupChain(t) - - sourceChain.Commit() - destChain.Commit() - - armSourceAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( - sourceUser, - sourceChain.Client(), - ) - require.NoError(t, err) - sourceChain.Commit() - - sourceARM, err := mock_rmn_contract.NewMockRMNContract(armSourceAddress, sourceChain.Client()) - require.NoError(t, err) - armProxySourceAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( - sourceUser, - sourceChain.Client(), - armSourceAddress, - ) - require.NoError(t, err) - sourceChain.Commit() - - sourceARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxySourceAddress, sourceChain.Client()) - require.NoError(t, err) - - armDestAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( - destUser, - destChain.Client(), - ) - require.NoError(t, err) - destChain.Commit() - - armProxyDestAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( - destUser, - destChain.Client(), - armDestAddress, - ) - require.NoError(t, err) - destChain.Commit() - - destARM, err := mock_rmn_contract.NewMockRMNContract(armDestAddress, destChain.Client()) - require.NoError(t, err) - destARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxyDestAddress, destChain.Client()) - require.NoError(t, err) - - // Deploy link token and pool on source chain - sourceLinkTokenAddress, _, _, err := link_token_interface.DeployLinkToken(sourceUser, sourceChain.Client()) - require.NoError(t, err) - sourceChain.Commit() - sourceLinkToken, err := link_token_interface.NewLinkToken(sourceLinkTokenAddress, sourceChain.Client()) - require.NoError(t, err) - - // Create router - sourceWeth9addr, _, _, err := weth9.DeployWETH9(sourceUser, sourceChain.Client()) - require.NoError(t, err) - sourceChain.Commit() - - sourceWrapped, err := weth9.NewWETH9(sourceWeth9addr, sourceChain.Client()) - require.NoError(t, err) - - sourceRouterAddress, _, _, err := router.DeployRouter(sourceUser, sourceChain.Client(), sourceWeth9addr, armProxySourceAddress) - require.NoError(t, err) - sourceChain.Commit() - - sourceRouter, err := router.NewRouter(sourceRouterAddress, sourceChain.Client()) - require.NoError(t, err) - - sourceWeth9PoolAddress, _, _, err := lock_release_token_pool_1_0_0.DeployLockReleaseTokenPool( - sourceUser, - sourceChain.Client(), - sourceWeth9addr, - []common.Address{}, - armProxySourceAddress, - ) - require.NoError(t, err) - sourceChain.Commit() - - sourceWeth9Pool, err := lock_release_token_pool_1_0_0.NewLockReleaseTokenPool(sourceWeth9PoolAddress, sourceChain.Client()) - require.NoError(t, err) - - sourcePoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( - sourceUser, - sourceChain.Client(), - sourceLinkTokenAddress, - []common.Address{}, - armProxySourceAddress, - true, - sourceRouterAddress, - ) - require.NoError(t, err) - sourceChain.Commit() - sourcePool, err := lock_release_token_pool.NewLockReleaseTokenPool(sourcePoolAddress, sourceChain.Client()) - require.NoError(t, err) - - // Deploy custom token pool source - sourceCustomTokenAddress, _, _, err := link_token_interface.DeployLinkToken(sourceUser, sourceChain.Client()) // Just re-use this, it's an ERC20. - require.NoError(t, err) - sourceCustomToken, err := link_token_interface.NewLinkToken(sourceCustomTokenAddress, sourceChain.Client()) - require.NoError(t, err) - destChain.Commit() - - // Deploy custom token pool dest - destCustomTokenAddress, _, _, err := link_token_interface.DeployLinkToken(destUser, destChain.Client()) // Just re-use this, it's an ERC20. - require.NoError(t, err) - destCustomToken, err := link_token_interface.NewLinkToken(destCustomTokenAddress, destChain.Client()) - require.NoError(t, err) - destChain.Commit() - - // Deploy and configure onramp - sourcePricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( - sourceUser, - sourceChain.Client(), - nil, - []common.Address{sourceLinkTokenAddress, sourceWeth9addr}, - 60*60*24*14, // two weeks - ) - require.NoError(t, err) - sourceChain.Commit() - - srcPriceRegistry, err := price_registry_1_2_0.NewPriceRegistry(sourcePricesAddress, sourceChain.Client()) - require.NoError(t, err) - - _, err = srcPriceRegistry.UpdatePrices(sourceUser, price_registry_1_2_0.InternalPriceUpdates{ - TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ - { - SourceToken: sourceLinkTokenAddress, - UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(20)), - }, - { - SourceToken: sourceWeth9addr, - UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2000)), - }, - }, - GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ - { - DestChainSelector: destChainSelector, - UsdPerUnitGas: big.NewInt(20000e9), - }, - }, - }) - require.NoError(t, err) - sourceChain.Commit() - - onRampAddress, _, _, err := evm_2_evm_onramp.DeployEVM2EVMOnRamp( - sourceUser, // user - sourceChain.Client(), // client - evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ - LinkToken: sourceLinkTokenAddress, - ChainSelector: sourceChainSelector, - DestChainSelector: destChainSelector, - DefaultTxGasLimit: 200_000, - MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), - PrevOnRamp: common.HexToAddress(""), - ArmProxy: armProxySourceAddress, // ARM - }, - evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ - Router: sourceRouterAddress, - MaxNumberOfTokensPerMsg: 5, - DestGasOverhead: 350_000, - DestGasPerPayloadByte: 16, - DestDataAvailabilityOverheadGas: 33_596, - DestGasPerDataAvailabilityByte: 16, - DestDataAvailabilityMultiplierBps: 6840, // 0.684 - PriceRegistry: sourcePricesAddress, - MaxDataBytes: 1e5, - MaxPerMsgGasLimit: 4_000_000, - }, - []evm_2_evm_onramp.InternalPoolUpdate{ - { - Token: sourceLinkTokenAddress, - Pool: sourcePoolAddress, - }, - { - Token: sourceWeth9addr, - Pool: sourceWeth9PoolAddress, - }, - }, - evm_2_evm_onramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: LinkUSDValue(100), - Rate: LinkUSDValue(1), - }, - []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ - { - Token: sourceLinkTokenAddress, - NetworkFeeUSDCents: 1_00, - GasMultiplierWeiPerEth: 1e18, - PremiumMultiplierWeiPerEth: 9e17, - Enabled: true, - }, - { - Token: sourceWeth9addr, - NetworkFeeUSDCents: 1_00, - GasMultiplierWeiPerEth: 1e18, - PremiumMultiplierWeiPerEth: 1e18, - Enabled: true, - }, - }, - []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ - { - Token: sourceLinkTokenAddress, - MinFeeUSDCents: 50, // $0.5 - MaxFeeUSDCents: 1_000_000_00, // $ 1 million - DeciBps: 5_0, // 5 bps - DestGasOverhead: 34_000, - DestBytesOverhead: 32, - }, - }, - []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, - ) - require.NoError(t, err) - sourceChain.Commit() - - onRamp, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(onRampAddress, sourceChain.Client()) - require.NoError(t, err) - _, err = sourcePool.ApplyChainUpdates( - sourceUser, - []lock_release_token_pool.TokenPoolChainUpdate{{ - RemoteChainSelector: DestChainSelector, - Allowed: true, - OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - }}, - ) - require.NoError(t, err) - _, err = sourceWeth9Pool.ApplyRampUpdates(sourceUser, - []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{{Ramp: onRampAddress, Allowed: true, - RateLimiterConfig: lock_release_token_pool_1_0_0.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - }}, - []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{}, - ) - require.NoError(t, err) - sourceChain.Commit() - _, err = sourceRouter.ApplyRampUpdates(sourceUser, []router.RouterOnRamp{{DestChainSelector: destChainSelector, OnRamp: onRampAddress}}, nil, nil) - require.NoError(t, err) - sourceChain.Commit() - - destWethaddr, _, _, err := weth9.DeployWETH9(destUser, destChain.Client()) - require.NoError(t, err) - destChain.Commit() - destWrapped, err := weth9.NewWETH9(destWethaddr, destChain.Client()) - require.NoError(t, err) - - // Create dest router - destRouterAddress, _, _, err := router.DeployRouter(destUser, destChain.Client(), destWethaddr, armProxyDestAddress) - require.NoError(t, err) - destChain.Commit() - destRouter, err := router.NewRouter(destRouterAddress, destChain.Client()) - require.NoError(t, err) - - // Deploy link token and pool on destination chain - destLinkTokenAddress, _, _, err := link_token_interface.DeployLinkToken(destUser, destChain.Client()) - require.NoError(t, err) - destChain.Commit() - destLinkToken, err := link_token_interface.NewLinkToken(destLinkTokenAddress, destChain.Client()) - require.NoError(t, err) - destPoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( - destUser, - destChain.Client(), - destLinkTokenAddress, - []common.Address{}, - armProxyDestAddress, - true, - destRouterAddress, - ) - require.NoError(t, err) - destChain.Commit() - destPool, err := lock_release_token_pool.NewLockReleaseTokenPool(destPoolAddress, destChain.Client()) - require.NoError(t, err) - destChain.Commit() - - // Float the offramp pool - o, err := destPool.Owner(nil) - require.NoError(t, err) - require.Equal(t, destUser.From.String(), o.String()) - _, err = destPool.SetRebalancer(destUser, destUser.From) - require.NoError(t, err) - _, err = destLinkToken.Approve(destUser, destPoolAddress, Link(200)) - require.NoError(t, err) - destChain.Commit() - _, err = destPool.ProvideLiquidity(destUser, Link(200)) - require.NoError(t, err) - destChain.Commit() - - destWrappedPoolAddress, _, _, err := lock_release_token_pool_1_0_0.DeployLockReleaseTokenPool( - destUser, - destChain.Client(), - destWethaddr, - []common.Address{}, - armProxyDestAddress, - ) - require.NoError(t, err) - destChain.Commit() - destWrappedPool, err := lock_release_token_pool_1_0_0.NewLockReleaseTokenPool(destWrappedPoolAddress, destChain.Client()) - require.NoError(t, err) - - poolFloatValue := big.NewInt(1e18) - - destUser.Value = poolFloatValue - _, err = destWrapped.Deposit(destUser) - require.NoError(t, err) - destChain.Commit() - destUser.Value = nil - - _, err = destWrapped.Transfer(destUser, destWrappedPool.Address(), poolFloatValue) - require.NoError(t, err) - destChain.Commit() - - // Deploy and configure ge offramp. - destPricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( - destUser, - destChain.Client(), - nil, - []common.Address{destLinkTokenAddress}, - 60*60*24*14, // two weeks - ) - require.NoError(t, err) - destChain.Commit() - - destPriceRegistry, err := price_registry_1_2_0.NewPriceRegistry(destPricesAddress, destChain.Client()) - require.NoError(t, err) - - // Deploy commit store. - commitStoreAddress, _, _, err := commit_store_1_2_0.DeployCommitStore( - destUser, // user - destChain.Client(), // client - commit_store_1_2_0.CommitStoreStaticConfig{ - ChainSelector: destChainSelector, - SourceChainSelector: sourceChainSelector, - OnRamp: onRamp.Address(), - ArmProxy: destARMProxy.Address(), - }, - ) - require.NoError(t, err) - destChain.Commit() - commitStore, err := commit_store_1_2_0.NewCommitStore(commitStoreAddress, destChain.Client()) - require.NoError(t, err) - - offRampAddress, _, _, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( - destUser, - destChain.Client(), - evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ - CommitStore: commitStore.Address(), - ChainSelector: destChainSelector, - SourceChainSelector: sourceChainSelector, - OnRamp: onRampAddress, - PrevOffRamp: common.HexToAddress(""), - ArmProxy: armProxyDestAddress, - }, - []common.Address{sourceLinkTokenAddress, sourceWeth9addr}, - []common.Address{destPoolAddress, destWrappedPool.Address()}, - evm_2_evm_offramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: LinkUSDValue(100), - Rate: LinkUSDValue(1), - }, - ) - require.NoError(t, err) - destChain.Commit() - - offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampAddress, destChain.Client()) - require.NoError(t, err) - _, err = destPool.ApplyChainUpdates(destUser, - []lock_release_token_pool.TokenPoolChainUpdate{{ - RemoteChainSelector: sourceChainSelector, - Allowed: true, - OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - }}, - ) - require.NoError(t, err) - - _, err = destWrappedPool.ApplyRampUpdates(destUser, - []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{}, - []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{{ - Ramp: offRampAddress, - Allowed: true, - RateLimiterConfig: lock_release_token_pool_1_0_0.RateLimiterConfig{ - IsEnabled: true, - Capacity: HundredLink, - Rate: big.NewInt(1e18), - }, - }}, - ) - require.NoError(t, err) - - destChain.Commit() - _, err = destPriceRegistry.ApplyPriceUpdatersUpdates(destUser, []common.Address{commitStoreAddress}, []common.Address{}) - require.NoError(t, err) - destChain.Commit() - - _, err = destRouter.ApplyRampUpdates(destUser, nil, - nil, []router.RouterOffRamp{{SourceChainSelector: sourceChainSelector, OffRamp: offRampAddress}}) - require.NoError(t, err) - destChain.Commit() - - // Deploy 2 revertable (one SS one non-SS) - revertingMessageReceiver1Address, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver(destUser, destChain.Client(), false) - require.NoError(t, err) - revertingMessageReceiver1, _ := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(revertingMessageReceiver1Address, destChain.Client()) - revertingMessageReceiver2Address, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver(destUser, destChain.Client(), false) - require.NoError(t, err) - revertingMessageReceiver2, _ := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(revertingMessageReceiver2Address, destChain.Client()) - // Need to commit here, or we will hit the block gas limit when deploying the executor - sourceChain.Commit() - destChain.Commit() - - // Ensure we have at least finality blocks. - for i := 0; i < 50; i++ { - sourceChain.Commit() - destChain.Commit() - } - - source := SourceChain{ - Common: Common{ - ChainID: sourceChainID, - ChainSelector: sourceChainSelector, - User: sourceUser, - Chain: sourceChain, - LinkToken: sourceLinkToken, - LinkTokenPool: sourcePool, - CustomToken: sourceCustomToken, - ARM: sourceARM, - ARMProxy: sourceARMProxy, - PriceRegistry: srcPriceRegistry, - WrappedNative: sourceWrapped, - WrappedNativePool: sourceWeth9Pool, - }, - Router: sourceRouter, - OnRamp: onRamp, - } - dest := DestinationChain{ - Common: Common{ - ChainID: destChainID, - ChainSelector: destChainSelector, - User: destUser, - Chain: destChain, - LinkToken: destLinkToken, - LinkTokenPool: destPool, - CustomToken: destCustomToken, - ARM: destARM, - ARMProxy: destARMProxy, - PriceRegistry: destPriceRegistry, - WrappedNative: destWrapped, - WrappedNativePool: destWrappedPool, - }, - CommitStore: commitStore, - Router: destRouter, - OffRamp: offRamp, - Receivers: []MaybeRevertReceiver{{Receiver: revertingMessageReceiver1, Strict: false}, {Receiver: revertingMessageReceiver2, Strict: true}}, - } - - return CCIPContracts{ - Source: source, - Dest: dest, - } -} - -func (c *CCIPContracts) SendRequest(t *testing.T, msg router.ClientEVM2AnyMessage) *types.Transaction { - tx, err := c.Source.Router.CcipSend(c.Source.User, c.Dest.ChainSelector, msg) - require.NoError(t, err) - testhelpers.ConfirmTxs(t, []*types.Transaction{tx}, c.Source.Chain) - return tx -} - -func (c *CCIPContracts) AssertExecState(t *testing.T, log logpoller.Log, state MessageExecutionState, offRampOpts ...common.Address) { - var offRamp *evm_2_evm_offramp.EVM2EVMOffRamp - var err error - if len(offRampOpts) > 0 { - offRamp, err = evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampOpts[0], c.Dest.Chain.Client()) - require.NoError(t, err) - } else { - require.NotNil(t, c.Dest.OffRamp, "no offRamp configured") - offRamp = c.Dest.OffRamp - } - executionStateChanged, err := offRamp.ParseExecutionStateChanged(log.ToGethLog()) - require.NoError(t, err) - if MessageExecutionState(executionStateChanged.State) != state { - t.Log("Execution failed", hexutil.Encode(executionStateChanged.ReturnData)) - t.Fail() - } -} - -func GetEVMExtraArgsV1(gasLimit *big.Int, strict bool) ([]byte, error) { - EVMV1Tag := []byte{0x97, 0xa6, 0x57, 0xc9} - - encodedArgs, err := utils.ABIEncode(`[{"type":"uint256"},{"type":"bool"}]`, gasLimit, strict) - if err != nil { - return nil, err - } - - return append(EVMV1Tag, encodedArgs...), nil -} - -type ManualExecArgs struct { - SourceChainID, DestChainID uint64 - DestUser *bind.TransactOpts - SourceChain, DestChain bind.ContractBackend - SourceStartBlock *big.Int // the block in/after which failed ccip-send transaction was triggered - DestStartBlock uint64 // the start block for filtering ReportAccepted event (including the failed seq num) - // in destination chain. if not provided to be derived by ApproxDestStartBlock method - DestLatestBlockNum uint64 // current block number in destination - DestDeployedAt uint64 // destination block number for the initial destination contract deployment. - // Can be any number before the tx was reverted in destination chain. Preferably this needs to be set up with - // a value greater than zero to avoid performance issue in locating approximate destination block - SendReqLogIndex uint // log index of the CCIPSendRequested log in source chain - SendReqTxHash string // tx hash of the ccip-send transaction for which execution was reverted - CommitStore string - OnRamp string - OffRamp string - SeqNr uint64 - GasLimit *big.Int -} - -// ApproxDestStartBlock attempts to locate a block in destination chain with timestamp closest to the timestamp of the block -// in source chain in which ccip-send transaction was included -// it uses binary search to locate the block with the closest timestamp -// if the block located has a timestamp greater than the timestamp of mentioned source block -// it just returns the first block found with lesser timestamp of the source block -// providing a value of args.DestDeployedAt ensures better performance by reducing the range of block numbers to be traversed -func (args *ManualExecArgs) ApproxDestStartBlock(ctx context.Context) error { - sourceBlockHdr, err := args.SourceChain.HeaderByNumber(ctx, args.SourceStartBlock) - if err != nil { - return err - } - sendTxTime := sourceBlockHdr.Time - maxBlockNum := args.DestLatestBlockNum - // setting this to an approx value of 1000 considering destination chain would have at least 1000 blocks before the transaction started - minBlockNum := args.DestDeployedAt - closestBlockNum := uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) - var closestBlockHdr *types.Header - closestBlockHdr, err = args.DestChain.HeaderByNumber(ctx, new(big.Int).SetUint64(closestBlockNum)) - if err != nil { - return err - } - // to reduce the number of RPC calls increase the value of blockOffset - blockOffset := uint64(10) - for { - blockNum := closestBlockHdr.Number.Uint64() - if minBlockNum > maxBlockNum { - break - } - timeDiff := math.Abs(float64(closestBlockHdr.Time - sendTxTime)) - // break if the difference in timestamp is lesser than 1 minute - if timeDiff < 60 { - break - } else if closestBlockHdr.Time > sendTxTime { - maxBlockNum = blockNum - 1 - } else { - minBlockNum = blockNum + 1 - } - closestBlockNum = uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) - closestBlockHdr, err = args.DestChain.HeaderByNumber(ctx, new(big.Int).SetUint64(closestBlockNum)) - if err != nil { - return err - } - } - - for closestBlockHdr.Time > sendTxTime { - closestBlockNum = closestBlockNum - blockOffset - if closestBlockNum <= 0 { - return fmt.Errorf("approx destination blocknumber not found") - } - closestBlockHdr, err = args.DestChain.HeaderByNumber(ctx, new(big.Int).SetUint64(closestBlockNum)) - if err != nil { - return err - } - } - args.DestStartBlock = closestBlockHdr.Number.Uint64() - fmt.Println("using approx destination start block number", args.DestStartBlock) - return nil -} - -func (args *ManualExecArgs) FindSeqNrFromCCIPSendRequested() (uint64, error) { - var seqNr uint64 - onRampContract, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(args.OnRamp), args.SourceChain) - if err != nil { - return seqNr, err - } - iterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ - Start: args.SourceStartBlock.Uint64(), - }) - if err != nil { - return seqNr, err - } - for iterator.Next() { - if iterator.Event.Raw.Index == args.SendReqLogIndex && - iterator.Event.Raw.TxHash.Hex() == args.SendReqTxHash { - seqNr = iterator.Event.Message.SequenceNumber - break - } - } - if seqNr == 0 { - return seqNr, - fmt.Errorf("no CCIPSendRequested logs found for logIndex %d starting from block number %d", args.SendReqLogIndex, args.SourceStartBlock) - } - return seqNr, nil -} - -func (args *ManualExecArgs) ExecuteManually(ctx context.Context) (*types.Transaction, error) { - if args.SourceChainID == 0 || - args.DestChainID == 0 || - args.DestUser == nil { - return nil, fmt.Errorf("chain ids and owners are mandatory for source and dest chain") - } - if !common.IsHexAddress(args.CommitStore) || - !common.IsHexAddress(args.OffRamp) || - !common.IsHexAddress(args.OnRamp) { - return nil, fmt.Errorf("contract addresses must be valid hex address") - } - if args.SendReqTxHash == "" { - return nil, fmt.Errorf("tx hash of ccip-send request are required") - } - if args.SourceStartBlock == nil { - return nil, fmt.Errorf("must provide the value of source block in/after which ccip-send tx was included") - } - if args.SeqNr == 0 { - if args.SendReqLogIndex == 0 { - return nil, fmt.Errorf("must provide the value of log index of ccip-send request") - } - // locate seq nr from CCIPSendRequested log - seqNr, err := args.FindSeqNrFromCCIPSendRequested() - if err != nil { - return nil, err - } - args.SeqNr = seqNr - } - commitStore, err := commit_store_1_2_0.NewCommitStore(common.HexToAddress(args.CommitStore), args.DestChain) - if err != nil { - return nil, err - } - if args.DestStartBlock < 1 { - err = args.ApproxDestStartBlock(ctx) - if err != nil { - return nil, err - } - } - iterator, err := commitStore.FilterReportAccepted(&bind.FilterOpts{Start: args.DestStartBlock}) - if err != nil { - return nil, err - } - - var commitReport *commit_store_1_2_0.CommitStoreCommitReport - for iterator.Next() { - if iterator.Event.Report.Interval.Min <= args.SeqNr && iterator.Event.Report.Interval.Max >= args.SeqNr { - commitReport = &iterator.Event.Report - fmt.Println("Found root") - break - } - } - if commitReport == nil { - return nil, fmt.Errorf("unable to find seq num %d in commit report", args.SeqNr) - } - - return args.execute(commitReport) -} - -func (args *ManualExecArgs) execute(report *commit_store_1_2_0.CommitStoreCommitReport) (*types.Transaction, error) { - log.Info().Msg("Executing request manually") - seqNr := args.SeqNr - // Build a merkle tree for the report - mctx := hashutil.NewKeccak() - onRampContract, err := evm_2_evm_onramp_1_2_0.NewEVM2EVMOnRamp(common.HexToAddress(args.OnRamp), args.SourceChain) - if err != nil { - return nil, err - } - leafHasher := v1_2_0.NewLeafHasher(args.SourceChainID, args.DestChainID, common.HexToAddress(args.OnRamp), mctx, onRampContract) - if leafHasher == nil { - return nil, fmt.Errorf("unable to create leaf hasher") - } - - var leaves [][32]byte - var curr, prove int - var msgs []evm_2_evm_offramp.InternalEVM2EVMMessage - var manualExecGasLimits []*big.Int - var tokenData [][][]byte - sendRequestedIterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ - Start: args.SourceStartBlock.Uint64(), - }) - if err != nil { - return nil, err - } - for sendRequestedIterator.Next() { - if sendRequestedIterator.Event.Message.SequenceNumber <= report.Interval.Max && - sendRequestedIterator.Event.Message.SequenceNumber >= report.Interval.Min { - fmt.Println("Found seq num", sendRequestedIterator.Event.Message.SequenceNumber, report.Interval) - hash, err2 := leafHasher.HashLeaf(sendRequestedIterator.Event.Raw) - if err2 != nil { - return nil, err2 - } - leaves = append(leaves, hash) - if sendRequestedIterator.Event.Message.SequenceNumber == seqNr { - fmt.Printf("Found proving %d %+v\n", curr, sendRequestedIterator.Event.Message) - var tokensAndAmounts []evm_2_evm_offramp.ClientEVMTokenAmount - for _, tokenAndAmount := range sendRequestedIterator.Event.Message.TokenAmounts { - tokensAndAmounts = append(tokensAndAmounts, evm_2_evm_offramp.ClientEVMTokenAmount{ - Token: tokenAndAmount.Token, - Amount: tokenAndAmount.Amount, - }) - } - msg := evm_2_evm_offramp.InternalEVM2EVMMessage{ - SourceChainSelector: sendRequestedIterator.Event.Message.SourceChainSelector, - Sender: sendRequestedIterator.Event.Message.Sender, - Receiver: sendRequestedIterator.Event.Message.Receiver, - SequenceNumber: sendRequestedIterator.Event.Message.SequenceNumber, - GasLimit: sendRequestedIterator.Event.Message.GasLimit, - Strict: sendRequestedIterator.Event.Message.Strict, - Nonce: sendRequestedIterator.Event.Message.Nonce, - FeeToken: sendRequestedIterator.Event.Message.FeeToken, - FeeTokenAmount: sendRequestedIterator.Event.Message.FeeTokenAmount, - Data: sendRequestedIterator.Event.Message.Data, - TokenAmounts: tokensAndAmounts, - SourceTokenData: sendRequestedIterator.Event.Message.SourceTokenData, - MessageId: sendRequestedIterator.Event.Message.MessageId, - } - msgs = append(msgs, msg) - if args.GasLimit != nil { - msg.GasLimit = args.GasLimit - } - manualExecGasLimits = append(manualExecGasLimits, msg.GasLimit) - var msgTokenData [][]byte - for range sendRequestedIterator.Event.Message.TokenAmounts { - msgTokenData = append(msgTokenData, []byte{}) - } - - tokenData = append(tokenData, msgTokenData) - prove = curr - } - curr++ - } - } - sendRequestedIterator.Close() - if msgs == nil { - return nil, fmt.Errorf("unable to find msg with seqNr %d", seqNr) - } - tree, err := merklemulti.NewTree(mctx, leaves) - if err != nil { - return nil, err - } - if tree.Root() != report.MerkleRoot { - return nil, fmt.Errorf("root doesn't match") - } - - proof, err := tree.Prove([]int{prove}) - if err != nil { - return nil, err - } - - offRampProof := evm_2_evm_offramp.InternalExecutionReport{ - Messages: msgs, - OffchainTokenData: tokenData, - Proofs: proof.Hashes, - ProofFlagBits: abihelpers.ProofFlagsToBits(proof.SourceFlags), - } - offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(args.OffRamp), args.DestChain) - if err != nil { - return nil, err - } - // Execute. - return offRamp.ManuallyExecute(args.DestUser, offRampProof, manualExecGasLimits) -} - -func (c *CCIPContracts) ExecuteMessage( - t *testing.T, - req logpoller.Log, - txHash common.Hash, - destStartBlock uint64, -) uint64 { - t.Log("Executing request manually") - ctx := tests.Context(t) - sendReqReceipt, err := c.Source.Chain.Client().TransactionReceipt(ctx, txHash) - require.NoError(t, err) - destLatest, err := c.Dest.Chain.Client().BlockByNumber(context.Background(), nil) - require.NoError(t, err) - args := ManualExecArgs{ - SourceChainID: c.Source.ChainID, - DestChainID: c.Dest.ChainID, - DestUser: c.Dest.User, - SourceChain: c.Source.Chain.Client(), - DestChain: c.Dest.Chain.Client(), - SourceStartBlock: sendReqReceipt.BlockNumber, - DestStartBlock: destStartBlock, - DestLatestBlockNum: destLatest.NumberU64(), - SendReqLogIndex: uint(req.LogIndex), - SendReqTxHash: txHash.String(), - CommitStore: c.Dest.CommitStore.Address().String(), - OnRamp: c.Source.OnRamp.Address().String(), - OffRamp: c.Dest.OffRamp.Address().String(), - } - tx, err := args.ExecuteManually(ctx) - require.NoError(t, err) - c.Dest.Chain.Commit() - c.Source.Chain.Commit() - rec, err := c.Dest.Chain.Client().TransactionReceipt(tests.Context(t), tx.Hash()) - require.NoError(t, err) - require.Equal(t, uint64(1), rec.Status, "manual execution failed") - t.Logf("Manual Execution completed for seqNum %d", args.SeqNr) - return args.SeqNr -} - -func GetBalance(t *testing.T, chain bind.ContractBackend, tokenAddr common.Address, addr common.Address) *big.Int { - token, err := link_token_interface.NewLinkToken(tokenAddr, chain) - require.NoError(t, err) - bal, err := token.BalanceOf(nil, addr) - require.NoError(t, err) - return bal -} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go deleted file mode 100644 index 30aaebd4e9e..00000000000 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go +++ /dev/null @@ -1,1053 +0,0 @@ -package testhelpers_1_4_0 - -import ( - "context" - "encoding/hex" - "fmt" - "math" - "math/big" - "net/http" - "net/http/httptest" - "strconv" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - types3 "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/google/uuid" - "github.com/hashicorp/consul/sdk/freeport" - "github.com/jmoiron/sqlx" - "github.com/onsi/gomega" - "github.com/pkg/errors" - "k8s.io/utils/ptr" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" - types4 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" - - pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - evmUtils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - configv2 "github.com/smartcontractkit/chainlink/v2/core/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/logger/audit" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - feeds2 "github.com/smartcontractkit/chainlink/v2/core/services/feeds" - feedsMocks "github.com/smartcontractkit/chainlink/v2/core/services/feeds/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - ksMocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" - integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - clutils "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" - "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" - "github.com/smartcontractkit/chainlink/v2/plugins" -) - -const ( - execSpecTemplate = ` - type = "offchainreporting2" - schemaVersion = 1 - name = "ccip-exec-1" - externalJobID = "67ffad71-d90f-4fe3-b4e4-494924b707fb" - forwardingAllowed = false - maxTaskDuration = "0s" - contractID = "%s" - contractConfigConfirmations = 1 - contractConfigTrackerPollInterval = "20s" - ocrKeyBundleID = "%s" - relay = "evm" - pluginType = "ccip-execution" - transmitterID = "%s" - - [relayConfig] - chainID = 1_337 - - [pluginConfig] - destStartBlock = 50 - - [pluginConfig.USDCConfig] - AttestationAPI = "http://blah.com" - SourceMessageTransmitterAddress = "%s" - SourceTokenAddress = "%s" - AttestationAPITimeoutSeconds = 10 - ` - commitSpecTemplatePipeline = ` - type = "offchainreporting2" - schemaVersion = 1 - name = "ccip-commit-1" - externalJobID = "13c997cf-1a14-4ab7-9068-07ee6d2afa55" - forwardingAllowed = false - maxTaskDuration = "0s" - contractID = "%s" - contractConfigConfirmations = 1 - contractConfigTrackerPollInterval = "20s" - ocrKeyBundleID = "%s" - relay = "evm" - pluginType = "ccip-commit" - transmitterID = "%s" - - [relayConfig] - chainID = 1_337 - - [pluginConfig] - destStartBlock = 50 - offRamp = "%s" - tokenPricesUSDPipeline = """ - %s - """ - ` - commitSpecTemplateDynamicPriceGetter = ` - type = "offchainreporting2" - schemaVersion = 1 - name = "ccip-commit-1" - externalJobID = "13c997cf-1a14-4ab7-9068-07ee6d2afa55" - forwardingAllowed = false - maxTaskDuration = "0s" - contractID = "%s" - contractConfigConfirmations = 1 - contractConfigTrackerPollInterval = "20s" - ocrKeyBundleID = "%s" - relay = "evm" - pluginType = "ccip-commit" - transmitterID = "%s" - - [relayConfig] - chainID = 1_337 - - [pluginConfig] - destStartBlock = 50 - offRamp = "%s" - priceGetterConfig = """ - %s - """ - ` -) - -type Node struct { - App chainlink.Application - Transmitter common.Address - PaymentReceiver common.Address - KeyBundle ocr2key.KeyBundle -} - -func (node *Node) FindJobIDForContract(t *testing.T, addr common.Address) int32 { - jobs := node.App.JobSpawner().ActiveJobs() - for _, j := range jobs { - if j.Type == job.OffchainReporting2 && j.OCR2OracleSpec.ContractID == addr.Hex() { - return j.ID - } - } - t.Fatalf("Could not find job for contract %s", addr.Hex()) - return 0 -} - -func (node *Node) EventuallyNodeUsesUpdatedPriceRegistry(t *testing.T, ccipContracts CCIPIntegrationTestHarness) logpoller.Log { - c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) - require.NoError(t, err) - var log logpoller.Log - gomega.NewGomegaWithT(t).Eventually(func() bool { - ccipContracts.Source.Chain.Commit() - ccipContracts.Dest.Chain.Commit() - log, err := c.LogPoller().LatestLogByEventSigWithConfs( - testutils.Context(t), - v1_2_0.UsdPerUnitGasUpdated, - ccipContracts.Dest.PriceRegistry.Address(), - 0, - ) - // err can be transient errors such as sql row set empty - if err != nil { - return false - } - return log != nil - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is not using updated price registry %s", ccipContracts.Dest.PriceRegistry.Address().Hex()) - return log -} - -func (node *Node) EventuallyNodeUsesNewCommitConfig(t *testing.T, ccipContracts CCIPIntegrationTestHarness, commitCfg ccipdata.CommitOnchainConfig) logpoller.Log { - c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) - require.NoError(t, err) - var log logpoller.Log - gomega.NewGomegaWithT(t).Eventually(func() bool { - ccipContracts.Source.Chain.Commit() - ccipContracts.Dest.Chain.Commit() - log, err := c.LogPoller().LatestLogByEventSigWithConfs( - testutils.Context(t), - evmrelay.OCR2AggregatorLogDecoder.EventSig(), - ccipContracts.Dest.CommitStore.Address(), - 0, - ) - require.NoError(t, err) - var latestCfg ccipdata.CommitOnchainConfig - if log != nil { - latestCfg, err = DecodeCommitOnChainConfig(log.Data) - require.NoError(t, err) - return latestCfg == commitCfg - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is using old cfg") - return log -} - -func (node *Node) EventuallyNodeUsesNewExecConfig(t *testing.T, ccipContracts CCIPIntegrationTestHarness, execCfg v1_2_0.ExecOnchainConfig) logpoller.Log { - c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) - require.NoError(t, err) - var log logpoller.Log - gomega.NewGomegaWithT(t).Eventually(func() bool { - ccipContracts.Source.Chain.Commit() - ccipContracts.Dest.Chain.Commit() - log, err := c.LogPoller().LatestLogByEventSigWithConfs( - testutils.Context(t), - evmrelay.OCR2AggregatorLogDecoder.EventSig(), - ccipContracts.Dest.OffRamp.Address(), - 0, - ) - require.NoError(t, err) - var latestCfg v1_2_0.ExecOnchainConfig - if log != nil { - latestCfg, err = DecodeExecOnChainConfig(log.Data) - require.NoError(t, err) - return latestCfg == execCfg - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is using old cfg") - return log -} - -func (node *Node) EventuallyHasReqSeqNum(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, onRamp common.Address, seqNum int) logpoller.Log { - c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Source.ChainID, 10)) - require.NoError(t, err) - var log logpoller.Log - gomega.NewGomegaWithT(t).Eventually(func() bool { - ccipContracts.Source.Chain.Commit() - ccipContracts.Dest.Chain.Commit() - lgs, err := c.LogPoller().LogsDataWordRange( - testutils.Context(t), - v1_2_0.CCIPSendRequestEventSig, - onRamp, - v1_2_0.CCIPSendRequestSeqNumIndex, - abihelpers.EvmWord(uint64(seqNum)), - abihelpers.EvmWord(uint64(seqNum)), - 1, - ) - require.NoError(t, err) - t.Log("Send requested", len(lgs)) - if len(lgs) == 1 { - log = lgs[0] - return true - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "eventually has seq num") - return log -} - -func (node *Node) EventuallyHasExecutedSeqNums(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, offRamp common.Address, minSeqNum int, maxSeqNum int) []logpoller.Log { - c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) - require.NoError(t, err) - var logs []logpoller.Log - gomega.NewGomegaWithT(t).Eventually(func() bool { - ccipContracts.Source.Chain.Commit() - ccipContracts.Dest.Chain.Commit() - lgs, err := c.LogPoller().IndexedLogsTopicRange( - testutils.Context(t), - v1_2_0.ExecutionStateChangedEvent, - offRamp, - v1_2_0.ExecutionStateChangedSeqNrIndex, - abihelpers.EvmWord(uint64(minSeqNum)), - abihelpers.EvmWord(uint64(maxSeqNum)), - 1, - ) - require.NoError(t, err) - t.Logf("Have executed logs %d want %d", len(lgs), maxSeqNum-minSeqNum+1) - if len(lgs) == maxSeqNum-minSeqNum+1 { - logs = lgs - t.Logf("Seq Num %d-%d executed", minSeqNum, maxSeqNum) - return true - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "eventually has not executed seq num") - return logs -} - -func (node *Node) ConsistentlySeqNumHasNotBeenExecuted(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, offRamp common.Address, seqNum int) logpoller.Log { - c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) - require.NoError(t, err) - var log logpoller.Log - gomega.NewGomegaWithT(t).Consistently(func() bool { - ccipContracts.Source.Chain.Commit() - ccipContracts.Dest.Chain.Commit() - lgs, err := c.LogPoller().IndexedLogsTopicRange( - testutils.Context(t), - v1_2_0.ExecutionStateChangedEvent, - offRamp, - v1_2_0.ExecutionStateChangedSeqNrIndex, - abihelpers.EvmWord(uint64(seqNum)), - abihelpers.EvmWord(uint64(seqNum)), - 1, - ) - require.NoError(t, err) - t.Log("Executed logs", lgs) - if len(lgs) == 1 { - log = lgs[0] - return true - } - return false - }, 10*time.Second, 1*time.Second).Should(gomega.BeFalse(), "seq number got executed") - return log -} - -func (node *Node) AddJob(t *testing.T, spec *integrationtesthelpers.OCR2TaskJobSpec) { - specString, err := spec.String() - require.NoError(t, err) - ccipJob, err := validate.ValidatedOracleSpecToml( - testutils.Context(t), - node.App.GetConfig().OCR2(), - node.App.GetConfig().Insecure(), - specString, - // FIXME Ani - nil, - ) - require.NoError(t, err) - err = node.App.AddJobV2(tests.Context(t), &ccipJob) - require.NoError(t, err) -} - -func (node *Node) AddBootstrapJob(t *testing.T, spec *integrationtesthelpers.OCR2TaskJobSpec) { - specString, err := spec.String() - require.NoError(t, err) - ccipJob, err := ocrbootstrap.ValidatedBootstrapSpecToml(specString) - require.NoError(t, err) - err = node.App.AddJobV2(tests.Context(t), &ccipJob) - require.NoError(t, err) -} - -func (node *Node) AddJobsWithSpec(t *testing.T, jobSpec *integrationtesthelpers.OCR2TaskJobSpec) { - // set node specific values - jobSpec.OCR2OracleSpec.OCRKeyBundleID.SetValid(node.KeyBundle.ID()) - jobSpec.OCR2OracleSpec.TransmitterID.SetValid(node.Transmitter.Hex()) - node.AddJob(t, jobSpec) -} - -func setupNodeCCIP( - t *testing.T, - owner *bind.TransactOpts, - port int64, - dbName string, - sourceChain *simulated.Backend, destChain *simulated.Backend, - sourceChainID *big.Int, destChainID *big.Int, - bootstrapPeerID string, - bootstrapPort int64, -) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) { - trueRef, falseRef := true, false - - // Do not want to load fixtures as they contain a dummy chainID. - loglevel := configv2.LogLevel(zap.DebugLevel) - config, db := heavyweight.FullTestDBNoFixturesV2(t, func(c *chainlink.Config, _ *chainlink.Secrets) { - p2pAddresses := []string{ - fmt.Sprintf("127.0.0.1:%d", port), - } - c.Log.Level = &loglevel - c.Feature.UICSAKeys = &trueRef - c.Feature.FeedsManager = &trueRef - c.OCR.Enabled = &falseRef - c.OCR.DefaultTransactionQueueDepth = ptr.To[uint32](200) - c.OCR2.Enabled = &trueRef - c.Feature.LogPoller = &trueRef - c.P2P.V2.Enabled = &trueRef - - dur, err := config.NewDuration(500 * time.Millisecond) - if err != nil { - panic(err) - } - c.P2P.V2.DeltaDial = &dur - - dur2, err := config.NewDuration(5 * time.Second) - if err != nil { - panic(err) - } - - c.P2P.V2.DeltaReconcile = &dur2 - c.P2P.V2.ListenAddresses = &p2pAddresses - c.P2P.V2.AnnounceAddresses = &p2pAddresses - - c.EVM = []*v2.EVMConfig{createConfigV2Chain(sourceChainID), createConfigV2Chain(destChainID)} - - if bootstrapPeerID != "" { - // Supply the bootstrap IP and port as a V2 peer address - c.P2P.V2.DefaultBootstrappers = &[]commontypes.BootstrapperLocator{ - { - PeerID: bootstrapPeerID, Addrs: []string{ - fmt.Sprintf("127.0.0.1:%d", bootstrapPort), - }, - }, - } - } - }) - - lggr := logger.TestLogger(t) - - // The in-memory geth sim does not let you create a custom ChainID, it will always be 1337. - // In particular this means that if you sign an eip155 tx, the chainID used MUST be 1337 - // and the CHAINID op code will always emit 1337. To work around this to simulate a "multichain" - // test, we fake different chainIDs using the wrapped sim cltest.SimulatedBackend so the RPC - // appears to operate on different chainIDs and we use an EthKeyStoreSim wrapper which always - // signs 1337 see https://github.com/smartcontractkit/chainlink-ccip/blob/a24dd436810250a458d27d8bb3fb78096afeb79c/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go#L35 - sourceClient := client.NewSimulatedBackendClient(t, sourceChain, sourceChainID) - destClient := client.NewSimulatedBackendClient(t, destChain, destChainID) - csaKeyStore := ksMocks.NewCSA(t) - - key, err := csakey.NewV2() - require.NoError(t, err) - csaKeyStore.On("GetAll").Return([]csakey.KeyV2{key}, nil) - keyStore := NewKsa(db, lggr, csaKeyStore) - - simEthKeyStore := testhelpers.EthKeyStoreSim{ - ETHKS: keyStore.Eth(), - CSAKS: keyStore.CSA(), - } - mailMon := mailbox.NewMonitor("CCIP", lggr.Named("Mailbox")) - evmOpts := chainlink.EVMFactoryConfig{ - ChainOpts: legacyevm.ChainOpts{ - AppConfig: config, - GenEthClient: func(chainID *big.Int) client.Client { - if chainID.String() == sourceChainID.String() { - return sourceClient - } else if chainID.String() == destChainID.String() { - return destClient - } - t.Fatalf("invalid chain ID %v", chainID.String()) - return nil - }, - MailMon: mailMon, - DS: db, - }, - CSAETHKeystore: simEthKeyStore, - } - - beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(keyStore) - require.NoError(t, err) - - loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex) - relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: loopRegistry, - GRPCOpts: loop.GRPCOpts{}, - CapabilitiesRegistry: coretypes.NewCapabilitiesRegistry(t), - } - testCtx := testutils.Context(t) - // evm alway enabled for backward compatibility - initOps := []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitEVM(testCtx, relayerFactory, evmOpts), - } - - relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) - if err != nil { - t.Fatal(err) - } - - app, err := chainlink.NewApplication(chainlink.ApplicationOpts{ - Config: config, - DS: db, - KeyStore: keyStore, - RelayerChainInteroperators: relayChainInterops, - Logger: lggr, - ExternalInitiatorManager: nil, - CloseLogger: lggr.Sync, - UnrestrictedHTTPClient: &http.Client{}, - RestrictedHTTPClient: &http.Client{}, - AuditLogger: audit.NoopLogger, - MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex), - }) - ctx := testutils.Context(t) - require.NoError(t, err) - require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) - _, err = app.GetKeyStore().P2P().Create(ctx) - require.NoError(t, err) - - p2pIDs, err := app.GetKeyStore().P2P().GetAll() - require.NoError(t, err) - require.Len(t, p2pIDs, 1) - peerID := p2pIDs[0].PeerID() - - _, err = app.GetKeyStore().Eth().Create(testCtx, destChainID) - require.NoError(t, err) - sendingKeys, err := app.GetKeyStore().Eth().EnabledKeysForChain(testCtx, destChainID) - require.NoError(t, err) - require.Len(t, sendingKeys, 1) - transmitter := sendingKeys[0].Address - s, err := app.GetKeyStore().Eth().GetState(testCtx, sendingKeys[0].ID(), destChainID) - require.NoError(t, err) - lggr.Debug(fmt.Sprintf("Transmitter address %s chainID %s", transmitter, s.EVMChainID.String())) - - // Fund the commitTransmitter address with some ETH - destChain.Commit() - n, err := destChain.Client().NonceAt(tests.Context(t), owner.From, nil) - require.NoError(t, err) - tx := types3.NewTransaction(n, transmitter, big.NewInt(1000000000000000000), 21000, big.NewInt(1000000000), nil) - signedTx, err := owner.Signer(owner.From, tx) - require.NoError(t, err) - err = destChain.Client().SendTransaction(tests.Context(t), signedTx) - require.NoError(t, err) - destChain.Commit() - - kb, err := app.GetKeyStore().OCR2().Create(ctx, chaintype.EVM) - require.NoError(t, err) - return app, peerID.Raw(), transmitter, kb -} - -func createConfigV2Chain(chainId *big.Int) *v2.EVMConfig { - // NOTE: For the executor jobs, the default of 500k is insufficient for a 3 message batch - defaultGasLimit := uint64(5000000) - tr := true - - sourceC := v2.Defaults((*evmUtils.Big)(chainId)) - sourceC.GasEstimator.LimitDefault = &defaultGasLimit - fixedPrice := "FixedPrice" - sourceC.GasEstimator.Mode = &fixedPrice - d, _ := config.NewDuration(100 * time.Millisecond) - sourceC.LogPollInterval = &d - fd := uint32(2) - sourceC.FinalityDepth = &fd - return &v2.EVMConfig{ - ChainID: (*evmUtils.Big)(chainId), - Enabled: &tr, - Chain: sourceC, - Nodes: v2.EVMNodes{&v2.Node{}}, - } -} - -type CCIPIntegrationTestHarness struct { - CCIPContracts - Nodes []Node - Bootstrap Node -} - -func SetupCCIPIntegrationTH(t *testing.T, sourceChainID, sourceChainSelector, destChainId, destChainSelector uint64) CCIPIntegrationTestHarness { - return CCIPIntegrationTestHarness{ - CCIPContracts: SetupCCIPContracts(t, sourceChainID, sourceChainSelector, destChainId, destChainSelector), - } -} - -func (c *CCIPIntegrationTestHarness) CreatePricesPipeline(t *testing.T) (string, *httptest.Server, *httptest.Server) { - linkUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - _, err := w.Write([]byte(`{"UsdPerLink": "8000000000000000000"}`)) - require.NoError(t, err) - })) - ethUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - _, err := w.Write([]byte(`{"UsdPerETH": "1700000000000000000000"}`)) - require.NoError(t, err) - })) - sourceWrappedNative, err := c.Source.Router.GetWrappedNative(nil) - require.NoError(t, err) - destWrappedNative, err := c.Dest.Router.GetWrappedNative(nil) - require.NoError(t, err) - tokenPricesUSDPipeline := fmt.Sprintf(` -// Price 1 -link [type=http method=GET url="%s"]; -link_parse [type=jsonparse path="UsdPerLink"]; -link->link_parse; -eth [type=http method=GET url="%s"]; -eth_parse [type=jsonparse path="UsdPerETH"]; -eth->eth_parse; -merge [type=merge left="{}" right="{\\\"%s\\\":$(link_parse), \\\"%s\\\":$(eth_parse), \\\"%s\\\":$(eth_parse)}"];`, - linkUSD.URL, ethUSD.URL, c.Dest.LinkToken.Address(), sourceWrappedNative, destWrappedNative) - - return tokenPricesUSDPipeline, linkUSD, ethUSD -} - -func (c *CCIPIntegrationTestHarness) AddAllJobs(t *testing.T, jobParams integrationtesthelpers.CCIPJobSpecParams) { - jobParams.OffRamp = c.Dest.OffRamp.Address() - - commitSpec, err := jobParams.CommitJobSpec() - require.NoError(t, err) - geExecutionSpec, err := jobParams.ExecutionJobSpec() - require.NoError(t, err) - nodes := c.Nodes - for _, node := range nodes { - node.AddJobsWithSpec(t, commitSpec) - node.AddJobsWithSpec(t, geExecutionSpec) - } -} - -func (c *CCIPIntegrationTestHarness) jobSpecProposal(t *testing.T, specTemplate string, f func() (*integrationtesthelpers.OCR2TaskJobSpec, error), feedsManagerId int64, version int32, opts ...any) feeds2.ProposeJobArgs { - spec, err := f() - require.NoError(t, err) - - args := []any{spec.OCR2OracleSpec.ContractID} - args = append(args, opts...) - - return feeds2.ProposeJobArgs{ - FeedsManagerID: feedsManagerId, - RemoteUUID: uuid.New(), - Multiaddrs: nil, - Version: version, - Spec: fmt.Sprintf(specTemplate, args...), - } -} - -func (c *CCIPIntegrationTestHarness) SetupFeedsManager(t *testing.T) { - ctx := testutils.Context(t) - for _, node := range c.Nodes { - f := node.App.GetFeedsService() - - managers, err := f.ListManagers(ctx) - require.NoError(t, err) - if len(managers) > 0 { - // Use at most one feeds manager, don't register if one already exists - continue - } - - secret := utils.RandomBytes32() - pkey, err := crypto.PublicKeyFromHex(hex.EncodeToString(secret[:])) - require.NoError(t, err) - - m := feeds2.RegisterManagerParams{ - Name: "CCIP", - URI: "http://localhost:8080", - PublicKey: *pkey, - } - - _, err = f.RegisterManager(testutils.Context(t), m) - require.NoError(t, err) - - connManager := feedsMocks.NewConnectionsManager(t) - connManager.On("GetClient", mock.Anything).Maybe().Return(NoopFeedsClient{}, nil) - connManager.On("Close").Maybe().Return() - connManager.On("IsConnected", mock.Anything).Maybe().Return(true) - f.Unsafe_SetConnectionsManager(connManager) - } -} - -func (c *CCIPIntegrationTestHarness) ApproveJobSpecs(t *testing.T, jobParams integrationtesthelpers.CCIPJobSpecParams) { - ctx := testutils.Context(t) - - for _, node := range c.Nodes { - f := node.App.GetFeedsService() - managers, err := f.ListManagers(ctx) - require.NoError(t, err) - require.Len(t, managers, 1, "expected exactly one feeds manager") - - execSpec := c.jobSpecProposal( - t, - execSpecTemplate, - jobParams.ExecutionJobSpec, - managers[0].ID, - 1, - node.KeyBundle.ID(), - node.Transmitter.Hex(), - utils.RandomAddress().String(), - utils.RandomAddress().String(), - ) - execId, err := f.ProposeJob(ctx, &execSpec) - require.NoError(t, err) - - err = f.ApproveSpec(ctx, execId, true) - require.NoError(t, err) - - var commitSpec feeds2.ProposeJobArgs - if jobParams.TokenPricesUSDPipeline != "" { - commitSpec = c.jobSpecProposal( - t, - commitSpecTemplatePipeline, - jobParams.CommitJobSpec, - managers[0].ID, - 2, - node.KeyBundle.ID(), - node.Transmitter.Hex(), - jobParams.OffRamp.String(), - jobParams.TokenPricesUSDPipeline, - ) - } else { - commitSpec = c.jobSpecProposal( - t, - commitSpecTemplateDynamicPriceGetter, - jobParams.CommitJobSpec, - managers[0].ID, - 2, - node.KeyBundle.ID(), - node.Transmitter.Hex(), - jobParams.OffRamp.String(), - jobParams.PriceGetterConfig, - ) - } - - commitId, err := f.ProposeJob(ctx, &commitSpec) - require.NoError(t, err) - - err = f.ApproveSpec(ctx, commitId, true) - require.NoError(t, err) - } -} - -func (c *CCIPIntegrationTestHarness) AllNodesHaveReqSeqNum(t *testing.T, seqNum int, onRampOpts ...common.Address) logpoller.Log { - var log logpoller.Log - nodes := c.Nodes - var onRamp common.Address - if len(onRampOpts) > 0 { - onRamp = onRampOpts[0] - } else { - require.NotNil(t, c.Source.OnRamp, "no onramp configured") - onRamp = c.Source.OnRamp.Address() - } - for _, node := range nodes { - log = node.EventuallyHasReqSeqNum(t, c, onRamp, seqNum) - } - return log -} - -func (c *CCIPIntegrationTestHarness) AllNodesHaveExecutedSeqNums(t *testing.T, minSeqNum int, maxSeqNum int, offRampOpts ...common.Address) []logpoller.Log { - var logs []logpoller.Log - nodes := c.Nodes - var offRamp common.Address - - if len(offRampOpts) > 0 { - offRamp = offRampOpts[0] - } else { - require.NotNil(t, c.Dest.OffRamp, "no offramp configured") - offRamp = c.Dest.OffRamp.Address() - } - for _, node := range nodes { - logs = node.EventuallyHasExecutedSeqNums(t, c, offRamp, minSeqNum, maxSeqNum) - } - return logs -} - -func (c *CCIPIntegrationTestHarness) NoNodesHaveExecutedSeqNum(t *testing.T, seqNum int, offRampOpts ...common.Address) logpoller.Log { - var log logpoller.Log - nodes := c.Nodes - var offRamp common.Address - if len(offRampOpts) > 0 { - offRamp = offRampOpts[0] - } else { - require.NotNil(t, c.Dest.OffRamp, "no offramp configured") - offRamp = c.Dest.OffRamp.Address() - } - for _, node := range nodes { - log = node.ConsistentlySeqNumHasNotBeenExecuted(t, c, offRamp, seqNum) - } - return log -} - -func (c *CCIPIntegrationTestHarness) EventuallyCommitReportAccepted(t *testing.T, currentBlock uint64, commitStoreOpts ...common.Address) commit_store_1_2_0.CommitStoreCommitReport { - var commitStore *commit_store_1_2_0.CommitStore - var err error - if len(commitStoreOpts) > 0 { - commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain.Client()) - require.NoError(t, err) - } else { - require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") - commitStore = c.Dest.CommitStore - } - g := gomega.NewGomegaWithT(t) - var report commit_store_1_2_0.CommitStoreCommitReport - g.Eventually(func() bool { - it, err := commitStore.FilterReportAccepted(&bind.FilterOpts{Start: currentBlock}) - g.Expect(err).NotTo(gomega.HaveOccurred(), "Error filtering ReportAccepted event") - g.Expect(it.Next()).To(gomega.BeTrue(), "No ReportAccepted event found") - report = it.Event.Report - if report.MerkleRoot != [32]byte{} { - t.Log("Report Accepted by commitStore") - return true - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "report has not been committed") - return report -} - -func (c *CCIPIntegrationTestHarness) EventuallyExecutionStateChangedToSuccess(t *testing.T, seqNum []uint64, blockNum uint64, offRampOpts ...common.Address) { - var offRamp *evm_2_evm_offramp_1_2_0.EVM2EVMOffRamp - var err error - if len(offRampOpts) > 0 { - offRamp, err = evm_2_evm_offramp_1_2_0.NewEVM2EVMOffRamp(offRampOpts[0], c.Dest.Chain.Client()) - require.NoError(t, err) - } else { - require.NotNil(t, c.Dest.OffRamp, "no offRamp configured") - offRamp = c.Dest.OffRamp - } - gomega.NewGomegaWithT(t).Eventually(func() bool { - it, err := offRamp.FilterExecutionStateChanged(&bind.FilterOpts{Start: blockNum}, seqNum, [][32]byte{}) - require.NoError(t, err) - for it.Next() { - if cciptypes.MessageExecutionState(it.Event.State) == cciptypes.ExecutionStateSuccess { - t.Logf("ExecutionStateChanged event found for seqNum %d", it.Event.SequenceNumber) - return true - } - } - c.Source.Chain.Commit() - c.Dest.Chain.Commit() - return false - }, testutils.WaitTimeout(t), time.Second). - Should(gomega.BeTrue(), "ExecutionStateChanged Event") -} - -func (c *CCIPIntegrationTestHarness) EventuallyReportCommitted(t *testing.T, max int, commitStoreOpts ...common.Address) uint64 { - var commitStore *commit_store_1_2_0.CommitStore - var err error - var committedSeqNum uint64 - if len(commitStoreOpts) > 0 { - commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain.Client()) - require.NoError(t, err) - } else { - require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") - commitStore = c.Dest.CommitStore - } - gomega.NewGomegaWithT(t).Eventually(func() bool { - minSeqNum, err := commitStore.GetExpectedNextSequenceNumber(nil) - require.NoError(t, err) - c.Source.Chain.Commit() - c.Dest.Chain.Commit() - t.Log("next expected seq num reported", minSeqNum) - committedSeqNum = minSeqNum - return minSeqNum > uint64(max) - }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue(), "report has not been committed") - return committedSeqNum -} - -func (c *CCIPIntegrationTestHarness) EventuallySendRequested(t *testing.T, seqNum uint64, onRampOpts ...common.Address) { - var onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp - var err error - if len(onRampOpts) > 0 { - onRamp, err = evm_2_evm_onramp_1_2_0.NewEVM2EVMOnRamp(onRampOpts[0], c.Source.Chain.Client()) - require.NoError(t, err) - } else { - require.NotNil(t, c.Source.OnRamp, "no onRamp configured") - onRamp = c.Source.OnRamp - } - gomega.NewGomegaWithT(t).Eventually(func() bool { - it, err := onRamp.FilterCCIPSendRequested(nil) - require.NoError(t, err) - for it.Next() { - if it.Event.Message.SequenceNumber == seqNum { - t.Log("sendRequested generated for", seqNum) - return true - } - } - c.Source.Chain.Commit() - c.Dest.Chain.Commit() - return false - }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue(), "sendRequested has not been generated") -} - -func (c *CCIPIntegrationTestHarness) ConsistentlyReportNotCommitted(t *testing.T, max int, commitStoreOpts ...common.Address) { - var commitStore *commit_store_1_2_0.CommitStore - var err error - if len(commitStoreOpts) > 0 { - commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain.Client()) - require.NoError(t, err) - } else { - require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") - commitStore = c.Dest.CommitStore - } - gomega.NewGomegaWithT(t).Consistently(func() bool { - minSeqNum, err := commitStore.GetExpectedNextSequenceNumber(nil) - require.NoError(t, err) - c.Source.Chain.Commit() - c.Dest.Chain.Commit() - t.Log("min seq num reported", minSeqNum) - require.GreaterOrEqual(t, max, 0) - return minSeqNum > uint64(max) //nolint:gosec // G115 false positive - }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeFalse(), "report has been committed") -} - -func (c *CCIPIntegrationTestHarness) SetupAndStartNodes(ctx context.Context, t *testing.T, bootstrapNodePort int64) (Node, []Node, uint64) { - appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNodeCCIP(t, c.Dest.User, bootstrapNodePort, - "bootstrap_ccip", c.Source.Chain, c.Dest.Chain, big.NewInt(0).SetUint64(c.Source.ChainID), - big.NewInt(0).SetUint64(c.Dest.ChainID), "", 0) - var ( - oracles []confighelper.OracleIdentityExtra - nodes []Node - ) - err := appBootstrap.Start(ctx) - require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, appBootstrap.Stop()) - }) - bootstrapNode := Node{ - App: appBootstrap, - Transmitter: bootstrapTransmitter, - KeyBundle: bootstrapKb, - } - // Set up the minimum 4 oracles all funded with destination ETH - for i := int64(0); i < 4; i++ { - app, peerID, transmitter, kb := setupNodeCCIP( - t, - c.Dest.User, - int64(freeport.GetOne(t)), - fmt.Sprintf("oracle_ccip%d", i), - c.Source.Chain, - c.Dest.Chain, - big.NewInt(0).SetUint64(c.Source.ChainID), - big.NewInt(0).SetUint64(c.Dest.ChainID), - bootstrapPeerID, - bootstrapNodePort, - ) - nodes = append(nodes, Node{ - App: app, - Transmitter: transmitter, - KeyBundle: kb, - }) - offchainPublicKey, _ := hex.DecodeString(strings.TrimPrefix(kb.OnChainPublicKey(), "0x")) - oracles = append(oracles, confighelper.OracleIdentityExtra{ - OracleIdentity: confighelper.OracleIdentity{ - OnchainPublicKey: offchainPublicKey, - TransmitAccount: types4.Account(transmitter.String()), - OffchainPublicKey: kb.OffchainPublicKey(), - PeerID: peerID, - }, - ConfigEncryptionPublicKey: kb.ConfigEncryptionPublicKey(), - }) - err = app.Start(ctx) - require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, app.Stop()) - }) - } - - c.Oracles = oracles - commitOnchainConfig := c.CreateDefaultCommitOnchainConfig(t) - commitOffchainConfig := c.CreateDefaultCommitOffchainConfig(t) - execOnchainConfig := c.CreateDefaultExecOnchainConfig(t) - execOffchainConfig := c.CreateDefaultExecOffchainConfig(t) - - configBlock := c.SetupOnchainConfig(t, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig) - c.Nodes = nodes - c.Bootstrap = bootstrapNode - //nolint:gosec // G115 - return bootstrapNode, nodes, uint64(configBlock) -} - -func (c *CCIPIntegrationTestHarness) SetUpNodesAndJobs(t *testing.T, pricePipeline string, priceGetterConfig string, usdcAttestationAPI string) integrationtesthelpers.CCIPJobSpecParams { - // setup Jobs - ctx := tests.Context(t) - // Starts nodes and configures them in the OCR contracts. - bootstrapNode, _, configBlock := c.SetupAndStartNodes(ctx, t, int64(freeport.GetOne(t))) - - jobParams := c.NewCCIPJobSpecParams(pricePipeline, priceGetterConfig, configBlock, usdcAttestationAPI) - - // Add the bootstrap job - c.Bootstrap.AddBootstrapJob(t, jobParams.BootstrapJob(c.Dest.CommitStore.Address().Hex())) - c.AddAllJobs(t, jobParams) - - // Replay for bootstrap. - bc, err := bootstrapNode.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(c.Dest.ChainID, 10)) - require.NoError(t, err) - require.LessOrEqual(t, configBlock, uint64(math.MaxInt64)) - require.NoError(t, bc.LogPoller().Replay(tests.Context(t), int64(configBlock))) //nolint:gosec // G115 false positive - c.Dest.Chain.Commit() - - return jobParams -} - -func (c *CCIPIntegrationTestHarness) NewCCIPJobSpecParams(tokenPricesUSDPipeline string, priceGetterConfig string, configBlock uint64, usdcAttestationAPI string) integrationtesthelpers.CCIPJobSpecParams { - return integrationtesthelpers.CCIPJobSpecParams{ - CommitStore: c.Dest.CommitStore.Address(), - OffRamp: c.Dest.OffRamp.Address(), - DestEvmChainId: c.Dest.ChainID, - SourceChainName: "SimulatedSource", - DestChainName: "SimulatedDest", - TokenPricesUSDPipeline: tokenPricesUSDPipeline, - PriceGetterConfig: priceGetterConfig, - DestStartBlock: configBlock, - USDCAttestationAPI: usdcAttestationAPI, - } -} - -func DecodeCommitOnChainConfig(encoded []byte) (ccipdata.CommitOnchainConfig, error) { - var onchainConfig ccipdata.CommitOnchainConfig - unpacked, err := abihelpers.DecodeOCR2Config(encoded) - if err != nil { - return onchainConfig, err - } - onChainCfg := unpacked.OnchainConfig - onchainConfig, err = abihelpers.DecodeAbiStruct[ccipdata.CommitOnchainConfig](onChainCfg) - if err != nil { - return onchainConfig, err - } - return onchainConfig, nil -} - -func DecodeExecOnChainConfig(encoded []byte) (v1_2_0.ExecOnchainConfig, error) { - var onchainConfig v1_2_0.ExecOnchainConfig - unpacked, err := abihelpers.DecodeOCR2Config(encoded) - if err != nil { - return onchainConfig, errors.Wrap(err, "failed to unpack log data") - } - onChainCfg := unpacked.OnchainConfig - onchainConfig, err = abihelpers.DecodeAbiStruct[v1_2_0.ExecOnchainConfig](onChainCfg) - if err != nil { - return onchainConfig, err - } - return onchainConfig, nil -} - -type ksa struct { - keystore.Master - csa keystore.CSA -} - -func (k *ksa) CSA() keystore.CSA { - return k.csa -} - -func NewKsa(db *sqlx.DB, lggr logger.Logger, csa keystore.CSA) *ksa { - return &ksa{ - Master: keystore.New(db, clutils.FastScryptParams, lggr), - csa: csa, - } -} - -type NoopFeedsClient struct{} - -func (n NoopFeedsClient) ApprovedJob(context.Context, *pb.ApprovedJobRequest) (*pb.ApprovedJobResponse, error) { - return &pb.ApprovedJobResponse{}, nil -} - -func (n NoopFeedsClient) Healthcheck(context.Context, *pb.HealthcheckRequest) (*pb.HealthcheckResponse, error) { - return &pb.HealthcheckResponse{}, nil -} - -func (n NoopFeedsClient) UpdateNode(context.Context, *pb.UpdateNodeRequest) (*pb.UpdateNodeResponse, error) { - return &pb.UpdateNodeResponse{}, nil -} - -func (n NoopFeedsClient) RejectedJob(context.Context, *pb.RejectedJobRequest) (*pb.RejectedJobResponse, error) { - return &pb.RejectedJobResponse{}, nil -} - -func (n NoopFeedsClient) CancelledJob(context.Context, *pb.CancelledJobRequest) (*pb.CancelledJobResponse, error) { - return &pb.CancelledJobResponse{}, nil -} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go deleted file mode 100644 index 087c21e9333..00000000000 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go +++ /dev/null @@ -1,75 +0,0 @@ -// Package with set of configs that should be used only within tests suites - -package testhelpers_1_4_0 - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" -) - -var PermissionLessExecutionThresholdSeconds = uint32(testhelpers.FirstBlockAge.Seconds()) - -func (c *CCIPContracts) CreateDefaultCommitOnchainConfig(t *testing.T) []byte { - config, err := abihelpers.EncodeAbiStruct(ccipdata.CommitOnchainConfig{ - PriceRegistry: c.Dest.PriceRegistry.Address(), - }) - require.NoError(t, err) - return config -} - -func (c *CCIPContracts) CreateDefaultCommitOffchainConfig(t *testing.T) []byte { - return c.createCommitOffchainConfig(t, 10*time.Second, 5*time.Second) -} - -func (c *CCIPContracts) createCommitOffchainConfig(t *testing.T, feeUpdateHearBeat time.Duration, inflightCacheExpiry time.Duration) []byte { - config, err := NewCommitOffchainConfig( - *config.MustNewDuration(feeUpdateHearBeat), - 1, - 1, - *config.MustNewDuration(feeUpdateHearBeat), - 1, - *config.MustNewDuration(inflightCacheExpiry), - false, - ).Encode() - require.NoError(t, err) - return config -} - -func (c *CCIPContracts) CreateDefaultExecOnchainConfig(t *testing.T) []byte { - config, err := abihelpers.EncodeAbiStruct(v1_2_0.ExecOnchainConfig{ - PermissionLessExecutionThresholdSeconds: PermissionLessExecutionThresholdSeconds, - Router: c.Dest.Router.Address(), - PriceRegistry: c.Dest.PriceRegistry.Address(), - MaxDataBytes: 1e5, - MaxNumberOfTokensPerMsg: 5, - MaxPoolReleaseOrMintGas: 200_000, - }) - require.NoError(t, err) - return config -} - -func (c *CCIPContracts) CreateDefaultExecOffchainConfig(t *testing.T) []byte { - return c.createExecOffchainConfig(t, 1*time.Minute, 1*time.Minute) -} - -func (c *CCIPContracts) createExecOffchainConfig(t *testing.T, inflightCacheExpiry time.Duration, rootSnoozeTime time.Duration) []byte { - config, err := NewExecOffchainConfig( - 1, - 5_000_000, - 0.07, - *config.MustNewDuration(inflightCacheExpiry), - *config.MustNewDuration(rootSnoozeTime), - uint32(0), - ).Encode() - require.NoError(t, err) - return config -} diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index c97e7bbc0aa..1f2859ae0db 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -57,7 +57,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) @@ -1415,16 +1414,6 @@ func NewCommitOffchainConfig( InflightCacheExpiry, priceReportingDisabled, ), nil - case V1_2_0: - return testhelpers_1_4_0.NewCommitOffchainConfig( - GasPriceHeartBeat, - DAGasPriceDeviationPPB, - ExecGasPriceDeviationPPB, - TokenPriceHeartBeat, - TokenPriceDeviationPPB, - InflightCacheExpiry, - priceReportingDisabled, - ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[CommitStoreContract]) } @@ -1436,8 +1425,6 @@ func NewCommitOnchainConfig( switch VersionMap[CommitStoreContract] { case Latest: return testhelpers.NewCommitOnchainConfig(PriceRegistry), nil - case V1_2_0: - return testhelpers_1_4_0.NewCommitOnchainConfig(PriceRegistry), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[CommitStoreContract]) } @@ -1454,15 +1441,6 @@ func NewExecOnchainConfig( switch VersionMap[OffRampContract] { case Latest: return testhelpers.NewExecOnchainConfig(PermissionLessExecutionThresholdSeconds, Router, PriceRegistry, MaxNumberOfTokensPerMsg, MaxDataBytes), nil - case V1_2_0: - return testhelpers_1_4_0.NewExecOnchainConfig( - PermissionLessExecutionThresholdSeconds, - Router, - PriceRegistry, - MaxNumberOfTokensPerMsg, - MaxDataBytes, - MaxPoolReleaseOrMintGas, - ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[OffRampContract]) } @@ -1487,15 +1465,6 @@ func NewExecOffchainConfig( rootSnoozeTime, batchingStrategyID, ), nil - case V1_2_0: - return testhelpers_1_4_0.NewExecOffchainConfig( - destOptimisticConfirmations, - batchGasLimit, - relativeBoostPerWaitHour, - inflightCacheExpiry, - rootSnoozeTime, - batchingStrategyID, - ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[OffRampContract]) } From 84208295f0945c5a1188387c20ea4a1771459216 Mon Sep 17 00:00:00 2001 From: Street <5597260+MStreet3@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:31:34 +0200 Subject: [PATCH 48/55] fix(workflows/syncer): skips fetching data for missing urls (#15519) --- core/services/workflows/syncer/handler.go | 18 +- .../services/workflows/syncer/handler_test.go | 235 ++++++++++++------ 2 files changed, 168 insertions(+), 85 deletions(-) diff --git a/core/services/workflows/syncer/handler.go b/core/services/workflows/syncer/handler.go index 46dcd21ed90..077dbc0cedb 100644 --- a/core/services/workflows/syncer/handler.go +++ b/core/services/workflows/syncer/handler.go @@ -383,14 +383,20 @@ func (h *eventHandler) workflowRegisteredEvent( return fmt.Errorf("failed to fetch binary from %s : %w", payload.BinaryURL, err) } - config, err := h.fetcher(ctx, payload.ConfigURL) - if err != nil { - return fmt.Errorf("failed to fetch config from %s : %w", payload.ConfigURL, err) + var config []byte + if payload.ConfigURL != "" { + config, err = h.fetcher(ctx, payload.ConfigURL) + if err != nil { + return fmt.Errorf("failed to fetch config from %s : %w", payload.ConfigURL, err) + } } - secrets, err := h.fetcher(ctx, payload.SecretsURL) - if err != nil { - return fmt.Errorf("failed to fetch secrets from %s : %w", payload.SecretsURL, err) + var secrets []byte + if payload.SecretsURL != "" { + secrets, err = h.fetcher(ctx, payload.SecretsURL) + if err != nil { + return fmt.Errorf("failed to fetch secrets from %s : %w", payload.SecretsURL, err) + } } // Calculate the hash of the binary and config files diff --git a/core/services/workflows/syncer/handler_test.go b/core/services/workflows/syncer/handler_test.go index bb0a61aea4d..7d11d347a02 100644 --- a/core/services/workflows/syncer/handler_test.go +++ b/core/services/workflows/syncer/handler_test.go @@ -173,59 +173,161 @@ const ( ) func Test_workflowRegisteredHandler(t *testing.T) { - t.Run("success with paused workflow registered", func(t *testing.T) { - var ( - ctx = testutils.Context(t) - lggr = logger.TestLogger(t) - db = pgtest.NewSqlxDB(t) - orm = NewWorkflowRegistryDS(db, lggr) - emitter = custmsg.NewLabeler() + var binaryURL = "http://example.com/binary" + var secretsURL = "http://example.com/secrets" + var configURL = "http://example.com/config" + var config = []byte("") + var wfOwner = []byte("0xOwner") + var binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) + defaultValidationFn := func(t *testing.T, ctx context.Context, h *eventHandler, wfOwner []byte, wfName string, wfID string) { + // Verify the record is updated in the database + dbSpec, err := h.orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") + require.NoError(t, err) + require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) + require.Equal(t, "workflow-name", dbSpec.WorkflowName) + require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) - config = []byte("") - secretsURL = "http://example.com" - binaryURL = "http://example.com/binary" - configURL = "http://example.com/config" - wfOwner = []byte("0xOwner") + // Verify the engine is started + engine, err := h.engineRegistry.Get(wfID) + require.NoError(t, err) + err = engine.Ready() + require.NoError(t, err) + } - fetcher = newMockFetcher(map[string]mockFetchResp{ + var tt = []testCase{ + { + Name: "success with active workflow registered", + fetcher: newMockFetcher(map[string]mockFetchResp{ binaryURL: {Body: binary, Err: nil}, configURL: {Body: config, Err: nil}, secretsURL: {Body: []byte("secrets"), Err: nil}, - }) - ) - - giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) - require.NoError(t, err) - - paused := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(1), - WorkflowID: giveWFID, - Owner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } + }), + GiveConfig: config, + ConfigURL: configURL, + SecretsURL: secretsURL, + BinaryURL: binaryURL, + GiveBinary: binary, + WFOwner: wfOwner, + Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { + return WorkflowRegistryWorkflowRegisteredV1{ + Status: uint8(0), + WorkflowID: [32]byte(wfID), + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + ConfigURL: configURL, + SecretsURL: secretsURL, + } + }, + validationFn: defaultValidationFn, + }, + { + Name: "success with paused workflow registered", + fetcher: newMockFetcher(map[string]mockFetchResp{ + binaryURL: {Body: binary, Err: nil}, + configURL: {Body: config, Err: nil}, + secretsURL: {Body: []byte("secrets"), Err: nil}, + }), + GiveConfig: config, + ConfigURL: configURL, + SecretsURL: secretsURL, + BinaryURL: binaryURL, + GiveBinary: binary, + WFOwner: wfOwner, + Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { + return WorkflowRegistryWorkflowRegisteredV1{ + Status: uint8(1), + WorkflowID: [32]byte(wfID), + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + ConfigURL: configURL, + SecretsURL: secretsURL, + } + }, + validationFn: func(t *testing.T, ctx context.Context, h *eventHandler, wfOwner []byte, wfName string, wfID string) { + // Verify the record is updated in the database + dbSpec, err := h.orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") + require.NoError(t, err) + require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) + require.Equal(t, "workflow-name", dbSpec.WorkflowName) + require.Equal(t, job.WorkflowSpecStatusPaused, dbSpec.Status) + + // Verify there is no running engine + _, err = h.engineRegistry.Get(wfID) + require.Error(t, err) + }, + }, + { + Name: "skips fetch if config url is missing", + GiveConfig: make([]byte, 0), + ConfigURL: "", + SecretsURL: secretsURL, + BinaryURL: binaryURL, + GiveBinary: binary, + WFOwner: wfOwner, + fetcher: newMockFetcher(map[string]mockFetchResp{ + binaryURL: {Body: binary, Err: nil}, + secretsURL: {Body: []byte("secrets"), Err: nil}, + }), + validationFn: defaultValidationFn, + Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { + return WorkflowRegistryWorkflowRegisteredV1{ + Status: uint8(0), + WorkflowID: [32]byte(wfID), + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + SecretsURL: secretsURL, + } + }, + }, + { + Name: "skips fetch if secrets url is missing", + GiveConfig: config, + ConfigURL: configURL, + BinaryURL: binaryURL, + GiveBinary: binary, + WFOwner: wfOwner, + fetcher: newMockFetcher(map[string]mockFetchResp{ + binaryURL: {Body: binary, Err: nil}, + configURL: {Body: config, Err: nil}, + }), + validationFn: defaultValidationFn, + Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { + return WorkflowRegistryWorkflowRegisteredV1{ + Status: uint8(0), + WorkflowID: [32]byte(wfID), + Owner: wfOwner, + WorkflowName: "workflow-name", + BinaryURL: binaryURL, + ConfigURL: configURL, + } + }, + }, + } - h := &eventHandler{ - lggr: lggr, - orm: orm, - fetcher: fetcher, - emitter: emitter, - } - err = h.workflowRegisteredEvent(ctx, paused) - require.NoError(t, err) + for _, tc := range tt { + testRunningWorkflow(t, tc) + } +} - // Verify the record is updated in the database - dbSpec, err := orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusPaused, dbSpec.Status) - }) +type testCase struct { + Name string + SecretsURL string + BinaryURL string + GiveBinary []byte + GiveConfig []byte + ConfigURL string + WFOwner []byte + fetcher FetcherFunc + Event func([]byte) WorkflowRegistryWorkflowRegisteredV1 + validationFn func(t *testing.T, ctx context.Context, h *eventHandler, wfOwner []byte, wfName string, wfID string) +} - t.Run("success with active workflow registered", func(t *testing.T) { +func testRunningWorkflow(t *testing.T, cmd testCase) { + t.Helper() + t.Run(cmd.Name, func(t *testing.T) { var ( ctx = testutils.Context(t) lggr = logger.TestLogger(t) @@ -233,34 +335,20 @@ func Test_workflowRegisteredHandler(t *testing.T) { orm = NewWorkflowRegistryDS(db, lggr) emitter = custmsg.NewLabeler() - binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) - config = []byte("") - secretsURL = "http://example.com" - binaryURL = "http://example.com/binary" - configURL = "http://example.com/config" - wfOwner = []byte("0xOwner") + binary = cmd.GiveBinary + config = cmd.GiveConfig + secretsURL = cmd.SecretsURL + wfOwner = cmd.WFOwner - fetcher = newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: binary, Err: nil}, - configURL: {Body: config, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }) + fetcher = cmd.fetcher ) giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, binary, config, secretsURL) require.NoError(t, err) - require.NoError(t, err) + wfID := hex.EncodeToString(giveWFID[:]) - active := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: giveWFID, - Owner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } + event := cmd.Event(giveWFID[:]) er := newEngineRegistry() store := wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()) @@ -275,21 +363,10 @@ func Test_workflowRegisteredHandler(t *testing.T) { capRegistry: registry, workflowStore: store, } - err = h.workflowRegisteredEvent(ctx, active) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err := orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") + err = h.workflowRegisteredEvent(ctx, event) require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - // Verify the engine is started - engine, err := h.engineRegistry.Get(hex.EncodeToString(giveWFID[:])) - require.NoError(t, err) - err = engine.Ready() - require.NoError(t, err) + cmd.validationFn(t, ctx, h, wfOwner, "workflow-name", wfID) }) } From 202e6b5652d7109c599678d7686e81811ee18373 Mon Sep 17 00:00:00 2001 From: jlaveracll Date: Mon, 9 Dec 2024 16:42:55 -0300 Subject: [PATCH 49/55] [SHIP-3521] Add tests to L2EP contracts to improve test coverage (#14341) * Add tests trying to improve test coverage * Increate testing and clean up * prettier * Update MockBaseSequencerUptimeFeed.sol * Create stale-cougars-approve.md * Update l2ep.gas-snapshot * [Bot] Update changeset file with jira issue * Revert "Update l2ep.gas-snapshot" This reverts commit 6e0d21131eb46355d8ff189370c2bb11a08514e1. * Update l2ep.gas-snapshot * fix comments and clean up scroll tests * Update l2ep.gas-snapshot * Update ZKSyncSequencerUptimeFeed.t.sol * fix gas snapshot * Update ScrollSequencerUptimeFeed.t.sol * Update ScrollSequencerUptimeFeed.t.sol * Update l2ep.gas-snapshot * rename l2ep -> shared to l2ep -> base * cleanup * address feedback * Renames tests to follow Solidity convetions * [Bot] Update changeset file with jira issues --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Co-authored-by: Mohamed Mehany <7327188+mohamed-mehany@users.noreply.github.com> --- .github/workflows/solidity-foundry.yml | 2 +- contracts/.changeset/thirty-rules-rule.md | 10 + contracts/gas-snapshots/l2ep.gas-snapshot | 79 ++-- .../BaseSequencerUptimeFeed.sol | 19 +- .../l2ep/{shared => base}/BaseValidator.sol | 2 +- .../optimism/OptimismSequencerUptimeFeed.sol | 2 +- .../v0.8/l2ep/optimism/OptimismValidator.sol | 2 +- .../l2ep/scroll/ScrollSequencerUptimeFeed.sol | 2 +- .../src/v0.8/l2ep/scroll/ScrollValidator.sol | 2 +- .../mocks/MockBaseSequencerUptimeFeed.sol | 25 ++ .../l2ep/test/mocks/MockBaseValidator.sol | 23 ++ .../OptimismSequencerUptimeFeed.t.sol | 302 ++------------ .../v1_0_0/optimism/OptimismValidator.t.sol | 24 +- .../scroll/ScrollCrossDomainForwarder.t.sol | 6 - .../scroll/ScrollCrossDomainGovernor.t.sol | 11 - .../scroll/ScrollSequencerUptimeFeed.t.sol | 310 +++----------- .../test/v1_0_0/scroll/ScrollValidator.t.sol | 37 +- .../shared/BaseSequencerUptimeFeed.t.sol | 377 ++++++++++++++++++ .../test/v1_0_0/shared/BaseValidator.t.sol | 57 +++ .../zksync/ZKSyncSequencerUptimeFeed.t.sol | 293 ++------------ .../test/v1_0_0/zksync/ZKSyncValidator.t.sol | 50 +-- .../l2ep/zksync/ZKSyncSequencerUptimeFeed.sol | 2 +- .../src/v0.8/l2ep/zksync/ZKSyncValidator.sol | 2 +- 23 files changed, 702 insertions(+), 937 deletions(-) create mode 100644 contracts/.changeset/thirty-rules-rule.md rename contracts/src/v0.8/l2ep/{shared => base}/BaseSequencerUptimeFeed.sol (93%) rename contracts/src/v0.8/l2ep/{shared => base}/BaseValidator.sol (96%) create mode 100644 contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol create mode 100644 contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol create mode 100644 contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol create mode 100644 contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index b94c0236155..850374b0cd3 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -33,7 +33,7 @@ jobs: { "name": "ccip", "setup": { "run-coverage": true, "min-coverage": 98.8, "extra-coverage-params": "--no-match-path='*End2End*'", "run-gas-snapshot": true, "run-forge-fmt": true }}, { "name": "functions", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "keystone", "setup": { "run-coverage": true, "min-coverage": 72.8, "run-gas-snapshot": false, "run-forge-fmt": false }}, - { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 61.0, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 65.0, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 44, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "llo-feeds", "setup": { "run-coverage": true, "min-coverage": 49.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "operatorforwarder", "setup": { "run-coverage": true, "min-coverage": 55.7, "run-gas-snapshot": true, "run-forge-fmt": false }}, diff --git a/contracts/.changeset/thirty-rules-rule.md b/contracts/.changeset/thirty-rules-rule.md new file mode 100644 index 00000000000..1c69192981c --- /dev/null +++ b/contracts/.changeset/thirty-rules-rule.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': patch +--- + +[L2EP] Refactor tests and fix file exclusion for coverage + + +PR issue: SHIP-3521 + +Solidity Review issue: SHIP-4050 \ No newline at end of file diff --git a/contracts/gas-snapshots/l2ep.gas-snapshot b/contracts/gas-snapshots/l2ep.gas-snapshot index 643127b6212..7caca346f48 100644 --- a/contracts/gas-snapshots/l2ep.gas-snapshot +++ b/contracts/gas-snapshots/l2ep.gas-snapshot @@ -34,6 +34,18 @@ ArbitrumSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerA ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 114527) ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 114610) ArbitrumValidator_Validate:test_PostSequencerOffline() (gas: 69009) +BaseSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface_ReturnsValidData() (gas: 69197) +BaseSequencerUptimeFeed_AggregatorV3Interface:test_getAnswer_ReturnsValidAnswer() (gas: 57300) +BaseSequencerUptimeFeed_AggregatorV3Interface:test_getTimestamp_ReturnsValidTimestamp() (gas: 57151) +BaseSequencerUptimeFeed_Constructor:test_Constructor_InitialState() (gas: 22050) +BaseSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_ProtectReads_AllowWhen_Whitelisted() (gas: 589517) +BaseSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_ProtectReads_DisallowWhen_NotWhitelisted() (gas: 562342) +BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_IgnoreOutOfOrderUpdates() (gas: 69490) +BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_UpdateWhen_NoStatusChangeSameTimestamp() (gas: 77166) +BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_UpdateWhen_StatusChangeAndNoTimeChange() (gas: 96021) +BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_UpdateWhen_StatusChangeAndTimeChange() (gas: 96100) +BaseSequencerUptimeFeed_transferL1Sender:test_transferL1Sender_CorrectlyTransfersL1Sender() (gas: 1479310) +BaseValidator_GetAndSetGasLimit:test_GetAndSetGasLimit_CorrectlyHandlesGasLimit() (gas: 20119) OptimismCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47110) OptimismCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22135) OptimismCrossDomainForwarder_Constructor:test_InitialState() (gas: 21947) @@ -60,23 +72,10 @@ OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 4 OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28733) OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16456) OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11044) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72286) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17639) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17875) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17628) -OptimismSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22002) -OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 589475) -OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 562336) -OptimismSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67804) -OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13109) -OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23523) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77205) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96089) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96172) -OptimismValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18636) -OptimismValidator_Validate:test_PostSequencerOffline() (gas: 74764) -OptimismValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 74798) -OptimismValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15556) +OptimismSequencerUptimeFeed_Constructor:test_Constructor_InitialState() (gas: 1530881) +OptimismSequencerUptimeFeed_ValidateSender:test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() (gas: 17874) +OptimismValidator_Validate:test_Validate_PostSequencerOffline() (gas: 74773) +OptimismValidator_Validate:test_Validate_PostSequencerStatus_NoStatusChange() (gas: 74788) ScrollCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47196) ScrollCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22185) ScrollCrossDomainForwarder_Constructor:test_InitialState() (gas: 21623) @@ -103,40 +102,12 @@ ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 489 ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28791) ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16456) ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11044) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72309) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17639) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17875) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17628) -ScrollSequencerUptimeFeed_Constructor:test_InitialState() (gas: 174353) -ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 589475) -ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 562336) -ScrollSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67850) -ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13109) -ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23523) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77251) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96135) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96218) -ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18770) -ScrollValidator_Validate:test_PostSequencerOffline() (gas: 78299) -ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 78339) -ScrollValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15556) -ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 67090) -ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17639) -ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17875) -ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17628) -ZKSyncSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22006) -ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 589495) -ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 562342) -ZKSyncSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 61883) -ZKSyncSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13055) -ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 71321) -ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 90176) -ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 90259) -ZKSyncValidator_Constructor:test_ConstructingRevertedWithInvalidChainId() (gas: 104069) -ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL1BridgeAddress() (gas: 81784) -ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL2UpdateFeedAddress() (gas: 81796) -ZKSyncValidator_GetChainId:test_CorrectlyGetsTheChainId() (gas: 8346) -ZKSyncValidator_GetSetL2GasPerPubdataByteLimit:test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() (gas: 18896) -ZKSyncValidator_Validate:test_PostSequencerOffline() (gas: 52210) -ZKSyncValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 52279) -ZKSyncValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15623) \ No newline at end of file +ScrollSequencerUptimeFeed_Constructor:test_Constructor_InitialState_WhenValidL2XDomainMessenger() (gas: 1511902) +ScrollSequencerUptimeFeed_ValidateSender:test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() (gas: 17864) +ScrollValidator_Validate:test_Validate_PostSequencerOffline() (gas: 78317) +ScrollValidator_Validate:test_Validate_PostSequencerStatus_NoStatusChange() (gas: 78338) +ZKSyncSequencerUptimeFeed_ValidateSender:test_ValidateSender_SuccessWhen_SenderIsValid() (gas: 12611) +ZKSyncValidator_GetChainId:test_GetChainId_CorrectlyGetsTheChainId() (gas: 8369) +ZKSyncValidator_GetSetL2GasPerPubdataByteLimit:test_GetSetL2GasPerPubdataByteLimit_CorrectlyHandlesGasPerPubdataByteLimit() (gas: 18918) +ZKSyncValidator_Validate:test_Validate_PostSequencerOffline() (gas: 52208) +ZKSyncValidator_Validate:test_Validate_PostSequencerStatus_NoStatusChange() (gas: 52280) \ No newline at end of file diff --git a/contracts/src/v0.8/l2ep/shared/BaseSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/base/BaseSequencerUptimeFeed.sol similarity index 93% rename from contracts/src/v0.8/l2ep/shared/BaseSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/base/BaseSequencerUptimeFeed.sol index 344270fcff8..81fcb11ca95 100644 --- a/contracts/src/v0.8/l2ep/shared/BaseSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/base/BaseSequencerUptimeFeed.sol @@ -59,7 +59,7 @@ abstract contract BaseSequencerUptimeFeed is /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract /// @param initialStatus The initial status of the feed constructor(address l1SenderAddress, bool initialStatus) { - // We neet to allow l1SenderAddress to be zero because this contract is deployed first + // We need to allow l1SenderAddress to be zero because this contract is deployed first // After deploying the validator contract, this contract will be updated with the correct L1 sender address _setL1Sender(l1SenderAddress); @@ -81,9 +81,9 @@ abstract contract BaseSequencerUptimeFeed is /// @notice Set the allowed L1 sender for this contract to a new L1 sender /// @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. - /// @param to new L1 sender that will be allowed to call `updateStatus` on this contract - function transferL1Sender(address to) external virtual onlyOwner { - _setL1Sender(to); + /// @param newSender new L1 sender that will be allowed to call `updateStatus` on this contract + function transferL1Sender(address newSender) external virtual onlyOwner { + _setL1Sender(newSender); } /// @notice internal method that stores the L1 sender @@ -164,13 +164,10 @@ abstract contract BaseSequencerUptimeFeed is return s_rounds[uint80(roundId)].startedAt; } - /** - * @notice Record a new status and timestamp if it has changed since the last round. - * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. - * - * @param status Sequencer status - * @param timestamp Block timestamp of status update - */ + /// @notice Record a new status and timestamp if it has changed since the last round. + /// @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. + /// @param status Sequencer status + /// @param timestamp Block timestamp of status update function updateStatus(bool status, uint64 timestamp) external override { _validateSender(s_l1Sender); diff --git a/contracts/src/v0.8/l2ep/shared/BaseValidator.sol b/contracts/src/v0.8/l2ep/base/BaseValidator.sol similarity index 96% rename from contracts/src/v0.8/l2ep/shared/BaseValidator.sol rename to contracts/src/v0.8/l2ep/base/BaseValidator.sol index 8b38da391ec..4f9c6912a00 100644 --- a/contracts/src/v0.8/l2ep/shared/BaseValidator.sol +++ b/contracts/src/v0.8/l2ep/base/BaseValidator.sol @@ -24,7 +24,7 @@ abstract contract BaseValidator is SimpleWriteAccessController, AggregatorValida uint32 internal s_gasLimit; /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address - /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeed contract address + /// @param l2UptimeFeedAddr the address of the L2 SequencerUptimeFeed contract address /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 constructor(address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, uint32 gasLimit) { if (l1CrossDomainMessengerAddress == address(0)) { diff --git a/contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol index 0e6f9c52f22..b160fe46155 100644 --- a/contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../base/BaseSequencerUptimeFeed.sol"; import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol b/contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol index cf5222f017e..97c202dcd88 100644 --- a/contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol +++ b/contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; -import {BaseValidator} from "../shared/BaseValidator.sol"; +import {BaseValidator} from "../base/BaseValidator.sol"; import {IL1CrossDomainMessenger} from "@eth-optimism/contracts/L1/messaging/IL1CrossDomainMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol index 40f2941aa69..9c0c22290f2 100644 --- a/contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../base/BaseSequencerUptimeFeed.sol"; import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol b/contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol index b009c80fdfd..0eda14d0adc 100644 --- a/contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol +++ b/contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; -import {BaseValidator} from "../shared/BaseValidator.sol"; +import {BaseValidator} from "../base/BaseValidator.sol"; import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol new file mode 100644 index 00000000000..50d852faa45 --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {BaseSequencerUptimeFeed} from "../../base/BaseSequencerUptimeFeed.sol"; + +contract MockBaseSequencerUptimeFeed is BaseSequencerUptimeFeed { + string public constant override typeAndVersion = "MockSequencerUptimeFeed 1.1.0-dev"; + + /// @dev this will be used for internal testing + bool private s_validateSenderShouldPass; + + constructor( + address l1SenderAddress, + bool initialStatus, + bool validateSenderShouldPass + ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { + s_validateSenderShouldPass = validateSenderShouldPass; + } + + function _validateSender(address /* l1Sender */) internal view override { + if (!s_validateSenderShouldPass) { + revert InvalidSender(); + } + } +} diff --git a/contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol b/contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol new file mode 100644 index 00000000000..d23efb48656 --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {BaseValidator} from "../../base/BaseValidator.sol"; + +contract MockBaseValidator is BaseValidator { + string public constant override typeAndVersion = "MockValidator 1.1.0-dev"; + + constructor( + address l1CrossDomainMessengerAddress, + address l2UptimeFeedAddr, + uint32 gasLimit + ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) {} + + function validate( + uint256 /* previousRoundId */, + int256 /* previousAnswer */, + uint256 /* currentRoundId */, + int256 /* currentAnswer */ + ) external view override checkAccess returns (bool) { + return true; + } +} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol index daf50962a1e..34010c313e8 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol @@ -4,30 +4,36 @@ pragma solidity 0.8.24; import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../shared/BaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract OptimismSequencerUptimeFeedTest is L2EPTest { - /// Constants - uint256 internal constant GAS_USED_DEVIATION = 100; +contract OptimismSequencerUptimeFeed_TestWrapper is OptimismSequencerUptimeFeed { + constructor( + address l1SenderAddress, + address l2CrossDomainMessengerAddr, + bool initialStatus + ) OptimismSequencerUptimeFeed(l1SenderAddress, l2CrossDomainMessengerAddr, initialStatus) {} + + /// @notice Exposes the internal `_validateSender` function for testing + function validateSenderTestWrapper(address l1Sender) external view { + super._validateSender(l1Sender); + } +} + +contract OptimismSequencerUptimeFeed_Setup is L2EPTest { + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); /// L2EP contracts MockOptimismL1CrossDomainMessenger internal s_mockOptimismL1CrossDomainMessenger; MockOptimismL2CrossDomainMessenger internal s_mockOptimismL2CrossDomainMessenger; - OptimismSequencerUptimeFeed internal s_optimismSequencerUptimeFeed; - - /// Events - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - event RoundUpdated(int256 status, uint64 updatedAt); + OptimismSequencerUptimeFeed_TestWrapper internal s_optimismSequencerUptimeFeed; /// Setup function setUp() public { - // Deploys contracts + // Deploy contracts s_mockOptimismL1CrossDomainMessenger = new MockOptimismL1CrossDomainMessenger(); s_mockOptimismL2CrossDomainMessenger = new MockOptimismL2CrossDomainMessenger(); - s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed( + s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed_TestWrapper( s_l1OwnerAddr, address(s_mockOptimismL2CrossDomainMessenger), false @@ -38,12 +44,14 @@ contract OptimismSequencerUptimeFeedTest is L2EPTest { } } -contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeedTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { +contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeed_Setup { + /// @notice Tests the initial state of the contract + function test_Constructor_InitialState() public { // Sets msg.sender and tx.origin to a valid address vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + new OptimismSequencerUptimeFeed_TestWrapper(s_l1OwnerAddr, address(s_mockOptimismL2CrossDomainMessenger), false); + // Checks L1 sender address actualL1Addr = s_optimismSequencerUptimeFeed.l1Sender(); assertEq(actualL1Addr, s_l1OwnerAddr); @@ -55,267 +63,33 @@ contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeedT } } -contract OptimismSequencerUptimeFeed_UpdateStatus is OptimismSequencerUptimeFeedTest { - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger - function test_RevertIfNotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); +contract OptimismSequencerUptimeFeed_ValidateSender is OptimismSequencerUptimeFeed_Setup { + /// @notice Reverts if called by an address that is not the L2 Cross Domain Messenger + function test_ValidateSender_RevertWhen_SenderIsNotL2CrossDomainMessengerAddr() public { + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + // Sets msg.sender to a different address + vm.startPrank(s_strangerAddr, l2MessengerAddr); - // Tries to update the status from an unauthorized account vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); + s_optimismSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); } - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender - function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { + /// @notice Reverts if the L1 sender address is not the L1 Cross Domain Messenger Sender + function test_ValidateSender_RevertWhen_L1CrossDomainMessengerAddrIsNotL1SenderAddr() public { // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Sets mock sender in mock L2 messenger contract - s_mockOptimismL2CrossDomainMessenger.setSender(s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should update status when status has not changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenNoChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data before updating it - ( - uint80 roundIdBeforeUpdate, - int256 answerBeforeUpdate, - uint256 startedAtBeforeUpdate, - , - uint80 answeredInRoundBeforeUpdate - ) = s_optimismSequencerUptimeFeed.latestRoundData(); - - // Submit another status update with the same status - vm.expectEmit(); - emit RoundUpdated(1, uint64(block.timestamp)); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data after updating it - ( - uint80 roundIdAfterUpdate, - int256 answerAfterUpdate, - uint256 startedAtAfterUpdate, - uint256 updatedAtAfterUpdate, - uint80 answeredInRoundAfterUpdate - ) = s_optimismSequencerUptimeFeed.latestRoundData(); - - // Verifies the latest round data has been properly updated - assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); - assertEq(answerAfterUpdate, answerBeforeUpdate); - assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); - assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); - assertEq(updatedAtAfterUpdate, block.timestamp); - } - - /// @notice it should update status when status has changed and incoming timestamp is newer than the latest - function test_UpdateStatusWhenStatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should update status when status has changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should ignore out-of-order updates - function test_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); vm.startPrank(l2MessengerAddr, l2MessengerAddr); - // Submits a status update - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - // TODO: how can we check that an AnswerUpdated event was NOT emitted - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_optimismSequencerUptimeFeed.validateSenderTestWrapper(s_strangerAddr); } -} -contract OptimismSequencerUptimeFeed_AggregatorV3Interface is OptimismSequencerUptimeFeedTest { - /// @notice it should return valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface() public { + /// @notice Updates status when status has changed and incoming timestamp is the same as the latest + function test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() public { // Sets msg.sender and tx.origin to a valid address address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); vm.startPrank(l2MessengerAddr, l2MessengerAddr); - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); - - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; - - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(1); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) - function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_optimismSequencerUptimeFeed.getRoundData(2); - } - - /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) - function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_optimismSequencerUptimeFeed.getAnswer(2); - } - - /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) - function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_optimismSequencerUptimeFeed.getTimestamp(2); - } -} - -contract OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is OptimismSequencerUptimeFeedTest { - /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); - - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); - } - - /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); - - // Whitelist consumer - s_optimismSequencerUptimeFeed.addAccess(address(feedConsumer)); - - // Sanity - consumer is whitelisted - assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); - - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); + s_optimismSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); } } diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol index ba9e3f872f1..48ff1f7778d 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol @@ -9,7 +9,7 @@ import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUp import {OptimismValidator} from "../../../optimism/OptimismValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract OptimismValidatorTest is L2EPTest { +contract OptimismValidator_Setup is L2EPTest { /// Helper constants address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; uint32 internal constant INIT_GAS_LIMIT = 1900000; @@ -42,26 +42,16 @@ contract OptimismValidatorTest is L2EPTest { } } -contract OptimismValidator_SetGasLimit is OptimismValidatorTest { - /// @notice it correctly updates the gas limit - function test_CorrectlyUpdatesTheGasLimit() public { - uint32 newGasLimit = 2000000; - assertEq(s_optimismValidator.getGasLimit(), INIT_GAS_LIMIT); - s_optimismValidator.setGasLimit(newGasLimit); - assertEq(s_optimismValidator.getGasLimit(), newGasLimit); - } -} - -contract OptimismValidator_Validate is OptimismValidatorTest { +contract OptimismValidator_Validate is OptimismValidator_Setup { /// @notice it reverts if called by account with no access - function test_RevertsIfCalledByAnAccountWithNoAccess() public { + function test_Validate_RevertWhen_CalledByAccountWithNoAccess() public { vm.startPrank(s_strangerAddr); vm.expectRevert("No access"); s_optimismValidator.validate(0, 0, 1, 1); } - /// @notice it posts sequencer status when there is not status change - function test_PostSequencerStatusWhenThereIsNotStatusChange() public { + /// @notice it posts sequencer status when there is no status change + function test_Validate_PostSequencerStatus_NoStatusChange() public { // Gives access to the s_eoaValidator s_optimismValidator.addAccess(s_eoaValidator); @@ -84,8 +74,8 @@ contract OptimismValidator_Validate is OptimismValidatorTest { s_optimismValidator.validate(0, 0, 0, 0); } - /// @notice it post sequencer offline - function test_PostSequencerOffline() public { + /// @notice it posts sequencer offline + function test_Validate_PostSequencerOffline() public { // Gives access to the s_eoaValidator s_optimismValidator.addAccess(s_eoaValidator); diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol index b0ef7df22c1..0025c6b9937 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol @@ -54,7 +54,6 @@ contract ScrollCrossDomainForwarder_Forward is ScrollCrossDomainForwarderTest { /// @notice it should be callable by crossdomain messenger address / L1 owner function test_Forward() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -74,7 +73,6 @@ contract ScrollCrossDomainForwarder_Forward is ScrollCrossDomainForwarderTest { /// @notice it should revert when contract call reverts function test_ForwardRevert() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message @@ -106,7 +104,6 @@ contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForw /// @notice it should be callable by current L1 owner function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -124,7 +121,6 @@ contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForw /// @notice it should be callable by current L1 owner to zero address function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -144,7 +140,6 @@ contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForw contract ScrollCrossDomainForwarder_AcceptL1Ownership is ScrollCrossDomainForwarderTest { /// @notice it should not be callable by non pending-owners function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends the message @@ -159,7 +154,6 @@ contract ScrollCrossDomainForwarder_AcceptL1Ownership is ScrollCrossDomainForwar /// @notice it should be callable by pending L1 owner function test_CallableByPendingL1Owner() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Request ownership transfer diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol index 5eefaddab70..a2523e5feb6 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol @@ -58,7 +58,6 @@ contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { /// @notice it should be callable by crossdomain messenger address / L1 owner function test_Forward() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -78,7 +77,6 @@ contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { /// @notice it should revert when contract call reverts function test_ForwardRevert() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message @@ -93,7 +91,6 @@ contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { /// @notice it should be callable by L2 owner function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin vm.startPrank(s_l1OwnerAddr); // Defines the cross domain message to send @@ -120,7 +117,6 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should be callable by crossdomain messenger address / L1 owner function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends the message @@ -141,7 +137,6 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should be callable by L2 owner function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin vm.startPrank(s_l1OwnerAddr); // Sends the message @@ -162,7 +157,6 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should revert batch when one call fails function test_RevertsBatchWhenOneCallFails() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message (empty transaction data is not allowed) @@ -184,7 +178,6 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should bubble up revert when contract call reverts function test_BubbleUpRevert() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message (empty transaction data is not allowed) @@ -220,7 +213,6 @@ contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGover /// @notice it should be callable by current L1 owner function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -238,7 +230,6 @@ contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGover /// @notice it should be callable by current L1 owner to zero address function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -258,7 +249,6 @@ contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGover contract ScrollCrossDomainGovernor_AcceptL1Ownership is ScrollCrossDomainGovernorTest { /// @notice it should not be callable by non pending-owners function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends the message @@ -273,7 +263,6 @@ contract ScrollCrossDomainGovernor_AcceptL1Ownership is ScrollCrossDomainGoverno /// @notice it should be callable by pending L1 owner function test_CallableByPendingL1Owner() public { - // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Request ownership transfer diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol index 5e4d8a7a20f..1ad4bfd8119 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol @@ -4,18 +4,30 @@ pragma solidity 0.8.24; import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; import {ScrollSequencerUptimeFeed} from "../../../scroll/ScrollSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../shared/BaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ScrollSequencerUptimeFeedTest is L2EPTest { +contract ScrollSequencerUptimeFeedTestWrapper is ScrollSequencerUptimeFeed { + constructor( + address l1SenderAddress, + address l2CrossDomainMessengerAddr, + bool initialStatus + ) ScrollSequencerUptimeFeed(l1SenderAddress, l2CrossDomainMessengerAddr, initialStatus) {} + + /// @notice It exposes the internal _validateSender function for testing + function validateSenderTestWrapper(address l1Sender) external view { + super._validateSender(l1Sender); + } +} + +contract ScrollSequencerUptimeFeed_Setup is L2EPTest { /// Constants uint256 internal constant GAS_USED_DEVIATION = 100; /// L2EP contracts MockScrollL1CrossDomainMessenger internal s_mockScrollL1CrossDomainMessenger; MockScrollL2CrossDomainMessenger internal s_mockScrollL2CrossDomainMessenger; - ScrollSequencerUptimeFeed internal s_scrollSequencerUptimeFeed; + ScrollSequencerUptimeFeedTestWrapper internal s_scrollSequencerUptimeFeed; /// Events event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); @@ -27,7 +39,7 @@ contract ScrollSequencerUptimeFeedTest is L2EPTest { // Deploys contracts s_mockScrollL1CrossDomainMessenger = new MockScrollL1CrossDomainMessenger(); s_mockScrollL2CrossDomainMessenger = new MockScrollL2CrossDomainMessenger(); - s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( + s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeedTestWrapper( s_l1OwnerAddr, address(s_mockScrollL2CrossDomainMessenger), false @@ -38,14 +50,13 @@ contract ScrollSequencerUptimeFeedTest is L2EPTest { } } -contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeedTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { +contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeed_Setup { + /// @notice Reverts when L2 Cross Domain Messenger address is invalid + function test_Constructor_RevertWhen_InvalidL2XDomainMessenger() public { // L2 cross domain messenger address must not be the zero address vm.expectRevert(ScrollSequencerUptimeFeed.ZeroAddress.selector); new ScrollSequencerUptimeFeed(s_l1OwnerAddr, address(0), false); - // Sets msg.sender and tx.origin to a valid address vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Checks L1 sender @@ -57,269 +68,50 @@ contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeedTest assertEq(roundId, 1); assertEq(answer, 0); } -} - -contract ScrollSequencerUptimeFeed_UpdateStatus is ScrollSequencerUptimeFeedTest { - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger - function test_RevertIfNotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender - function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Sets mock sender in mock L2 messenger contract - s_mockScrollL2CrossDomainMessenger.setSender(s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should update status when status has not changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenNoChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data before updating it - ( - uint80 roundIdBeforeUpdate, - int256 answerBeforeUpdate, - uint256 startedAtBeforeUpdate, - , - uint80 answeredInRoundBeforeUpdate - ) = s_scrollSequencerUptimeFeed.latestRoundData(); - - // Submit another status update with the same status - vm.expectEmit(); - emit RoundUpdated(1, uint64(block.timestamp)); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data after updating it - ( - uint80 roundIdAfterUpdate, - int256 answerAfterUpdate, - uint256 startedAtAfterUpdate, - uint256 updatedAtAfterUpdate, - uint80 answeredInRoundAfterUpdate - ) = s_scrollSequencerUptimeFeed.latestRoundData(); - - // Verifies the latest round data has been properly updated - assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); - assertEq(answerAfterUpdate, answerBeforeUpdate); - assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); - assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); - assertEq(updatedAtAfterUpdate, block.timestamp); - } - - /// @notice it should update status when status has changed and incoming timestamp is newer than the latest - function test_UpdateStatusWhenStatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should update status when status has changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should ignore out-of-order updates - function test_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - // TODO: how can we check that an AnswerUpdated event was NOT emitted - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - } -} - -contract ScrollSequencerUptimeFeed_AggregatorV3Interface is ScrollSequencerUptimeFeedTest { - /// @notice it should return valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); + /// @notice Tests initial state with valid L2 Cross Domain Messenger + function test_Constructor_InitialState_WhenValidL2XDomainMessenger() public { + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + ScrollSequencerUptimeFeed scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( + s_l1OwnerAddr, + address(s_mockScrollL2CrossDomainMessenger), + false + ); - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; + // Checks L1 sender + address actualL1Addr = scrollSequencerUptimeFeed.l1Sender(); + assertEq(actualL1Addr, s_l1OwnerAddr); - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(1); + // Checks latest round data + (uint80 roundId, int256 answer, , , ) = scrollSequencerUptimeFeed.latestRoundData(); assertEq(roundId, 1); assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) - function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_scrollSequencerUptimeFeed.getRoundData(2); - } - - /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) - function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_scrollSequencerUptimeFeed.getAnswer(2); - } - - /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) - function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_scrollSequencerUptimeFeed.getTimestamp(2); } } -contract ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ScrollSequencerUptimeFeedTest { - /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); +contract ScrollSequencerUptimeFeed_ValidateSender is ScrollSequencerUptimeFeed_Setup { + /// @notice Reverts when sender is not L2 Cross Domain Messenger address + function test_ValidateSender_RevertWhen_SenderIsNotL2CrossDomainMessengerAddr() public { + vm.startPrank(s_strangerAddr); - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_scrollSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); } - /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); + /// @notice Reverts when L1 Cross Domain Messenger address is not L1 sender address + function test_ValidateSender_RevertWhen_L1CrossDomainMessengerAddrIsNotL1SenderAddr() public { + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr); - // Whitelist consumer - s_scrollSequencerUptimeFeed.addAccess(address(feedConsumer)); + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_scrollSequencerUptimeFeed.validateSenderTestWrapper(s_strangerAddr); + } - // Sanity - consumer is whitelisted - assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + /// @notice Updates status when status changes and incoming timestamp is the same as latest + function test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() public { + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr); - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); + s_scrollSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); } } diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol index 1a0bcc856f2..b7708889100 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol @@ -10,9 +10,9 @@ import {ScrollSequencerUptimeFeed} from "../../../scroll/ScrollSequencerUptimeFe import {ScrollValidator} from "../../../scroll/ScrollValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ScrollValidatorTest is L2EPTest { +contract ScrollValidator_Setup is L2EPTest { /// Helper constants - address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; + address internal immutable L2_SEQ_STATUS_RECORDER_ADDRESS = makeAddr("L2_SEQ_STATUS_RECORDER_ADDRESS"); uint32 internal constant INIT_GAS_LIMIT = 1900000; /// L2EP contracts @@ -53,26 +53,31 @@ contract ScrollValidatorTest is L2EPTest { } } -contract ScrollValidator_SetGasLimit is ScrollValidatorTest { - /// @notice it correctly updates the gas limit - function test_CorrectlyUpdatesTheGasLimit() public { - uint32 newGasLimit = 2000000; - assertEq(s_scrollValidator.getGasLimit(), INIT_GAS_LIMIT); - s_scrollValidator.setGasLimit(newGasLimit); - assertEq(s_scrollValidator.getGasLimit(), newGasLimit); +contract ScrollValidator_Constructor is ScrollValidator_Setup { + /// @notice Reverts when L1 message queue address is invalid + function test_Constructor_RevertWhen_InvalidL1MessageQueueAddress() public { + vm.startPrank(s_l1OwnerAddr); + + vm.expectRevert("Invalid L1 message queue address"); + new ScrollValidator( + address(s_mockScrollL1CrossDomainMessenger), + address(s_scrollSequencerUptimeFeed), + address(0), + INIT_GAS_LIMIT + ); } } -contract ScrollValidator_Validate is ScrollValidatorTest { - /// @notice it reverts if called by account with no access - function test_RevertsIfCalledByAnAccountWithNoAccess() public { +contract ScrollValidator_Validate is ScrollValidator_Setup { + /// @notice Reverts if called by an account with no access + function test_Validate_RevertWhen_CalledByAccountWithNoAccess() public { vm.startPrank(s_strangerAddr); vm.expectRevert("No access"); s_scrollValidator.validate(0, 0, 1, 1); } - /// @notice it posts sequencer status when there is not status change - function test_PostSequencerStatusWhenThereIsNotStatusChange() public { + /// @notice Posts sequencer status when there is no status change + function test_Validate_PostSequencerStatus_NoStatusChange() public { // Gives access to the s_eoaValidator s_scrollValidator.addAccess(s_eoaValidator); @@ -96,8 +101,8 @@ contract ScrollValidator_Validate is ScrollValidatorTest { s_scrollValidator.validate(0, 0, 0, 0); } - /// @notice it post sequencer offline - function test_PostSequencerOffline() public { + /// @notice Posts sequencer offline status + function test_Validate_PostSequencerOffline() public { // Gives access to the s_eoaValidator s_scrollValidator.addAccess(s_eoaValidator); diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol new file mode 100644 index 00000000000..20553e33bab --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {Vm} from "forge-std/Test.sol"; +import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; +import {MockBaseSequencerUptimeFeed} from "../../../test/mocks/MockBaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract BaseSequencerUptimeFeed_Setup is L2EPTest { + /// Helper Variables + address internal s_aliasedL1OwnerAddress = AddressAliasHelper.applyL1ToL2Alias(s_l1OwnerAddr); + + /// L2EP contracts + BaseSequencerUptimeFeed internal s_sequencerUptimeFeed; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); + event L1SenderTransferred(address indexed from, address indexed to); + + /// Setup + function setUp() public { + // Deploys contracts + s_sequencerUptimeFeed = new MockBaseSequencerUptimeFeed(s_l1OwnerAddr, false, true); + } +} + +contract BaseSequencerUptimeFeed_Constructor is BaseSequencerUptimeFeed_Setup { + /// @notice Tests initial state of the contract + function test_Constructor_InitialState() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Checks L1 sender + address actualL1Addr = s_sequencerUptimeFeed.l1Sender(); + assertEq(actualL1Addr, s_l1OwnerAddr); + + // Checks latest round data + (uint80 roundId, int256 answer, , , ) = s_sequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} + +contract BaseSequencerUptimeFeed_transferL1Sender is BaseSequencerUptimeFeed_Setup { + /// @notice Tests transferring L1 sender + function test_transferL1Sender_CorrectlyTransfersL1Sender() public { + address initialSender = address(0); + address newSender = makeAddr("newSender"); + + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + MockBaseSequencerUptimeFeed sequencerUptimeFeed = new MockBaseSequencerUptimeFeed(initialSender, false, true); + + assertEq(sequencerUptimeFeed.l1Sender(), initialSender); + + // Transfers the L1 sender + vm.expectEmit(); + emit L1SenderTransferred(initialSender, newSender); + sequencerUptimeFeed.transferL1Sender(newSender); + assertEq(sequencerUptimeFeed.l1Sender(), newSender); + + vm.recordLogs(); + // Transfers to the same L1 sender should not emit an event + sequencerUptimeFeed.transferL1Sender(newSender); + assertEq(vm.getRecordedLogs().length, 0); + } + + /// @notice Reverts if called by an unauthorized account + function test_transferL1Sender_RevertWhen_CalledByUnauthorizedAccount() public { + address newSender = makeAddr("newSender"); + + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + vm.expectRevert("Only callable by owner"); + s_sequencerUptimeFeed.transferL1Sender(newSender); + } +} + +contract BaseSequencerUptimeFeed_UpdateStatus is BaseSequencerUptimeFeed_Setup { + /// @notice Reverts if called by an unauthorized account + function test_updateStatus_RevertWhen_NotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + BaseSequencerUptimeFeed s_sequencerUptimeFeedFailSenderCheck = new MockBaseSequencerUptimeFeed( + s_l1OwnerAddr, + false, + false + ); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_sequencerUptimeFeedFailSenderCheck.updateStatus(true, uint64(1)); + } + + /// @notice Updates status when status has not changed and incoming timestamp is the same as latest + function test_updateStatus_UpdateWhen_NoStatusChangeSameTimestamp() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_sequencerUptimeFeed.latestRound(), 2); + assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_sequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_sequencerUptimeFeed.latestRound(), 2); + assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_sequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice Updates status when status has changed and incoming timestamp is newer than the latest + function test_updateStatus_UpdateWhen_StatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_sequencerUptimeFeed.latestRound(), 2); + assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_sequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_sequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_sequencerUptimeFeed.latestRound(), 3); + assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice Updates status when status has changed and incoming timestamp is the same as latest + function test_updateStatus_UpdateWhen_StatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_sequencerUptimeFeed.latestRound(), 2); + assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_sequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_sequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_sequencerUptimeFeed.latestRound(), 3); + assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice Ignores out-of-order updates + function test_updateStatus_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_sequencerUptimeFeed.latestRound(), 2); + assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + + vm.recordLogs(); + + // Tries to update with stale timestamp + s_sequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + assertEq(entries[0].topics[0], keccak256("UpdateIgnored(bool,uint64,bool,uint64)")); + } +} + +contract BaseSequencerUptimeFeed_AggregatorV3Interface is BaseSequencerUptimeFeed_Setup { + /// @notice Returns valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface_ReturnsValidData() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice Reverts when getRoundData is called for a round that does not exist yet + function test_getRoundData_RevertWhen_RoundDoesNotExist() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_sequencerUptimeFeed.getRoundData(2); + } + + /// @notice Returns the getAnswer for the latest round + function test_getAnswer_ReturnsValidAnswer() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + uint256 startedAt; + (, , startedAt, , ) = s_sequencerUptimeFeed.latestRoundData(); + + s_sequencerUptimeFeed.updateStatus(true, uint64(startedAt + 1000)); + + assertEq(0, s_sequencerUptimeFeed.getAnswer(1)); + } + + /// @notice Reverts when getAnswer is called for a round that does not exist yet + function test_getAnswer_RevertWhen_RoundDoesNotExist() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_sequencerUptimeFeed.getAnswer(2); + } + + /// @notice Returns the getTimestamp for the latest round + function test_getTimestamp_ReturnsValidTimestamp() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + uint256 startedAt; + (, , startedAt, , ) = s_sequencerUptimeFeed.latestRoundData(); + + s_sequencerUptimeFeed.updateStatus(true, uint64(startedAt + 1000)); + + assertEq(startedAt, s_sequencerUptimeFeed.getTimestamp(1)); + } + + /// @notice Reverts when getTimestamp is called for a round that does not exist yet + function test_getTimestamp_RevertWhen_RoundDoesNotExist() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_sequencerUptimeFeed.getTimestamp(2); + } +} + +contract BaseSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is BaseSequencerUptimeFeed_Setup { + /// @notice Disallows reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_ProtectReads_DisallowWhen_NotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_sequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_sequencerUptimeFeed.checkEnabled(), true); + assertEq(s_sequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice Allows reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_ProtectReads_AllowWhen_Whitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_sequencerUptimeFeed)); + + // Whitelist consumer + s_sequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_sequencerUptimeFeed.checkEnabled(), true); + assertEq(s_sequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol new file mode 100644 index 00000000000..4b0868c71b3 --- /dev/null +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {BaseValidator} from "../../../base/BaseValidator.sol"; +import {MockBaseValidator} from "../../mocks/MockBaseValidator.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract BaseValidator_Setup is L2EPTest { + address internal immutable L2_SEQ_STATUS_RECORDER_ADDRESS = makeAddr("L2_SEQ_STATUS_RECORDER_ADDRESS"); + address internal immutable DUMMY_L1_XDOMAIN_MSNGR_ADDR = makeAddr("DUMMY_L1_XDOMAIN_MSNGR_ADDR"); + address internal immutable DUMMY_L2_UPTIME_FEED_ADDR = makeAddr("DUMMY_L2_UPTIME_FEED_ADDR"); + uint32 internal constant INIT_GAS_LIMIT = 1900000; + + BaseValidator internal s_baseValidator; + + /// Fake event that will get emitted when `requestL2TransactionDirect` is called + /// Definition is taken from MockZKSyncL1Bridge + event SentMessage(address indexed sender, bytes message); + + /// Setup + function setUp() public { + s_baseValidator = new MockBaseValidator( + DUMMY_L1_XDOMAIN_MSNGR_ADDR, + L2_SEQ_STATUS_RECORDER_ADDRESS, + INIT_GAS_LIMIT + ); + } +} + +contract BaseValidator_Constructor is BaseValidator_Setup { + /// @notice Reverts when L1 bridge address is zero + function test_Constructor_RevertWhen_L1BridgeAddressIsZero() public { + vm.expectRevert(BaseValidator.L1CrossDomainMessengerAddressZero.selector); + new MockBaseValidator(address(0), DUMMY_L2_UPTIME_FEED_ADDR, INIT_GAS_LIMIT); + } + + /// @notice Reverts when L2 Uptime feed address is zero + function test_Constructor_RevertWhen_L2UptimeFeedAddressIsZero() public { + vm.expectRevert(BaseValidator.L2UptimeFeedAddrZero.selector); + new MockBaseValidator(DUMMY_L1_XDOMAIN_MSNGR_ADDR, address(0), INIT_GAS_LIMIT); + } +} + +contract BaseValidator_GetAndSetGasLimit is BaseValidator_Setup { + /// @notice Verifies the correct retrieval and update of the gas limit + function test_GetAndSetGasLimit_CorrectlyHandlesGasLimit() public { + assertEq(s_baseValidator.getGasLimit(), INIT_GAS_LIMIT); + + uint32 newGasLimit = INIT_GAS_LIMIT + 1; + + vm.expectEmit(); + emit BaseValidator.GasLimitUpdated(newGasLimit); + s_baseValidator.setGasLimit(newGasLimit); + + assertEq(s_baseValidator.getGasLimit(), newGasLimit); + } +} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol index 5b319d32407..8e9c387c875 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol @@ -3,289 +3,50 @@ pragma solidity ^0.8.24; import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; import {ZKSyncSequencerUptimeFeed} from "../../../zksync/ZKSyncSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../shared/BaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ZKSyncSequencerUptimeFeedTest is L2EPTest { +contract ZKSyncSequencerUptimeFeed_TestWrapper is ZKSyncSequencerUptimeFeed { + constructor(address l1SenderAddress, bool initialStatus) ZKSyncSequencerUptimeFeed(l1SenderAddress, initialStatus) {} + + /// @notice Exposes the internal _validateSender function for testing + function validateSenderTestWrapper(address l1Sender) external view { + super._validateSender(l1Sender); + } +} + +contract ZKSyncSequencerUptimeFeed_Setup is L2EPTest { /// Helper Variables - address internal s_aliasedL1OwnerAddress = AddressAliasHelper.applyL1ToL2Alias(s_l1OwnerAddr); + address internal l1SenderAddress = address(5); + address internal s_aliasedL1SenderAddress = AddressAliasHelper.applyL1ToL2Alias(l1SenderAddress); /// L2EP contracts - ZKSyncSequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; - - /// Events - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - event RoundUpdated(int256 status, uint64 updatedAt); + ZKSyncSequencerUptimeFeed_TestWrapper internal s_zksyncSequencerUptimeFeed; /// Setup function setUp() public { // Deploys contracts - s_zksyncSequencerUptimeFeed = new ZKSyncSequencerUptimeFeed(s_l1OwnerAddr, false); - } -} - -contract ZKSyncSequencerUptimeFeed_Constructor is ZKSyncSequencerUptimeFeedTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Checks L1 sender - address actualL1Addr = s_zksyncSequencerUptimeFeed.l1Sender(); - assertEq(actualL1Addr, s_l1OwnerAddr); - - // Checks latest round data - (uint80 roundId, int256 answer, , , ) = s_zksyncSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); + s_zksyncSequencerUptimeFeed = new ZKSyncSequencerUptimeFeed_TestWrapper(l1SenderAddress, false); } } -contract ZKSyncSequencerUptimeFeed_UpdateStatus is ZKSyncSequencerUptimeFeedTest { - /// @notice it should revert if called by an unauthorized account - function test_RevertIfNotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); +contract ZKSyncSequencerUptimeFeed_ValidateSender is ZKSyncSequencerUptimeFeed_Setup { + /// @notice Reverts when pass is not valid + function test_ValidateSender_RevertWhen_PassIsNotValid() public { + // Sets msg.sender and tx.origin to an authorized address + vm.startPrank(s_aliasedL1SenderAddress, s_aliasedL1SenderAddress); // Tries to update the status from an unauthorized account vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should update status when status has not changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenNoChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Fetches the latest timestamp - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data before updating it - ( - uint80 roundIdBeforeUpdate, - int256 answerBeforeUpdate, - uint256 startedAtBeforeUpdate, - , - uint80 answeredInRoundBeforeUpdate - ) = s_zksyncSequencerUptimeFeed.latestRoundData(); - - // Submit another status update with the same status - vm.expectEmit(); - emit RoundUpdated(1, uint64(block.timestamp)); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data after updating it - ( - uint80 roundIdAfterUpdate, - int256 answerAfterUpdate, - uint256 startedAtAfterUpdate, - uint256 updatedAtAfterUpdate, - uint80 answeredInRoundAfterUpdate - ) = s_zksyncSequencerUptimeFeed.latestRoundData(); - - // Verifies the latest round data has been properly updated - assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); - assertEq(answerAfterUpdate, answerBeforeUpdate); - assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); - assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); - assertEq(updatedAtAfterUpdate, block.timestamp); - } - - /// @notice it should update status when status has changed and incoming timestamp is newer than the latest - function test_UpdateStatusWhenStatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Submits a status update - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should update status when status has changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Fetches the latest timestamp - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should ignore out-of-order updates - function test_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Submits a status update - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - // TODO: how can we check that an AnswerUpdated event was NOT emitted - s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - } -} - -contract ZKSyncSequencerUptimeFeed_AggregatorV3Interface is ZKSyncSequencerUptimeFeedTest { - /// @notice it should return valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); - - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; - - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(1); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) - function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_zksyncSequencerUptimeFeed.getRoundData(2); - } - - /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) - function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_zksyncSequencerUptimeFeed.getAnswer(2); - } - - /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) - function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_zksyncSequencerUptimeFeed.getTimestamp(2); + s_zksyncSequencerUptimeFeed.validateSenderTestWrapper(address(6)); } -} - -contract ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ZKSyncSequencerUptimeFeedTest { - /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); - - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); - } - - /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); - - // Whitelist consumer - s_zksyncSequencerUptimeFeed.addAccess(address(feedConsumer)); - // Sanity - consumer is whitelisted - assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + /// @notice Passes when sender is valid + function test_ValidateSender_SuccessWhen_SenderIsValid() public { + // Sets msg.sender and tx.origin to an authorized address + vm.startPrank(s_aliasedL1SenderAddress, s_aliasedL1SenderAddress); - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); + // Tries to update the status from an authorized account + s_zksyncSequencerUptimeFeed.validateSenderTestWrapper(l1SenderAddress); } } diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol index 1a0f16d6ae0..e36a2732c27 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol @@ -4,13 +4,13 @@ pragma solidity ^0.8.24; import {MockBridgehub} from "../../mocks/zksync/MockZKSyncL1Bridge.sol"; import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; import {ZKSyncValidator} from "../../../zksync/ZKSyncValidator.sol"; -import {BaseValidator} from "../../../shared/BaseValidator.sol"; +import {BaseValidator} from "../../../base/BaseValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ZKSyncValidatorTest is L2EPTest { - address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = address(0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b); - address internal constant DUMMY_L1_XDOMAIN_MSNGR_ADDR = address(0xa04Fc18f012B1a5A8231c7Ee4b916Dd6dbd271b6); - address internal constant DUMMY_L2_UPTIME_FEED_ADDR = address(0xFe31891940A2e5f04B76eD8bD1038E44127d1512); +contract ZKSyncValidator_Setup is L2EPTest { + address internal immutable L2_SEQ_STATUS_RECORDER_ADDRESS = makeAddr("L2_SEQ_STATUS_RECORDER_ADDRESS"); + address internal immutable DUMMY_L1_XDOMAIN_MSNGR_ADDR = makeAddr("DUMMY_L1_XDOMAIN_MSNGR_ADDR"); + address internal immutable DUMMY_L2_UPTIME_FEED_ADDR = makeAddr("DUMMY_L2_UPTIME_FEED_ADDR"); uint32 internal constant INIT_GAS_PER_PUBDATA_BYTE_LIMIT = 800; uint32 internal constant INIT_GAS_LIMIT = 1900000; uint32 internal constant MAIN_NET_CHAIN_ID = 300; @@ -38,9 +38,9 @@ contract ZKSyncValidatorTest is L2EPTest { } } -contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { - /// @notice it correctly validates that the chain id is valid - function test_ConstructingRevertedWithInvalidChainId() public { +contract ZKSyncValidator_Constructor is ZKSyncValidator_Setup { + /// @notice Reverts when chain ID is invalid + function test_Constructor_RevertWhen_ChainIdIsInvalid() public { vm.expectRevert(ZKSyncValidator.InvalidChainID.selector); new ZKSyncValidator( DUMMY_L1_XDOMAIN_MSNGR_ADDR, @@ -51,8 +51,8 @@ contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { ); } - /// @notice it correctly validates that the L1 bridge address is not zero - function test_ConstructingRevertedWithZeroL1BridgeAddress() public { + /// @notice Reverts when L1 bridge address is zero + function test_Constructor_RevertWhen_L1BridgeAddressIsZero() public { vm.expectRevert(BaseValidator.L1CrossDomainMessengerAddressZero.selector); new ZKSyncValidator( address(0), @@ -63,8 +63,8 @@ contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { ); } - /// @notice it correctly validates that the L2 Uptime feed address is not zero - function test_ConstructingRevertedWithZeroL2UpdateFeedAddress() public { + /// @notice Reverts when L2 update feed address is zero + function test_Constructor_RevertWhen_L2UpdateFeedAddressIsZero() public { vm.expectRevert(BaseValidator.L2UptimeFeedAddrZero.selector); new ZKSyncValidator( DUMMY_L1_XDOMAIN_MSNGR_ADDR, @@ -76,9 +76,9 @@ contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { } } -contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidatorTest { - /// @notice it correctly updates the gas limit per pubdata byte - function test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() public { +contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidator_Setup { + /// @notice Correctly gets and updates the gas per pubdata byte limit + function test_GetSetL2GasPerPubdataByteLimit_CorrectlyHandlesGasPerPubdataByteLimit() public { assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), INIT_GAS_PER_PUBDATA_BYTE_LIMIT); uint32 newGasPerPubDataByteLimit = 2000000; @@ -87,23 +87,23 @@ contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidatorTest { } } -contract ZKSyncValidator_GetChainId is ZKSyncValidatorTest { - /// @notice it correctly gets the chain id - function test_CorrectlyGetsTheChainId() public { +contract ZKSyncValidator_GetChainId is ZKSyncValidator_Setup { + /// @notice Correctly gets the chain ID + function test_GetChainId_CorrectlyGetsTheChainId() public view { assertEq(s_zksyncValidator.getChainId(), MAIN_NET_CHAIN_ID); } } -contract ZKSyncValidator_Validate is ZKSyncValidatorTest { - /// @notice it reverts if called by account with no access - function test_RevertsIfCalledByAnAccountWithNoAccess() public { +contract ZKSyncValidator_Validate is ZKSyncValidator_Setup { + /// @notice Reverts if called by an account with no access + function test_Validate_RevertWhen_CalledByAccountWithNoAccess() public { vm.startPrank(s_strangerAddr); vm.expectRevert("No access"); s_zksyncValidator.validate(0, 0, 1, 1); } - /// @notice it posts sequencer status when there is not status change - function test_PostSequencerStatusWhenThereIsNotStatusChange() public { + /// @notice Posts sequencer status when there is no status change + function test_Validate_PostSequencerStatus_NoStatusChange() public { // Gives access to the s_eoaValidator s_zksyncValidator.addAccess(s_eoaValidator); @@ -126,8 +126,8 @@ contract ZKSyncValidator_Validate is ZKSyncValidatorTest { s_zksyncValidator.validate(0, 0, 0, 0); } - /// @notice it post sequencer offline - function test_PostSequencerOffline() public { + /// @notice Posts sequencer offline status + function test_Validate_PostSequencerOffline() public { // Gives access to the s_eoaValidator s_zksyncValidator.addAccess(s_eoaValidator); diff --git a/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol index cb520d2d0ac..e464cc7407d 100644 --- a/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../base/BaseSequencerUptimeFeed.sol"; import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; diff --git a/contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol b/contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol index 10f68ce286d..39ba0cd839a 100644 --- a/contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol +++ b/contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; -import {BaseValidator} from "../shared/BaseValidator.sol"; +import {BaseValidator} from "../base/BaseValidator.sol"; import {IBridgehub, L2TransactionRequestDirect} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; From 75f9cf0e3a7e83f838d74f4e27b8c9fde8ce7962 Mon Sep 17 00:00:00 2001 From: "Simon B.Robert" Date: Mon, 9 Dec 2024 14:47:30 -0500 Subject: [PATCH 50/55] Initial commit for RMN Home config changeset (#15525) * Initial commit for RMN Home config changeset * Add RMNRemote changeset * Integrate with develop * Update deployment/ccip/changeset/cs_update_rmn_config_test.go Co-authored-by: Makram * Address PR feedback * Address some more feedback on the PR * Make MCMS optional for RMN changeset * Update deployment/ccip/changeset/cs_update_rmn_config.go Co-authored-by: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> * Address PR comments --------- Co-authored-by: Makram Co-authored-by: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> --- .../ccip/changeset/cs_update_rmn_config.go | 440 ++++++++++++++++++ .../changeset/cs_update_rmn_config_test.go | 184 ++++++++ 2 files changed, 624 insertions(+) create mode 100644 deployment/ccip/changeset/cs_update_rmn_config.go create mode 100644 deployment/ccip/changeset/cs_update_rmn_config_test.go diff --git a/deployment/ccip/changeset/cs_update_rmn_config.go b/deployment/ccip/changeset/cs_update_rmn_config.go new file mode 100644 index 00000000000..7e4d09af20f --- /dev/null +++ b/deployment/ccip/changeset/cs_update_rmn_config.go @@ -0,0 +1,440 @@ +package changeset + +import ( + "fmt" + "math/big" + "reflect" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + mcmsWrappers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" +) + +func getDeployer(e deployment.Environment, chain uint64, mcmConfig *MCMSConfig) *bind.TransactOpts { + if mcmConfig == nil { + return e.Chains[chain].DeployerKey + } + + return deployment.SimTransactOpts() +} + +type MCMSConfig struct { + MinDelay time.Duration +} + +type SetRMNHomeCandidateConfig struct { + HomeChainSelector uint64 + RMNStaticConfig rmn_home.RMNHomeStaticConfig + RMNDynamicConfig rmn_home.RMNHomeDynamicConfig + DigestToOverride [32]byte + MCMSConfig *MCMSConfig +} + +func (c SetRMNHomeCandidateConfig) Validate(state CCIPOnChainState) error { + err := deployment.IsValidChainSelector(c.HomeChainSelector) + if err != nil { + return err + } + + if len(c.RMNDynamicConfig.OffchainConfig) != 0 { + return fmt.Errorf("RMNDynamicConfig.OffchainConfig must be empty") + } + if len(c.RMNStaticConfig.OffchainConfig) != 0 { + return fmt.Errorf("RMNStaticConfig.OffchainConfig must be empty") + } + + if len(c.RMNStaticConfig.Nodes) > 256 { + return fmt.Errorf("RMNStaticConfig.Nodes must be less than 256") + } + + var ( + peerIds = make(map[[32]byte]struct{}) + offchainPublicKeys = make(map[[32]byte]struct{}) + ) + + for _, node := range c.RMNStaticConfig.Nodes { + if _, exists := peerIds[node.PeerId]; exists { + return fmt.Errorf("peerId %x is duplicated", node.PeerId) + } + peerIds[node.PeerId] = struct{}{} + + if _, exists := offchainPublicKeys[node.OffchainPublicKey]; exists { + return fmt.Errorf("offchainPublicKey %x is duplicated", node.OffchainPublicKey) + } + offchainPublicKeys[node.OffchainPublicKey] = struct{}{} + } + rmnHome := state.Chains[c.HomeChainSelector].RMNHome + + if rmnHome == nil { + return fmt.Errorf("RMNHome not found for chain %d", c.HomeChainSelector) + } + + currentDigest, err := rmnHome.GetCandidateDigest(nil) + if err != nil { + return fmt.Errorf("failed to get RMNHome candidate digest: %w", err) + } + + if currentDigest != c.DigestToOverride { + return fmt.Errorf("current digest (%x) does not match digest to override (%x)", currentDigest[:], c.DigestToOverride[:]) + } + + return nil +} + +type PromoteRMNHomeCandidateConfig struct { + HomeChainSelector uint64 + DigestToPromote [32]byte + MCMSConfig *MCMSConfig +} + +func (c PromoteRMNHomeCandidateConfig) Validate(state CCIPOnChainState) error { + err := deployment.IsValidChainSelector(c.HomeChainSelector) + if err != nil { + return err + } + + rmnHome := state.Chains[c.HomeChainSelector].RMNHome + if rmnHome == nil { + return fmt.Errorf("RMNHome not found for chain %d", c.HomeChainSelector) + } + + currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) + if err != nil { + return fmt.Errorf("failed to get RMNHome candidate digest: %w", err) + } + + if currentCandidateDigest != c.DigestToPromote { + return fmt.Errorf("current digest (%x) does not match digest to promote (%x)", currentCandidateDigest[:], c.DigestToPromote[:]) + } + + return nil +} + +// NewSetRMNHomeCandidateConfigChangeset creates a changeset to set the RMNHome candidate config +// DigestToOverride is the digest of the current candidate config that the new config will override +// StaticConfig contains the list of nodes with their peerIDs (found in their rageproxy keystore) and offchain public keys (found in the RMN keystore) +// DynamicConfig contains the list of source chains with their chain selectors, f value and the bitmap of the nodes that are oberver for each source chain +// The bitmap is a 256 bit array where each bit represents a node. If the bit matching the index of the node in the static config is set it means that the node is an observer +func NewSetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) + } + + err = config.Validate(state) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + homeChain, ok := e.Chains[config.HomeChainSelector] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found", config.HomeChainSelector) + } + + rmnHome := state.Chains[config.HomeChainSelector].RMNHome + if rmnHome == nil { + return deployment.ChangesetOutput{}, fmt.Errorf("RMNHome not found for chain %s", homeChain.String()) + } + + deployer := getDeployer(e, config.HomeChainSelector, config.MCMSConfig) + setCandidateTx, err := rmnHome.SetCandidate(deployer, config.RMNStaticConfig, config.RMNDynamicConfig, config.DigestToOverride) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("build RMNHome set candidate calldata for chain %s: %w", homeChain.String(), err) + } + + if config.MCMSConfig == nil { + chain := e.Chains[config.HomeChainSelector] + _, err := chain.Confirm(setCandidateTx) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), deployment.MaybeDataErr(err)) + } + + return deployment.ChangesetOutput{}, nil + } + + op := mcms.Operation{ + To: rmnHome.Address(), + Data: setCandidateTx.Data(), + Value: big.NewInt(0), + } + + batches := []timelock.BatchChainOperation{ + { + ChainIdentifier: mcms.ChainIdentifier(config.HomeChainSelector), + Batch: []mcms.Operation{op}, + }, + } + + timelocksPerChain := buildTimelockAddressPerChain(e, state) + + proposerMCMSes := buildProposerPerChain(e, state) + + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + batches, + "proposal to set candidate config", + config.MCMSConfig.MinDelay, + ) + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} + +func NewPromoteCandidateConfigChangeset(e deployment.Environment, config PromoteRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) + } + + err = config.Validate(state) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + homeChain, ok := e.Chains[config.HomeChainSelector] + + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found", config.HomeChainSelector) + } + + rmnHome := state.Chains[config.HomeChainSelector].RMNHome + if rmnHome == nil { + return deployment.ChangesetOutput{}, fmt.Errorf("RMNHome not found for chain %s", homeChain.String()) + } + + currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNHome candidate digest for chain %s: %w", homeChain.String(), err) + } + + currentActiveDigest, err := rmnHome.GetActiveDigest(nil) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNHome active digest for chain %s: %w", homeChain.String(), err) + } + + deployer := getDeployer(e, config.HomeChainSelector, config.MCMSConfig) + promoteCandidateTx, err := rmnHome.PromoteCandidateAndRevokeActive(deployer, currentCandidateDigest, currentActiveDigest) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("get call data to promote RMNHome candidate digest for chain %s: %w", homeChain.String(), err) + } + + if config.MCMSConfig == nil { + chain := e.Chains[config.HomeChainSelector] + _, err := chain.Confirm(promoteCandidateTx) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), deployment.MaybeDataErr(err)) + } + + return deployment.ChangesetOutput{}, nil + } + + op := mcms.Operation{ + To: rmnHome.Address(), + Data: promoteCandidateTx.Data(), + Value: big.NewInt(0), + } + + batches := []timelock.BatchChainOperation{ + { + ChainIdentifier: mcms.ChainIdentifier(config.HomeChainSelector), + Batch: []mcms.Operation{op}, + }, + } + + timelocksPerChain := buildTimelockAddressPerChain(e, state) + + proposerMCMSes := buildProposerPerChain(e, state) + + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + batches, + "proposal to promote candidate config", + config.MCMSConfig.MinDelay, + ) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal for chain %s: %w", homeChain.String(), err) + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} + +func buildTimelockPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*mcmsWrappers.RBACTimelock { + timelocksPerChain := make(map[uint64]*mcmsWrappers.RBACTimelock) + for _, chain := range e.Chains { + timelocksPerChain[chain.Selector] = state.Chains[chain.Selector].Timelock + } + return timelocksPerChain +} + +func buildTimelockAddressPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]common.Address { + timelocksPerChain := buildTimelockPerChain(e, state) + timelockAddressPerChain := make(map[uint64]common.Address) + for chain, timelock := range timelocksPerChain { + timelockAddressPerChain[chain] = timelock.Address() + } + return timelockAddressPerChain +} + +func buildProposerPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*gethwrappers.ManyChainMultiSig { + proposerPerChain := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for _, chain := range e.Chains { + proposerPerChain[chain.Selector] = state.Chains[chain.Selector].ProposerMcm + } + return proposerPerChain +} + +func buildRMNRemotePerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*rmn_remote.RMNRemote { + timelocksPerChain := make(map[uint64]*rmn_remote.RMNRemote) + for _, chain := range e.Chains { + timelocksPerChain[chain.Selector] = state.Chains[chain.Selector].RMNRemote + } + return timelocksPerChain +} + +type SetRMNRemoteConfig struct { + HomeChainSelector uint64 + Signers []rmn_remote.RMNRemoteSigner + F uint64 + MCMSConfig *MCMSConfig +} + +func (c SetRMNRemoteConfig) Validate() error { + err := deployment.IsValidChainSelector(c.HomeChainSelector) + if err != nil { + return err + } + + for i := 0; i < len(c.Signers)-1; i++ { + if c.Signers[i].NodeIndex >= c.Signers[i+1].NodeIndex { + return fmt.Errorf("signers must be in ascending order of nodeIndex") + } + } + + if len(c.Signers) < 2*int(c.F)+1 { + return fmt.Errorf("signers count must greater than or equal to %d", 2*c.F+1) + } + + return nil +} + +func NewSetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteConfig) (deployment.ChangesetOutput, error) { + state, err := LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) + } + + lggr := e.Logger + + err = config.Validate() + if err != nil { + return deployment.ChangesetOutput{}, err + } + + homeChain, ok := e.Chains[config.HomeChainSelector] + + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found", config.HomeChainSelector) + } + + rmnHome := state.Chains[config.HomeChainSelector].RMNHome + if rmnHome == nil { + return deployment.ChangesetOutput{}, fmt.Errorf("RMNHome not found for chain %s", homeChain.String()) + } + + activeConfig, err := rmnHome.GetActiveDigest(nil) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNHome active digest for chain %s: %w", homeChain.String(), err) + } + + rmnRemotePerChain := buildRMNRemotePerChain(e, state) + batches := make([]timelock.BatchChainOperation, 0) + for chain, remote := range rmnRemotePerChain { + if remote == nil { + continue + } + + currentVersionConfig, err := remote.GetVersionedConfig(nil) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNRemote config for chain %s: %w", e.Chains[chain].String(), err) + } + + newConfig := rmn_remote.RMNRemoteConfig{ + RmnHomeContractConfigDigest: activeConfig, + Signers: config.Signers, + F: config.F, + } + + if reflect.DeepEqual(currentVersionConfig.Config, newConfig) { + lggr.Infow("RMNRemote config already up to date", "chain", e.Chains[chain].String()) + continue + } + + deployer := getDeployer(e, chain, config.MCMSConfig) + tx, err := remote.SetConfig(deployer, newConfig) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("build call data to set RMNRemote config for chain %s: %w", e.Chains[chain].String(), err) + } + + if config.MCMSConfig == nil { + _, err := e.Chains[chain].Confirm(tx) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", e.Chains[chain].String(), deployment.MaybeDataErr(err)) + } + } + + op := mcms.Operation{ + To: remote.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + } + + batch := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(chain), + Batch: []mcms.Operation{op}, + } + + batches = append(batches, batch) + } + + if config.MCMSConfig == nil { + return deployment.ChangesetOutput{}, nil + } + + timelocksPerChain := buildTimelockAddressPerChain(e, state) + + proposerMCMSes := buildProposerPerChain(e, state) + + prop, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + batches, + "proposal to promote candidate config", + config.MCMSConfig.MinDelay, + ) + + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal for chain %s: %w", homeChain.String(), err) + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} diff --git a/deployment/ccip/changeset/cs_update_rmn_config_test.go b/deployment/ccip/changeset/cs_update_rmn_config_test.go new file mode 100644 index 00000000000..deae3e2e771 --- /dev/null +++ b/deployment/ccip/changeset/cs_update_rmn_config_test.go @@ -0,0 +1,184 @@ +package changeset + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +type updateRMNConfigTestCase struct { + useMCMS bool + name string +} + +func TestUpdateRMNConfig(t *testing.T) { + t.Parallel() + testCases := []updateRMNConfigTestCase{ + { + useMCMS: true, + name: "with MCMS", + }, + { + useMCMS: false, + name: "without MCMS", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + updateRMNConfig(t, tc) + }) + } +} + +func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { + e := NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), memory.MemoryEnvironmentConfig{ + Chains: 2, + Nodes: 4, + Bootstraps: 1, + }, nil) + + state, err := LoadOnchainState(e.Env) + require.NoError(t, err) + + contractsByChain := make(map[uint64][]common.Address) + rmnRemoteAddressesByChain := buildRMNRemoteAddressPerChain(e.Env, state) + for chainSelector, rmnRemoteAddress := range rmnRemoteAddressesByChain { + contractsByChain[chainSelector] = []common.Address{rmnRemoteAddress} + } + + contractsByChain[e.HomeChainSel] = append(contractsByChain[e.HomeChainSel], state.Chains[e.HomeChainSel].RMNHome.Address()) + + timelocksPerChain := buildTimelockPerChain(e.Env, state) + if tc.useMCMS { + // This is required because RMNHome is initially owned by the deployer + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), + Config: commonchangeset.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contractsByChain, + MinDelay: 0, + }, + }, + }) + } + + rmnHome := state.Chains[e.HomeChainSel].RMNHome + + previousCandidateDigest, err := rmnHome.GetCandidateDigest(nil) + require.NoError(t, err) + previousActiveDigest, err := rmnHome.GetActiveDigest(nil) + require.NoError(t, err) + + var mcmsConfig *MCMSConfig = nil + + if tc.useMCMS { + mcmsConfig = &MCMSConfig{ + MinDelay: 0, + } + } + + setRMNHomeCandidateConfig := SetRMNHomeCandidateConfig{ + HomeChainSelector: e.HomeChainSel, + RMNStaticConfig: rmn_home.RMNHomeStaticConfig{ + Nodes: []rmn_home.RMNHomeNode{}, + OffchainConfig: []byte(""), + }, + RMNDynamicConfig: rmn_home.RMNHomeDynamicConfig{ + SourceChains: []rmn_home.RMNHomeSourceChain{}, + OffchainConfig: []byte(""), + }, + MCMSConfig: mcmsConfig, + } + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(NewSetRMNHomeCandidateConfigChangeset), + Config: setRMNHomeCandidateConfig, + }, + }) + + require.NoError(t, err) + + state, err = LoadOnchainState(e.Env) + require.NoError(t, err) + + currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) + require.NoError(t, err) + currentActiveDigest, err := rmnHome.GetActiveDigest(nil) + require.NoError(t, err) + + require.NotEqual(t, previousCandidateDigest, currentCandidateDigest) + require.Equal(t, previousActiveDigest, currentActiveDigest) + + promoteConfig := PromoteRMNHomeCandidateConfig{ + HomeChainSelector: e.HomeChainSel, + DigestToPromote: currentCandidateDigest, + MCMSConfig: mcmsConfig, + } + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(NewPromoteCandidateConfigChangeset), + Config: promoteConfig, + }, + }) + + require.NoError(t, err) + currentActiveDigest, err = rmnHome.GetActiveDigest(nil) + + require.NoError(t, err) + require.NotEqual(t, previousActiveDigest, currentActiveDigest) + + setRemoteConfig := SetRMNRemoteConfig{ + HomeChainSelector: e.HomeChainSel, + Signers: []rmn_remote.RMNRemoteSigner{ + { + OnchainPublicKey: common.Address{}, + NodeIndex: 0, + }, + }, + F: 0, + MCMSConfig: mcmsConfig, + } + + _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(NewSetRMNRemoteConfigChangeset), + Config: setRemoteConfig, + }, + }) + + require.NoError(t, err) + rmnRemotePerChain := buildRMNRemotePerChain(e.Env, state) + for _, rmnRemote := range rmnRemotePerChain { + remoteConfigSetEvents, err := rmnRemote.FilterConfigSet(nil, nil) + require.NoError(t, err) + var lastEvent *rmn_remote.RMNRemoteConfigSet + for remoteConfigSetEvents.Next() { + lastEvent = remoteConfigSetEvents.Event + } + require.NotNil(t, lastEvent) + require.Equal(t, lastEvent.Config.RmnHomeContractConfigDigest, currentActiveDigest) + } +} + +func buildRMNRemoteAddressPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]common.Address { + rmnRemotePerChain := buildRMNRemotePerChain(e, state) + rmnRemoteAddressPerChain := make(map[uint64]common.Address) + for chain, remote := range rmnRemotePerChain { + if remote == nil { + continue + } + rmnRemoteAddressPerChain[chain] = remote.Address() + } + return rmnRemoteAddressPerChain +} From 7b6e20f1b40506467349eb0203178aa2c51f5d41 Mon Sep 17 00:00:00 2001 From: krehermann <16602512+krehermann@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:04:55 -0700 Subject: [PATCH 51/55] update nodes changeset mcms (#15543) * support mcms in ocr3 contract config changeset * test working for ocr3 config with mcms * migrate deployment test to setup test env * fix test * refactor forwarder configuration changeset for mcms * refactor capability update changeset mcms * plumbing update nodes * update node with mcms --- .changeset/many-crews-wave.md | 5 + deployment/keystone/capability_management.go | 94 +++++++------ .../keystone/changeset/deploy_ocr3_test.go | 9 +- deployment/keystone/changeset/helpers_test.go | 10 +- .../internal/append_node_capabilities.go | 5 +- .../keystone/changeset/internal/test/utils.go | 1 + .../keystone/changeset/internal/update_don.go | 7 +- .../internal/update_node_capabilities.go | 6 +- .../changeset/internal/update_nodes.go | 60 ++++++++- .../changeset/update_node_capabilities.go | 2 + deployment/keystone/changeset/update_nodes.go | 38 +++++- .../keystone/changeset/update_nodes_test.go | 125 ++++++++++++++++++ deployment/keystone/deploy.go | 5 +- 13 files changed, 296 insertions(+), 71 deletions(-) create mode 100644 .changeset/many-crews-wave.md create mode 100644 deployment/keystone/changeset/update_nodes_test.go diff --git a/.changeset/many-crews-wave.md b/.changeset/many-crews-wave.md new file mode 100644 index 00000000000..328a00e2f48 --- /dev/null +++ b/.changeset/many-crews-wave.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal refactor update nodes changeset to support mcms diff --git a/deployment/keystone/capability_management.go b/deployment/keystone/capability_management.go index 4e15ea897ab..888cba5b931 100644 --- a/deployment/keystone/capability_management.go +++ b/deployment/keystone/capability_management.go @@ -2,8 +2,8 @@ package keystone import ( "fmt" - "strings" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" @@ -11,56 +11,35 @@ import ( // AddCapabilities adds the capabilities to the registry // it tries to add all capabilities in one go, if that fails, it falls back to adding them one by one -func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain deployment.Chain, capabilities []kcr.CapabilitiesRegistryCapability) error { + +func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain deployment.Chain, capabilities []kcr.CapabilitiesRegistryCapability, useMCMS bool) ([]timelock.MCMSWithTimelockProposal, error) { if len(capabilities) == 0 { - return nil + return nil, nil } - // dedup capabilities - var deduped []kcr.CapabilitiesRegistryCapability - seen := make(map[string]struct{}) - for _, cap := range capabilities { - if _, ok := seen[CapabilityID(cap)]; !ok { - seen[CapabilityID(cap)] = struct{}{} - deduped = append(deduped, cap) - } + deduped, err := dedupCapabilities(registry, capabilities) + if err != nil { + return nil, fmt.Errorf("failed to dedup capabilities: %w", err) } - - tx, err := registry.AddCapabilities(chain.DeployerKey, deduped) + txOpts := chain.DeployerKey + if useMCMS { + txOpts = deployment.SimTransactOpts() + } + tx, err := registry.AddCapabilities(txOpts, deduped) if err != nil { err = DecodeErr(kcr.CapabilitiesRegistryABI, err) - // no typed errors in the abi, so we have to do string matching - // try to add all capabilities in one go, if that fails, fall back to 1-by-1 - if !strings.Contains(err.Error(), "CapabilityAlreadyExists") { - return fmt.Errorf("failed to call AddCapabilities: %w", err) - } - lggr.Warnw("capabilities already exist, falling back to 1-by-1", "capabilities", deduped) - for _, cap := range deduped { - tx, err = registry.AddCapabilities(chain.DeployerKey, []kcr.CapabilitiesRegistryCapability{cap}) - if err != nil { - err = DecodeErr(kcr.CapabilitiesRegistryABI, err) - if strings.Contains(err.Error(), "CapabilityAlreadyExists") { - lggr.Warnw("capability already exists, skipping", "capability", cap) - continue - } - return fmt.Errorf("failed to call AddCapabilities for capability %v: %w", cap, err) - } - // 1-by-1 tx is pending and we need to wait for it to be mined - _, err = chain.Confirm(tx) - if err != nil { - return fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) - } - lggr.Debugw("registered capability", "capability", cap) - - } - } else { - // the bulk add tx is pending and we need to wait for it to be mined + return nil, fmt.Errorf("failed to add capabilities: %w", err) + } + var proposals []timelock.MCMSWithTimelockProposal + if !useMCMS { _, err = chain.Confirm(tx) if err != nil { - return fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) + return nil, fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) } lggr.Info("registered capabilities", "capabilities", deduped) + } else { + // TODO } - return nil + return proposals, nil } // CapabilityID returns a unique id for the capability @@ -68,3 +47,36 @@ func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, cha func CapabilityID(c kcr.CapabilitiesRegistryCapability) string { return fmt.Sprintf("%s@%s", c.LabelledName, c.Version) } + +// dedupCapabilities deduplicates the capabilities +// dedup capabilities with respect to the registry +// contract reverts on adding the same capability twice and that would cause the whole transaction to revert +// which is very bad for us for mcms +func dedupCapabilities(registry *kcr.CapabilitiesRegistry, capabilities []kcr.CapabilitiesRegistryCapability) ([]kcr.CapabilitiesRegistryCapability, error) { + var out []kcr.CapabilitiesRegistryCapability + existing, err := registry.GetCapabilities(nil) + if err != nil { + return nil, fmt.Errorf("failed to call GetCapabilities: %w", err) + } + existingByID := make(map[[32]byte]struct{}) + for _, cap := range existing { + existingByID[cap.HashedId] = struct{}{} + } + seen := make(map[string]struct{}) + for _, candidate := range capabilities { + h, err := registry.GetHashedCapabilityId(nil, candidate.LabelledName, candidate.Version) + if err != nil { + return nil, fmt.Errorf("failed to call GetHashedCapabilityId: %w", err) + } + // dedup input capabilities + if _, exists := seen[CapabilityID(candidate)]; exists { + continue + } + seen[CapabilityID(candidate)] = struct{}{} + // dedup with respect to the registry + if _, exists := existingByID[h]; !exists { + out = append(out, candidate) + } + } + return out, nil +} diff --git a/deployment/keystone/changeset/deploy_ocr3_test.go b/deployment/keystone/changeset/deploy_ocr3_test.go index 0e5fea6b7c6..ae00f19fc22 100644 --- a/deployment/keystone/changeset/deploy_ocr3_test.go +++ b/deployment/keystone/changeset/deploy_ocr3_test.go @@ -46,7 +46,6 @@ func TestDeployOCR3(t *testing.T) { func TestConfigureOCR3(t *testing.T) { t.Parallel() - lggr := logger.Test(t) c := kslib.OracleConfig{ MaxFaultyOracles: 1, @@ -119,13 +118,9 @@ func TestConfigureOCR3(t *testing.T) { assert.NotNil(t, csOut.Proposals) t.Logf("got: %v", csOut.Proposals[0]) - contractSetsResp, err := kslib.GetContractSets(lggr, &kslib.GetContractSetsRequest{ - Chains: te.Env.Chains, - AddressBook: te.Env.ExistingAddresses, - }) - require.NoError(t, err) + contracts := te.ContractSets()[te.RegistrySelector] var timelocks = map[uint64]*gethwrappers.RBACTimelock{ - te.RegistrySelector: contractSetsResp.ContractSets[te.RegistrySelector].Timelock, + te.RegistrySelector: contracts.Timelock, } // now apply the changeset such that the proposal is signed and execed w2 := &bytes.Buffer{} diff --git a/deployment/keystone/changeset/helpers_test.go b/deployment/keystone/changeset/helpers_test.go index faf112867ce..a4e98efd550 100644 --- a/deployment/keystone/changeset/helpers_test.go +++ b/deployment/keystone/changeset/helpers_test.go @@ -115,6 +115,7 @@ func (te TestEnv) ContractSets() map[uint64]kslib.ContractSet { } // SetupTestEnv sets up a keystone test environment with the given configuration +// TODO: make more configurable; eg many tests don't need all the nodes (like when testing a registry change) func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { require.NoError(t, c.Validate()) lggr := logger.Test(t) @@ -220,15 +221,13 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { } var allDons = []keystone.DonCapabilities{wfDon, cwDon, assetDon} - _, err = kschangeset.ConfigureInitialContractsChangeset(env, kschangeset.InitialContractsCfg{ + csOut, err := kschangeset.ConfigureInitialContractsChangeset(env, kschangeset.InitialContractsCfg{ RegistryChainSel: registryChainSel, Dons: allDons, OCR3Config: &ocr3Config, }) require.NoError(t, err) - // TODO: KS-rm_deploy_opt - //require.Nil(t, csOut.AddressBook, "no new addresses should be created in configure initial contracts") - //require.NoError(t, env.ExistingAddresses.Merge(csOut.AddressBook)) + require.Nil(t, csOut.AddressBook, "no new addresses should be created in configure initial contracts") req := &keystone.GetContractSetsRequest{ Chains: env.Chains, @@ -256,8 +255,7 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { validateDon(t, gotRegistry, assetNodes, assetDon) if c.UseMCMS { - // TODO: mcms on all the chains, currently only on the registry chain. need to fix this for forwarders - // deploy, configure and xfer ownership of MCMS + // deploy, configure and xfer ownership of MCMS on all chains timelockCfgs := make(map[uint64]commontypes.MCMSWithTimelockConfig) for sel := range env.Chains { t.Logf("Enabling MCMS on chain %d", sel) diff --git a/deployment/keystone/changeset/internal/append_node_capabilities.go b/deployment/keystone/changeset/internal/append_node_capabilities.go index cb28c03c6f5..6168356c351 100644 --- a/deployment/keystone/changeset/internal/append_node_capabilities.go +++ b/deployment/keystone/changeset/internal/append_node_capabilities.go @@ -15,6 +15,7 @@ type AppendNodeCapabilitiesRequest struct { Registry *kcr.CapabilitiesRegistry P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability + UseMCMS bool } func (req *AppendNodeCapabilitiesRequest) Validate() error { @@ -36,7 +37,7 @@ func AppendNodeCapabilitiesImpl(lggr logger.Logger, req *AppendNodeCapabilitiesR for _, cap := range req.P2pToCapabilities { capabilities = append(capabilities, cap...) } - err := kslib.AddCapabilities(lggr, req.Registry, req.Chain, capabilities) + proposals, err := kslib.AddCapabilities(lggr, req.Registry, req.Chain, capabilities, req.UseMCMS) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -55,10 +56,12 @@ func AppendNodeCapabilitiesImpl(lggr logger.Logger, req *AppendNodeCapabilitiesR Chain: req.Chain, Registry: req.Registry, P2pToUpdates: updatesByPeer, + UseMCMS: req.UseMCMS, } resp, err := UpdateNodes(lggr, updateNodesReq) if err != nil { return nil, fmt.Errorf("failed to update nodes: %w", err) } + resp.Proposals = append(proposals, resp.Proposals...) return resp, nil } diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/internal/test/utils.go index 6fe4a8f4a2e..a7aed2c9cb1 100644 --- a/deployment/keystone/changeset/internal/test/utils.go +++ b/deployment/keystone/changeset/internal/test/utils.go @@ -33,6 +33,7 @@ type SetupTestRegistryRequest struct { P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability NopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc Dons []Don + // TODO maybe add support for MCMS at this level } type SetupTestRegistryResponse struct { diff --git a/deployment/keystone/changeset/internal/update_don.go b/deployment/keystone/changeset/internal/update_don.go index 4883368dc4d..d56f77c1c78 100644 --- a/deployment/keystone/changeset/internal/update_don.go +++ b/deployment/keystone/changeset/internal/update_don.go @@ -9,6 +9,7 @@ import ( "sort" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -31,6 +32,8 @@ type UpdateDonRequest struct { P2PIDs []p2pkey.PeerID // this is the unique identifier for the don CapabilityConfigs []CapabilityConfig // if Config subfield is nil, a default config is used + + UseMCMS bool } func (r *UpdateDonRequest) appendNodeCapabilitiesRequest() *AppendNodeCapabilitiesRequest { @@ -38,6 +41,7 @@ func (r *UpdateDonRequest) appendNodeCapabilitiesRequest() *AppendNodeCapabiliti Chain: r.Chain, Registry: r.Registry, P2pToCapabilities: make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability), + UseMCMS: r.UseMCMS, } for _, p2pid := range r.P2PIDs { if _, exists := out.P2pToCapabilities[p2pid]; !exists { @@ -61,7 +65,8 @@ func (r *UpdateDonRequest) Validate() error { } type UpdateDonResponse struct { - DonInfo kcr.CapabilitiesRegistryDONInfo + DonInfo kcr.CapabilitiesRegistryDONInfo + Proposals []timelock.MCMSWithTimelockProposal } func UpdateDon(lggr logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, error) { diff --git a/deployment/keystone/changeset/internal/update_node_capabilities.go b/deployment/keystone/changeset/internal/update_node_capabilities.go index 0420c46f27d..72e6f99ee49 100644 --- a/deployment/keystone/changeset/internal/update_node_capabilities.go +++ b/deployment/keystone/changeset/internal/update_node_capabilities.go @@ -15,6 +15,8 @@ type UpdateNodeCapabilitiesImplRequest struct { Registry *kcr.CapabilitiesRegistry P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability + + UseMCMS bool } func (req *UpdateNodeCapabilitiesImplRequest) Validate() error { @@ -37,7 +39,7 @@ func UpdateNodeCapabilitiesImpl(lggr logger.Logger, req *UpdateNodeCapabilitiesI for _, cap := range req.P2pToCapabilities { capabilities = append(capabilities, cap...) } - err := kslib.AddCapabilities(lggr, req.Registry, req.Chain, capabilities) + proposals, err := kslib.AddCapabilities(lggr, req.Registry, req.Chain, capabilities, req.UseMCMS) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -51,10 +53,12 @@ func UpdateNodeCapabilitiesImpl(lggr logger.Logger, req *UpdateNodeCapabilitiesI Chain: req.Chain, Registry: req.Registry, P2pToUpdates: p2pToUpdates, + UseMCMS: req.UseMCMS, } resp, err := UpdateNodes(lggr, updateNodesReq) if err != nil { return nil, fmt.Errorf("failed to update nodes: %w", err) } + resp.Proposals = append(proposals, resp.Proposals...) return resp, nil } diff --git a/deployment/keystone/changeset/internal/update_nodes.go b/deployment/keystone/changeset/internal/update_nodes.go index b8a08c37e50..2eba6d063df 100644 --- a/deployment/keystone/changeset/internal/update_nodes.go +++ b/deployment/keystone/changeset/internal/update_nodes.go @@ -5,15 +5,21 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" "sort" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) @@ -30,6 +36,9 @@ type UpdateNodesRequest struct { Registry *kcr.CapabilitiesRegistry P2pToUpdates map[p2pkey.PeerID]NodeUpdate + + ContractSet kslib.ContractSet // contract set for the given chain + UseMCMS bool } func (req *UpdateNodesRequest) NodeParams() ([]kcr.CapabilitiesRegistryNodeParams, error) { @@ -80,10 +89,12 @@ func (req *UpdateNodesRequest) Validate() error { type UpdateNodesResponse struct { NodeParams []kcr.CapabilitiesRegistryNodeParams + Proposals []timelock.MCMSWithTimelockProposal } // UpdateNodes updates the nodes in the registry -// the update sets the signer and capabilities for each node. it does not append capabilities to the existing ones +// the update sets the signer and capabilities for each node. +// The nodes and capabilities must already exist in the registry. func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesResponse, error) { if err := req.Validate(); err != nil { return nil, fmt.Errorf("failed to validate request: %w", err) @@ -94,17 +105,54 @@ func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesRespo err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to make node params: %w", err) } - tx, err := req.Registry.UpdateNodes(req.Chain.DeployerKey, params) + txOpts := req.Chain.DeployerKey + if req.UseMCMS { + txOpts = deployment.SimTransactOpts() + } + tx, err := req.Registry.UpdateNodes(txOpts, params) if err != nil { err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call UpdateNodes: %w", err) } - _, err = req.Chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm UpdateNodes confirm transaction %s: %w", tx.Hash().String(), err) + var proposals []timelock.MCMSWithTimelockProposal + if !req.UseMCMS { + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm UpdateNodes confirm transaction %s: %w", tx.Hash().String(), err) + } + } else { + ops := timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(req.Chain.Selector), + Batch: []mcms.Operation{ + { + To: req.Registry.Address(), + Data: tx.Data(), + Value: big.NewInt(0), + }, + }, + } + timelocksPerChain := map[uint64]common.Address{ + req.Chain.Selector: req.ContractSet.Timelock.Address(), + } + proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ + req.Chain.Selector: req.ContractSet.ProposerMcm, + } + + proposal, err := proposalutils.BuildProposalFromBatches( + timelocksPerChain, + proposerMCMSes, + []timelock.BatchChainOperation{ops}, + "proposal to set update nodes", + 0, + ) + if err != nil { + return nil, fmt.Errorf("failed to build proposal: %w", err) + } + proposals = append(proposals, *proposal) } - return &UpdateNodesResponse{NodeParams: params}, nil + + return &UpdateNodesResponse{NodeParams: params, Proposals: proposals}, nil } // AppendCapabilities appends the capabilities to the existing capabilities of the nodes listed in p2pIds in the registry diff --git a/deployment/keystone/changeset/update_node_capabilities.go b/deployment/keystone/changeset/update_node_capabilities.go index 1d6dde6af5a..655614ed7f0 100644 --- a/deployment/keystone/changeset/update_node_capabilities.go +++ b/deployment/keystone/changeset/update_node_capabilities.go @@ -54,6 +54,7 @@ type MutateNodeCapabilitiesRequest struct { RegistryChainSel uint64 P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability + UseMCMS bool } func (req *MutateNodeCapabilitiesRequest) Validate() error { @@ -95,6 +96,7 @@ func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e de Chain: registryChain, Registry: registry, P2pToCapabilities: req.P2pToCapabilities, + UseMCMS: req.UseMCMS, }, nil } diff --git a/deployment/keystone/changeset/update_nodes.go b/deployment/keystone/changeset/update_nodes.go index 7e436160d2e..76b095d0949 100644 --- a/deployment/keystone/changeset/update_nodes.go +++ b/deployment/keystone/changeset/update_nodes.go @@ -4,21 +4,49 @@ import ( "fmt" "github.com/smartcontractkit/chainlink/deployment" + + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) var _ deployment.ChangeSet[*UpdateNodesRequest] = UpdateNodes -type UpdateNodesRequest = internal.UpdateNodesRequest +type UpdateNodesRequest struct { + RegistryChainSel uint64 + P2pToUpdates map[p2pkey.PeerID]NodeUpdate + + UseMCMS bool +} type NodeUpdate = internal.NodeUpdate // UpdateNodes updates the a set of nodes. -// This a complex action in practice that involves registering missing capabilities, adding the nodes, and updating -// the capabilities of the DON +// The nodes and capabilities in the request must already exist in the registry contract. func UpdateNodes(env deployment.Environment, req *UpdateNodesRequest) (deployment.ChangesetOutput, error) { - _, err := internal.UpdateNodes(env.Logger, req) + // extract the registry contract and chain from the environment + registryChain, ok := env.Chains[req.RegistryChainSel] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) + } + contracts, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: env.ExistingAddresses, + }) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) + } + + resp, err := internal.UpdateNodes(env.Logger, &internal.UpdateNodesRequest{ + Chain: registryChain, + Registry: contracts.ContractSets[req.RegistryChainSel].CapabilitiesRegistry, + ContractSet: contracts.ContractSets[req.RegistryChainSel], + P2pToUpdates: req.P2pToUpdates, + UseMCMS: req.UseMCMS, + }) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to update don: %w", err) } - return deployment.ChangesetOutput{}, nil + return deployment.ChangesetOutput{ + Proposals: resp.Proposals, + }, nil } diff --git a/deployment/keystone/changeset/update_nodes_test.go b/deployment/keystone/changeset/update_nodes_test.go new file mode 100644 index 00000000000..10c08333d22 --- /dev/null +++ b/deployment/keystone/changeset/update_nodes_test.go @@ -0,0 +1,125 @@ +package changeset_test + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" +) + +func TestUpdateNodes(t *testing.T) { + t.Parallel() + + t.Run("no mcms", func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 1, + }) + + updates := make(map[p2pkey.PeerID]changeset.NodeUpdate) + i := uint8(0) + for id, _ := range te.WFNodes { + k, err := p2pkey.MakePeerID(id) + require.NoError(t, err) + pubKey := [32]byte{31: i + 1} + // don't set capabilities or nop b/c those must already exist in the contract + // those ops must be a different proposal when using MCMS + updates[k] = changeset.NodeUpdate{ + EncryptionPublicKey: hex.EncodeToString(pubKey[:]), + Signer: [32]byte{0: i + 1}, + } + i++ + } + + cfg := changeset.UpdateNodesRequest{ + RegistryChainSel: te.RegistrySelector, + P2pToUpdates: updates, + } + + csOut, err := changeset.UpdateNodes(te.Env, &cfg) + require.NoError(t, err) + require.Len(t, csOut.Proposals, 0) + require.Nil(t, csOut.AddressBook) + + validateUpdate(t, te, updates) + }) + + t.Run("with mcms", func(t *testing.T) { + te := SetupTestEnv(t, TestConfig{ + WFDonConfig: DonConfig{N: 4}, + AssetDonConfig: DonConfig{N: 4}, + WriterDonConfig: DonConfig{N: 4}, + NumChains: 1, + UseMCMS: true, + }) + + updates := make(map[p2pkey.PeerID]changeset.NodeUpdate) + i := uint8(0) + for id, _ := range te.WFNodes { + k, err := p2pkey.MakePeerID(id) + require.NoError(t, err) + pubKey := [32]byte{31: i + 1} + // don't set capabilities or nop b/c those must already exist in the contract + // those ops must be a different proposal when using MCMS + updates[k] = changeset.NodeUpdate{ + EncryptionPublicKey: hex.EncodeToString(pubKey[:]), + Signer: [32]byte{0: i + 1}, + } + i++ + } + + cfg := changeset.UpdateNodesRequest{ + RegistryChainSel: te.RegistrySelector, + P2pToUpdates: updates, + UseMCMS: true, + } + + csOut, err := changeset.UpdateNodes(te.Env, &cfg) + require.NoError(t, err) + require.Len(t, csOut.Proposals, 1) + require.Nil(t, csOut.AddressBook) + + // now apply the changeset such that the proposal is signed and execed + contracts := te.ContractSets()[te.RegistrySelector] + timelocks := map[uint64]*gethwrappers.RBACTimelock{ + te.RegistrySelector: contracts.Timelock, + } + _, err = commonchangeset.ApplyChangesets(t, te.Env, timelocks, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(changeset.UpdateNodes), + Config: &changeset.UpdateNodesRequest{ + RegistryChainSel: te.RegistrySelector, + P2pToUpdates: updates, + UseMCMS: true, + }, + }, + }) + require.NoError(t, err) + + validateUpdate(t, te, updates) + }) + +} + +// validateUpdate checks reads nodes from the registry and checks they have the expected updates +func validateUpdate(t *testing.T, te TestEnv, expected map[p2pkey.PeerID]changeset.NodeUpdate) { + registry := te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry + wfP2PIDs := p2pIDs(t, maps.Keys(te.WFNodes)) + nodes, err := registry.GetNodesByP2PIds(nil, wfP2PIDs) + require.NoError(t, err) + require.Len(t, nodes, len(wfP2PIDs)) + for _, node := range nodes { + // only check the fields that were updated + assert.Equal(t, expected[node.P2pId].EncryptionPublicKey, hex.EncodeToString(node.EncryptionPublicKey[:])) + assert.Equal(t, expected[node.P2pId].Signer, node.Signer) + } +} diff --git a/deployment/keystone/deploy.go b/deployment/keystone/deploy.go index 9bd291e9c1e..4dd8b8c495a 100644 --- a/deployment/keystone/deploy.go +++ b/deployment/keystone/deploy.go @@ -21,7 +21,6 @@ import ( "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -483,8 +482,8 @@ func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) ( for cap := range uniqueCaps { capabilities = append(capabilities, cap) } - - err = AddCapabilities(lggr, registry, registryChain, capabilities) + // not using mcms; ignore proposals + _, err = AddCapabilities(lggr, registry, registryChain, capabilities, false) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } From 45898fc6752d4aae410cb6f07f9d9817b3ab2bec Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Mon, 9 Dec 2024 13:03:15 -0800 Subject: [PATCH 52/55] feat: conditionally run unit tests (#15347) * feat: conditionally run unit tests * feat: separate action to different steps * feat: combine core unit tests * update setup env action * feat: collect coverage * chore: cleanup * chore: less run conditions, lower concurrency, proper action version * fix: dont modify ci-core.yml Did some testing trying to see if I could speed up test binary building through caching. It seems like the cache saving doesn't work when the composite action is nested. * fix: no nested composite actions --- .../actions/setup-ci-core-tests/action.yml | 61 ++++ .github/workflows/ci-core-partial.yml | 287 ++++++++++++++++++ 2 files changed, 348 insertions(+) create mode 100644 .github/actions/setup-ci-core-tests/action.yml create mode 100644 .github/workflows/ci-core-partial.yml diff --git a/.github/actions/setup-ci-core-tests/action.yml b/.github/actions/setup-ci-core-tests/action.yml new file mode 100644 index 00000000000..a2cf3f4103c --- /dev/null +++ b/.github/actions/setup-ci-core-tests/action.yml @@ -0,0 +1,61 @@ +name: Setup CI Core Tests +description: | + Shared setup steps for ci-core. + Note: Other actions should not be called from this action. There is + weird behavior when nesting reusable actions. +inputs: + + go-mod-download-directory: + description: | + The directory to run go mod download in. If not provided, it will not run go mod download. + required: false + default: "" + + db-url: + description: | + The expected database URL + required: true + +runs: + using: composite + steps: + - name: Touching core/web/assets/index.html + shell: bash + run: mkdir -p core/web/assets && touch core/web/assets/index.html + + - name: Download Go vendor packages + shell: bash + run: go mod download + + - name: Go Mod Download (optional) + if: ${{ inputs.go-mod-download-directory != '' }} + shell: bash + working-directory: ${{ inputs.go-mod-download-directory }} + run: go mod download + + - name: Build binary + shell: bash + run: go build -o chainlink.test . + + - name: Setup DB + shell: bash + run: ./chainlink.test local db preparetest + env: + CL_DATABASE_URL: ${{ inputs.db-url }} + + - name: Install LOOP Plugins + shell: bash + run: | + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds) + go install ./cmd/chainlink-feeds + popd + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-data-streams) + go install ./mercury/cmd/chainlink-mercury + popd + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana) + go install ./pkg/solana/cmd/chainlink-solana + popd + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer) + go install ./pkg/chainlink/cmd/chainlink-starknet + popd + diff --git a/.github/workflows/ci-core-partial.yml b/.github/workflows/ci-core-partial.yml new file mode 100644 index 00000000000..c9752d4e1e4 --- /dev/null +++ b/.github/workflows/ci-core-partial.yml @@ -0,0 +1,287 @@ +name: Core Unit Tests + +on: + push: + branches: + - develop + # - "release/*" + # merge_group: + pull_request: + schedule: + - cron: "0 1 * * *" + +env: + # We explicitly have this env var not be "CL_DATABASE_URL" to avoid having it be used by core related tests + # when they should not be using it, while still allowing us to DRY up the setup + DB_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable + +jobs: + filter: + name: Detect Changes + permissions: + pull-requests: read + outputs: + should-run-all-tests: ${{ steps.match-some.outputs.test-data == 'true' }} + should-collect-coverage: ${{ github.event_name == 'schedule' }} + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + with: + repository: smartcontractkit/chainlink + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: match-some + with: + # "if any changed file matches one or more of the conditions" (https://github.com/dorny/paths-filter/issues/225) + predicate-quantifier: some + # test-data - any changes to any testdata files/paths + filters: | + test-data: + - '**/testdata/**' + + run-unit-tests: + name: Tests (${{ matrix.type.test-suite }}) + needs: filter + runs-on: ubuntu22.04-32cores-128GB + permissions: + id-token: write + contents: write + strategy: + fail-fast: false + matrix: + type: + - test-suite: "core" + module-directory: "./" + build-flags: "-tags=integration" + - test-suite: "ccip-deployment" + module-directory: "./deployment" + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + with: + prod: "true" + + - name: Setup Go + uses: ./.github/actions/setup-go + with: + build-cache-version: ${{ matrix.type.test-suite }} + restore-build-cache-only: "false" + + - name: Setup Solana + uses: ./.github/actions/setup-solana + + - name: Setup wasmd + uses: ./.github/actions/setup-wasmd + + - name: Setup Postgres + uses: ./.github/actions/setup-postgres + + - name: Setup CI Core Environment + uses: ./.github/actions/setup-ci-core-tests + with: + db-url: ${{ env.DB_URL }} + go-mod-download-directory: ${{ matrix.type.test-suite == 'ccip-deployment' && matrix.type.module-directory || '' }} + + - name: Build Tests + uses: smartcontractkit/.github/apps/go-conditional-tests@37882e110590e636627a26371bdbd56ddfcce821 # go-conditional-tests@0.1.0 + timeout-minutes: 10 + with: + pipeline-step: "build" + build-concurrency: "32" + collect-coverage: ${{ needs.filter.outputs.should-collect-coverage }} + test-suite: ${{ matrix.type.test-suite }} + module-directory: ${{ matrix.type.module-directory }} + github-token: ${{ secrets.GITHUB_TOKEN }} + build-flags: ${{ matrix.type.build-flags }} + + - name: Run Tests + uses: smartcontractkit/.github/apps/go-conditional-tests@37882e110590e636627a26371bdbd56ddfcce821 # go-conditional-tests@0.1.0 + timeout-minutes: 15 + env: + CL_DATABASE_URL: ${{ env.DB_URL }} + with: + pipeline-step: "run" + run-concurrency: "16" + run-all-tests: ${{ needs.filter.outputs.should-run-all-tests }} + collect-coverage: ${{ needs.filter.outputs.should-collect-coverage }} + test-suite: ${{ matrix.type.test-suite }} + module-directory: ${{ matrix.type.module-directory }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Update Test Index + uses: smartcontractkit/.github/apps/go-conditional-tests@37882e110590e636627a26371bdbd56ddfcce821 # go-conditional-tests@0.1.0 + with: + pipeline-step: "update" + collect-coverage: ${{ needs.filter.outputs.should-collect-coverage }} + test-suite: ${{ matrix.type.test-suite }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Print postgres logs + if: ${{ always() }} + run: docker compose logs postgres | tee ../../../postgres_logs.txt + working-directory: ./.github/actions/setup-postgres + + scan: + name: SonarQube Scan + needs: [run-unit-tests, filter] + if: ${{ needs.filter.outputs.should-collect-coverage == 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + with: + # fetches all history for all tags and branches to provide more metadata for sonar reports + fetch-depth: 0 + + - name: Download all workflow run artifacts + uses: actions/download-artifact@v4.1.8 + with: + path: coverage + pattern: coverage-* + merge-multiple: true + + - name: Check and Set SonarQube Report Paths + shell: bash + run: | + ARGS="" + sonarqube_coverage_report_paths=$(find ./coverage -name '*.cover.out' | paste -sd "," -) + + # TODO uncomment when linting in enabled + # Check and assign paths for lint reports + # if [ -d "golangci-lint-report" ]; then + # sonarqube_lint_report_paths=$(find golangci-lint-report -name 'golangci-lint-report.xml' | paste -sd "," -) + # else + # sonarqube_lint_report_paths="" + # fi + # if [[ -z "$sonarqube_lint_report_paths" ]]; then + # echo "::warning::No lint report paths found, will not pass to sonarqube" + # else + # echo "Found lint report paths: $sonarqube_lint_report_paths" + # ARGS="$ARGS -Dsonar.go.golangci-lint.reportPaths=$sonarqube_lint_report_paths" + # fi + + if [[ -z "$sonarqube_coverage_report_paths" ]]; then + echo "::warning::No coverage report paths found, will not pass to sonarqube" + else + echo "Found coverage report paths: $sonarqube_coverage_report_paths" + ARGS="$ARGS -Dsonar.go.coverage.reportPaths=$sonarqube_coverage_report_paths" + fi + + echo "Final SONARQUBE_ARGS: $ARGS" + echo "SONARQUBE_ARGS=$ARGS" >> $GITHUB_ENV + + - name: SonarQube Scan + if: ${{ env.SONARQUBE_ARGS != '' }} + uses: sonarsource/sonarqube-scan-action@aecaf43ae57e412bd97d70ef9ce6076e672fe0a9 # v2.3.0 + with: + args: ${{ env.SONARQUBE_ARGS }} + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_SCANNER_OPTS: "-Xms6g -Xmx8g" + + run-fuzz-tests: + name: Tests (fuzz) + runs-on: ubuntu22.04-32cores-128GB + if: ${{ github.event_name == 'schedule' }} + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + + - name: Setup Go + uses: ./.github/actions/setup-go + with: + build-cache-version: "fuzz" + restore-build-cache-only: "true" + + - name: Setup Solana + uses: ./.github/actions/setup-solana + + - name: Setup wasmd + uses: ./.github/actions/setup-wasmd + + - name: Setup Postgres + uses: ./.github/actions/setup-postgres + + - name: Setup CI Core Environment + uses: ./.github/actions/setup-ci-core-tests + with: + db-url: ${{ env.DB_URL }} + + - name: Increase Timeouts + if: ${{ github.event_name == 'schedule'}} + run: | + echo "FUZZ_TIMEOUT_MINUTES=10">> $GITHUB_ENV + + - name: Run Fuzz Tests + env: + OUTPUT_FILE: ./output.txt + CL_DATABASE_URL: ${{ env.DB_URL }} + run: ./tools/bin/go_core_fuzz ./... + + - name: Print postgres logs + if: ${{ always() }} + run: docker compose logs postgres | tee ../../../postgres_logs.txt + working-directory: ./.github/actions/setup-postgres + + run-race-tests: + name: Tests (race) + runs-on: ubuntu22.04-32cores-128GB + if: ${{ github.event_name == 'schedule' }} + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + + - name: Setup Go + uses: ./.github/actions/setup-go + with: + build-cache-version: "race" + restore-build-cache-only: "true" + + - name: Setup Solana + uses: ./.github/actions/setup-solana + + - name: Setup wasmd + uses: ./.github/actions/setup-wasmd + + - name: Setup Postgres + uses: ./.github/actions/setup-postgres + + - name: Setup CI Core Environment + uses: ./.github/actions/setup-ci-core-tests + with: + db-url: ${{ env.DB_URL }} + + - name: Increase Timeouts + if: ${{ github.event_name == 'schedule'}} + run: | + echo "TIMEOUT=10m" >> $GITHUB_ENV + echo "COUNT=50" >> $GITHUB_ENV + + - name: Run Race Tests + env: + OUTPUT_FILE: ./output.txt + CL_DATABASE_URL: ${{ env.DB_URL }} + run: ./tools/bin/go_core_race_tests ./... + + - name: Print Races + id: print-races + if: ${{ failure() }} + run: | + find race.* | xargs cat > race.txt + if [[ -s race.txt ]]; then + cat race.txt + echo "post_to_slack=true" >> $GITHUB_OUTPUT + else + echo "post_to_slack=false" >> $GITHUB_OUTPUT + fi + echo "github.event_name: ${{ github.event_name }}" + echo "github.ref: ${{ github.ref }}" + + - name: Print postgres logs + if: ${{ always() }} + run: docker compose logs postgres | tee ../../../postgres_logs.txt + working-directory: ./.github/actions/setup-postgres From aae1def589edf40effb808bf5d29ba792c99d3a4 Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Mon, 9 Dec 2024 22:53:43 -0800 Subject: [PATCH 53/55] remove deployCCIPContracts (#15586) --- .../ccip/changeset/cs_add_chain_test.go | 15 ++++++++- deployment/ccip/changeset/cs_deploy_chain.go | 32 ------------------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/deployment/ccip/changeset/cs_add_chain_test.go b/deployment/ccip/changeset/cs_add_chain_test.go index c8d872236c2..2873b3bf613 100644 --- a/deployment/ccip/changeset/cs_add_chain_test.go +++ b/deployment/ccip/changeset/cs_add_chain_test.go @@ -80,10 +80,23 @@ func TestAddChainInbound(t *testing.T) { for _, chain := range initialDeploy { chainConfig[chain] = DefaultOCRParams(e.FeedChainSel, nil, nil) } - err = deployCCIPContracts(e.Env, newAddresses, NewChainsConfig{ + newChainCfg := NewChainsConfig{ HomeChainSel: e.HomeChainSel, FeedChainSel: e.FeedChainSel, ChainConfigByChain: chainConfig, + } + e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ + { + Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), + Config: DeployChainContractsConfig{ + ChainSelectors: newChainCfg.Chains(), + HomeChainSelector: newChainCfg.HomeChainSel, + }, + }, + { + Changeset: commonchangeset.WrapChangeSet(ConfigureNewChains), + Config: newChainCfg, + }, }) require.NoError(t, err) diff --git a/deployment/ccip/changeset/cs_deploy_chain.go b/deployment/ccip/changeset/cs_deploy_chain.go index e2762b27578..de6e4b5f466 100644 --- a/deployment/ccip/changeset/cs_deploy_chain.go +++ b/deployment/ccip/changeset/cs_deploy_chain.go @@ -65,38 +65,6 @@ func (c DeployChainContractsConfig) Validate() error { return nil } -// deployCCIPContracts assumes the following contracts are deployed: -// - Capability registry -// - CCIP home -// - RMN home -// - Fee tokens on all chains. -// and present in ExistingAddressBook. -// It then deploys the rest of the CCIP chain contracts to the selected chains -// registers the nodes with the capability registry and creates a DON for -// each new chain. -func deployCCIPContracts( - e deployment.Environment, - ab deployment.AddressBook, - c NewChainsConfig) error { - err := deployChainContractsForChains(e, ab, c.HomeChainSel, c.Chains()) - if err != nil { - e.Logger.Errorw("Failed to deploy chain contracts", "err", err) - return err - } - err = e.ExistingAddresses.Merge(ab) - if err != nil { - e.Logger.Errorw("Failed to merge address book", "err", err) - return err - } - err = configureChain(e, c) - if err != nil { - e.Logger.Errorw("Failed to add chain", "err", err) - return err - } - - return nil -} - func deployChainContractsForChains( e deployment.Environment, ab deployment.AddressBook, From 99b666fbcbccb926e6dbac11896bf7e7ee5c25ea Mon Sep 17 00:00:00 2001 From: Graham Goh Date: Tue, 10 Dec 2024 18:53:50 +1100 Subject: [PATCH 54/55] fix(operator-ui): fix duplicate chain id in chain config dialog (#15585) There was an issue raised [here](https://chainlink-core.slack.com/archives/C06NF17JK9N/p1733437678773739?thread_ts=1733412322.287769&cid=C06NF17JK9N) impacting the chain config dialog of the operator ui, because the chain id is no longer unique now that we work with multichain, we need to handle it better by considering the network and chain id together instead of just chainid. Context: https://github.com/smartcontractkit/operator-ui/pull/97 JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1384 --- .changeset/six-coins-mix.md | 5 +++++ core/web/assets/index.html | 2 +- core/web/assets/index.html.gz | Bin 419 -> 420 bytes ...c1e482.js => main.008c37495ba29761321d.js} | 2 +- ....js.gz => main.008c37495ba29761321d.js.gz} | Bin 1198074 -> 1198171 bytes operator_ui/TAG | 2 +- 6 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/six-coins-mix.md rename core/web/assets/{main.ec7b7e88c8c965c1e482.js => main.008c37495ba29761321d.js} (90%) rename core/web/assets/{main.ec7b7e88c8c965c1e482.js.gz => main.008c37495ba29761321d.js.gz} (92%) diff --git a/.changeset/six-coins-mix.md b/.changeset/six-coins-mix.md new file mode 100644 index 00000000000..2877aa3012a --- /dev/null +++ b/.changeset/six-coins-mix.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix fix: duplicate chain id in chain config dialog diff --git a/core/web/assets/index.html b/core/web/assets/index.html index 6e2fd9cf254..ae1aac9ede0 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 9d9d6b9151f5f943cc67dbc3175f825a8407d3ef..a65173c97c81ceb7da51eee8443c4d0395a6644d 100644 GIT binary patch literal 420 zcmV;V0bBkbiwFP!000021C^3bYa1~T#lMOw=&A8)Z70niq|G5vNTC#(=FsC{g|oXF$i@VKB%LJ$|#LqxZn8A1}V`#NF);i8@&tvO0I zQvRh1MyKn*Mf^?_dCpo51$(Clk+I$xQxg=KO$&HwC~fJr$tcDTKzU{~phNJxp`;Jfi+&8)#A#oG#2V`vjUgYmRtx OSk>QPQcP380ssJ`k;5qf literal 419 zcmV;U0bKqciwFP!000021C^3NYuqpph5w2w=&8GwlO~NDBi&mbKU=pXFsguEVIFZNg^4L%!Aqd;zA)vdM8A1}U{W@X>;jEq>tXU-+ zDE(3ygVSZ;EdC&hJSVM&jJ?x?$XITTDG{>FrWw3c6!-K}B^2Wapfoco@_YveVdpuH z8B2M4dEax6AaetY&7a7glay-DyblN?mCAE8zLdKjB88*-#yb|ieP7p`tGeD?*R?)1 zD#w6jK>RQAJk=}u3kYU{@b1BLD*wWo9;Uf^9#Q`_tNBBnrU-j9FWW^shkpN>&^hwr zGmWA;>@hpNTw0avoi8t*h6x^5TVa(CNy$J(!8lgdoC|G7lcLV)%q+7{M^kIfiZ{!u N{swyIDQUn0007U@#6AE3 diff --git a/core/web/assets/main.ec7b7e88c8c965c1e482.js b/core/web/assets/main.008c37495ba29761321d.js similarity index 90% rename from core/web/assets/main.ec7b7e88c8c965c1e482.js rename to core/web/assets/main.008c37495ba29761321d.js index 5640ce7c29e..b9feeec3d83 100644 --- a/core/web/assets/main.ec7b7e88c8c965c1e482.js +++ b/core/web/assets/main.008c37495ba29761321d.js @@ -171,4 +171,4 @@ object-assign */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},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;nAp});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)))};function xc(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xl(){var e=xc(["\n fragment FetchFeedsManagersPayload_ResultsFields on FeedsManager {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n disabledAt\n }\n query FetchFeedsManagers {\n feedsManagers {\n results {\n ...FetchFeedsManagersPayload_ResultsFields\n }\n }\n }\n"]);return xl=function(){return e},e}var xf=n0(xl()),xd=function(e){return rv(xf,e)},xh=n(47559),xp=n(83165),xb=n(47298),xm=n(81395),xg=function(){return(0,b.createStyles)({root:{display:"flex"},activeIcon:{color:xh.default[500]},inactiveIcon:{color:xp.default[500]},text:{marginLeft:4}})},xv=(0,b.withStyles)(xg)(function(e){var t=e.isActive,n=e.activeText,r=e.inactiveText,i=e.classes;return l.createElement("div",{className:i.root},t?l.createElement(xm.Z,{fontSize:"small",className:i.activeIcon}):l.createElement(xb.Z,{fontSize:"small",className:i.inactiveIcon}),l.createElement(x.default,{variant:"body1",inline:!0,className:i.text},t?n:r))}),xy=(0,b.withStyles)(iu)(function(e){var t=e.jobDistributor,n=e.classes;return l.createElement(ir.Z,{className:n.row,hover:!0},l.createElement(r7.default,{className:n.cell,component:"th",scope:"row"},l.createElement(ih,{className:n.link,href:"/job_distributors/".concat(t.id)},t.name)),l.createElement(r7.default,null,l.createElement(xv,{isActive:t.isConnectionActive,activeText:"Connected",inactiveText:"Disconnected"})),l.createElement(r7.default,null,l.createElement(xv,{isActive:!t.disabledAt,activeText:"Enabled",inactiveText:"Disabled"})),l.createElement(r7.default,null,_T(t.publicKey,{start:6,end:6}),l.createElement(_x,{data:t.publicKey})),l.createElement(r7.default,null,t.uri))}),xw=function(e){var t=e.jobDistributors;return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Distributors")),l.createElement(d.Z,{item:!0,xs:3},l.createElement(d.Z,{container:!0,justify:"flex-end"},l.createElement(d.Z,{item:!0},l.createElement(aA.Z,{variant:"secondary",component:tz,href:"/job_distributors/new"},"New Job Distributor")))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Name"),l.createElement(r7.default,null,"Connection Status"),l.createElement(r7.default,null,"Status"),l.createElement(r7.default,null,"CSA Public Key"),l.createElement(r7.default,null,"RPC URL"))),l.createElement(r9.Z,null,0===t.length&&l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},"Job Distributors have not been registered")),t.map(function(e){return l.createElement(xy,{key:e.id,jobDistributor:e})})))))))},x_=function(){var e,t=xd({fetchPolicy:"cache-and-network"}),n=t.data,r=t.loading,i=t.error;return r?l.createElement(iR,null):i?l.createElement(iD,{error:i}):l.createElement(xw,{jobDistributors:null!==(e=null==n?void 0:n.feedsManagers.results)&&void 0!==e?e:[]})},xE=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xS=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xE,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 Job Distributor 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 Job Distributor 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"))))})},xk=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 Job Distributor"}),l.createElement(aW.Z,null,l.createElement(xS,{initialValues:r,onSubmit:n})))))};function xx(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(xZ,e)},xJ=function(){return(0,b.createStyles)({root:{fontSize:24}})},xQ=(0,b.withStyles)(xJ)(function(e){var t=e.children,n=e.classes;return l.createElement(x.default,{variant:"h2",className:n.root},t)}),x1=n(9290),x0=n(74923);function x2(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);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function TT(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 TM(e,t){return Tv(e)||TE(e,t)||TA(e,t)||TS()}function TO(e){return Ty(e)||T_(e)||TA(e)||Tk()}function TA(e,t){if(e){if("string"==typeof e)return Tg(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 Tg(e,t)}}var TL=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},TC=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0(),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()}),TI=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},TD=function(e){var t=e.addresses,n=Tx(e,["addresses"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=TM(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,!TL(a)&&l.createElement(hP,Tw({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)})),TL(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}),TL(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"}})))},TN=(0,b.withStyles)(TI)(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.chains,u=void 0===s?[]:s,c=e.accountsEVM,f=void 0===c?[]:c,h=e.accountsNonEvm,p=e.p2pKeys,b=void 0===p?[]:p,m=e.ocrKeys,g=void 0===m?[]:m,v=e.ocr2Keys,y=void 0===v?[]:v,w=e.showSubmit,_=void 0!==w&&w,E=TO(y).sort(function(e,t){var n,r,i;return e.chainType===t.chainType?e.id.localeCompare(t.id):null!==(i=null===(n=e.chainType)||void 0===n?void 0:n.localeCompare(null!==(r=t.chainType)&&void 0!==r?r:""))&&void 0!==i?i:0});return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:TC,onSubmit:o},function(e){var n,i,a=e.values,o=[];switch(a.chainType){case Tm.EVM:o=f.filter(function(e){return e.chain.id==a.chainID&&!e.isDisabled}).map(function(e){return e.address});break;case Tm.APTOS:o=null!==(n=null==h?void 0:h.aptosKeys.results.map(function(e){return e.account}))&&void 0!==n?n:[];break;case Tm.SOLANA:o=null!==(i=null==h?void 0:h.solanaKeys.results.map(function(e){return e.id}))&&void 0!==i?i:[];break;default:o=[]}var s=u.filter(function(e){return e.network.toUpperCase()===a.chainType});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:r},l.createElement(tE.default,{key:Tm.EVM,value:Tm.EVM},"EVM"),l.createElement(tE.default,{key:Tm.APTOS,value:Tm.APTOS},"APTOS"),l.createElement(tE.default,{key:Tm.SOLANA,value:Tm.SOLANA},"SOLANA"))),l.createElement(d.Z,{item:!0,xs:12,md:6},s.length>0&&!r?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"}},s.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})):l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,disabled:r,inputProps:{"data-testid":"chainID-manual-input"},FormHelperTextProps:{"data-testid":"chainID-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},o.length>0?l.createElement(TD,{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",addresses:o,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}}):l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-manual-input"},required:!0,fullWidth:!0,helperText:"The account address used for this chain",FormHelperTextProps:{"data-testid":"accountAddr-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",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"}}),a.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?"}})),a.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"}},b.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"}},g.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"}}),a.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?"}})),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:!a.ocr2IsBootstrap,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),a.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:"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"}},E.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id," (",e.chainType,")")}))),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"}}))))))),_&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})});function TP(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function TR(){var e=TP(["\n fragment AptosKeysPayload_ResultsFields on AptosKey {\n account\n id\n }\n"]);return TR=function(){return e},e}function Tj(){var e=TP(["\n fragment SolanaKeysPayload_ResultsFields on SolanaKey {\n id\n }\n"]);return Tj=function(){return e},e}function TF(){var e=TP(["\n ","\n ","\n query FetchNonEvmKeys {\n aptosKeys {\n results {\n ...AptosKeysPayload_ResultsFields\n }\n }\n solanaKeys {\n results {\n ...SolanaKeysPayload_ResultsFields\n }\n }\n }\n"]);return TF=function(){return e},e}var TY=n0(TR()),TB=n0(Tj()),TU=n0(TF(),TY,TB),TH=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(TU,e)},T$=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=TH({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,d={chainID:"",chainType:Tm.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:""},h=a?a.chains.results:[],p=o?o.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.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(TN,{innerRef:i,initialValues:d,onSubmit:r,chains:h,accountsEVM:p,accountsNonEvm:s,p2pKeys:b,ocrKeys:m,ocr2Keys:g})),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")))},Tz=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=TH({fetchPolicy:"cache-and-network"}).data,c=SV({fetchPolicy:"cache-and-network"}).data,f=EO({fetchPolicy:"cache-and-network"}).data,d=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var h={chainID:t.chainID,chainType:t.chainType,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},p=o?o.chains.results:[],b=s?s.ethKeys.results:[],m=c?c.p2pKeys.results:[],g=f?f.ocrKeyBundles.results:[],v=d?d.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(TN,{innerRef:a,initialValues:h,onSubmit:i,chains:p,accountsEVM:b,accountsNonEvm:u,p2pKeys:m,ocrKeys:g,ocr2Keys:v,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 TG(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&&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 M1(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?M6[c.action].title:"",body:c?M6[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(Mz,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function M8(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function M9(){var e=M8(["\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 M9=function(){return e},e}var M7=n0(M9(),M3),Oe=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(MF,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(xQ,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(M5,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Ot(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.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","DuplicateFeedsManagerError","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"],DisableFeedsManagerPayload:["DisableFeedsManagerSuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],EnableFeedsManagerPayload:["EnableFeedsManagerSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DuplicateFeedsManagerError","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","StreamSpec","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)))};function xc(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xl(){var e=xc(["\n fragment FetchFeedsManagersPayload_ResultsFields on FeedsManager {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n disabledAt\n }\n query FetchFeedsManagers {\n feedsManagers {\n results {\n ...FetchFeedsManagersPayload_ResultsFields\n }\n }\n }\n"]);return xl=function(){return e},e}var xf=n0(xl()),xd=function(e){return rv(xf,e)},xh=n(47559),xp=n(83165),xb=n(47298),xm=n(81395),xg=function(){return(0,b.createStyles)({root:{display:"flex"},activeIcon:{color:xh.default[500]},inactiveIcon:{color:xp.default[500]},text:{marginLeft:4}})},xv=(0,b.withStyles)(xg)(function(e){var t=e.isActive,n=e.activeText,r=e.inactiveText,i=e.classes;return l.createElement("div",{className:i.root},t?l.createElement(xm.Z,{fontSize:"small",className:i.activeIcon}):l.createElement(xb.Z,{fontSize:"small",className:i.inactiveIcon}),l.createElement(x.default,{variant:"body1",inline:!0,className:i.text},t?n:r))}),xy=(0,b.withStyles)(iu)(function(e){var t=e.jobDistributor,n=e.classes;return l.createElement(ir.Z,{className:n.row,hover:!0},l.createElement(r7.default,{className:n.cell,component:"th",scope:"row"},l.createElement(ih,{className:n.link,href:"/job_distributors/".concat(t.id)},t.name)),l.createElement(r7.default,null,l.createElement(xv,{isActive:t.isConnectionActive,activeText:"Connected",inactiveText:"Disconnected"})),l.createElement(r7.default,null,l.createElement(xv,{isActive:!t.disabledAt,activeText:"Enabled",inactiveText:"Disabled"})),l.createElement(r7.default,null,_T(t.publicKey,{start:6,end:6}),l.createElement(_x,{data:t.publicKey})),l.createElement(r7.default,null,t.uri))}),xw=function(e){var t=e.jobDistributors;return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Distributors")),l.createElement(d.Z,{item:!0,xs:3},l.createElement(d.Z,{container:!0,justify:"flex-end"},l.createElement(d.Z,{item:!0},l.createElement(aA.Z,{variant:"secondary",component:tz,href:"/job_distributors/new"},"New Job Distributor")))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Name"),l.createElement(r7.default,null,"Connection Status"),l.createElement(r7.default,null,"Status"),l.createElement(r7.default,null,"CSA Public Key"),l.createElement(r7.default,null,"RPC URL"))),l.createElement(r9.Z,null,0===t.length&&l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},"Job Distributors have not been registered")),t.map(function(e){return l.createElement(xy,{key:e.id,jobDistributor:e})})))))))},x_=function(){var e,t=xd({fetchPolicy:"cache-and-network"}),n=t.data,r=t.loading,i=t.error;return r?l.createElement(iR,null):i?l.createElement(iD,{error:i}):l.createElement(xw,{jobDistributors:null!==(e=null==n?void 0:n.feedsManagers.results)&&void 0!==e?e:[]})},xE=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xS=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xE,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 Job Distributor 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 Job Distributor 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"))))})},xk=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 Job Distributor"}),l.createElement(aW.Z,null,l.createElement(xS,{initialValues:r,onSubmit:n})))))};function xx(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(xZ,e)},xJ=function(){return(0,b.createStyles)({root:{fontSize:24}})},xQ=(0,b.withStyles)(xJ)(function(e){var t=e.children,n=e.classes;return l.createElement(x.default,{variant:"h2",className:n.root},t)}),x1=n(9290),x0=n(74923);function x2(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);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function TT(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 TM(e,t){return Tv(e)||TE(e,t)||TA(e,t)||TS()}function TO(e){return Ty(e)||T_(e)||TA(e)||Tk()}function TA(e,t){if(e){if("string"==typeof e)return Tg(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 Tg(e,t)}}var TL=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},TC=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0(),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()}),TI=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},TD=function(e){var t=e.addresses,n=Tx(e,["addresses"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=TM(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,!TL(a)&&l.createElement(hP,Tw({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)})),TL(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}),TL(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"}})))},TN=(0,b.withStyles)(TI)(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.chains,u=void 0===s?[]:s,c=e.accountsEVM,f=void 0===c?[]:c,h=e.accountsNonEvm,p=e.p2pKeys,b=void 0===p?[]:p,m=e.ocrKeys,g=void 0===m?[]:m,v=e.ocr2Keys,y=void 0===v?[]:v,w=e.showSubmit,_=void 0!==w&&w,E=TO(y).sort(function(e,t){var n,r,i;return e.chainType===t.chainType?e.id.localeCompare(t.id):null!==(i=null===(n=e.chainType)||void 0===n?void 0:n.localeCompare(null!==(r=t.chainType)&&void 0!==r?r:""))&&void 0!==i?i:0});return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:TC,onSubmit:o},function(e){var n,i,a=e.values,o=[];switch(a.chainType){case Tm.EVM:o=f.filter(function(e){return e.chain.id==a.chainID&&!e.isDisabled}).map(function(e){return e.address});break;case Tm.APTOS:o=null!==(n=null==h?void 0:h.aptosKeys.results.map(function(e){return e.account}))&&void 0!==n?n:[];break;case Tm.SOLANA:o=null!==(i=null==h?void 0:h.solanaKeys.results.map(function(e){return e.id}))&&void 0!==i?i:[];break;default:o=[]}var s=u.filter(function(e){return e.network.toUpperCase()===a.chainType});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:r},l.createElement(tE.default,{key:Tm.EVM,value:Tm.EVM},"EVM"),l.createElement(tE.default,{key:Tm.APTOS,value:Tm.APTOS},"APTOS"),l.createElement(tE.default,{key:Tm.SOLANA,value:Tm.SOLANA},"SOLANA"))),l.createElement(d.Z,{item:!0,xs:12,md:6},s.length>0&&!r?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"}},s.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})):l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,disabled:r,inputProps:{"data-testid":"chainID-manual-input"},FormHelperTextProps:{"data-testid":"chainID-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},o.length>0?l.createElement(TD,{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",addresses:o,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}}):l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-manual-input"},required:!0,fullWidth:!0,helperText:"The account address used for this chain",FormHelperTextProps:{"data-testid":"accountAddr-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",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"}}),a.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?"}})),a.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"}},b.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"}},g.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"}}),a.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?"}})),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:!a.ocr2IsBootstrap,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),a.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:"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"}},E.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id," (",e.chainType,")")}))),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"}}))))))),_&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})});function TP(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function TR(){var e=TP(["\n fragment AptosKeysPayload_ResultsFields on AptosKey {\n account\n id\n }\n"]);return TR=function(){return e},e}function Tj(){var e=TP(["\n fragment SolanaKeysPayload_ResultsFields on SolanaKey {\n id\n }\n"]);return Tj=function(){return e},e}function TF(){var e=TP(["\n ","\n ","\n query FetchNonEvmKeys {\n aptosKeys {\n results {\n ...AptosKeysPayload_ResultsFields\n }\n }\n solanaKeys {\n results {\n ...SolanaKeysPayload_ResultsFields\n }\n }\n }\n"]);return TF=function(){return e},e}var TY=n0(TR()),TB=n0(Tj()),TU=n0(TF(),TY,TB),TH=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(TU,e)},T$=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=TH({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,d={chainID:"",chainType:Tm.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:""},h=a?a.chains.results:[],p=o?o.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.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(TN,{innerRef:i,initialValues:d,onSubmit:r,chains:h,accountsEVM:p,accountsNonEvm:s,p2pKeys:b,ocrKeys:m,ocr2Keys:g})),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")))},Tz=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=TH({fetchPolicy:"cache-and-network"}).data,c=SV({fetchPolicy:"cache-and-network"}).data,f=EO({fetchPolicy:"cache-and-network"}).data,d=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var h={chainID:t.chainID,chainType:t.chainType,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},p=o?o.chains.results:[],b=s?s.ethKeys.results:[],m=c?c.p2pKeys.results:[],g=f?f.ocrKeyBundles.results:[],v=d?d.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(TN,{innerRef:a,initialValues:h,onSubmit:i,chains:p,accountsEVM:b,accountsNonEvm:u,p2pKeys:m,ocrKeys:g,ocr2Keys:v,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 TG(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&&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 M1(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?M6[c.action].title:"",body:c?M6[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(Mz,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function M8(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function M9(){var e=M8(["\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 M9=function(){return e},e}var M7=n0(M9(),M3),Oe=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(MF,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(xQ,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(M5,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Ot(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.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","DuplicateFeedsManagerError","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"],DisableFeedsManagerPayload:["DisableFeedsManagerSuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],EnableFeedsManagerPayload:["EnableFeedsManagerSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DuplicateFeedsManagerError","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","StreamSpec","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,dataIdFromObject:function(e){if("Chain"===e.__typename){if(!e.network)throw Error("Due to Chain ID not being unique across chain, ensure network is fetched too");return"Chain:".concat(e.network,":").concat(e.id)}return id(e)}}),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.ec7b7e88c8c965c1e482.js.gz b/core/web/assets/main.008c37495ba29761321d.js.gz similarity index 92% rename from core/web/assets/main.ec7b7e88c8c965c1e482.js.gz rename to core/web/assets/main.008c37495ba29761321d.js.gz index 446f5f6ece1086536d9f91b9e5ce2fe96aeba416..c5cb981d0055351233b5b95ad14604dc0c02467b 100644 GIT binary patch delta 97083 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 Date: Tue, 10 Dec 2024 05:16:35 -0500 Subject: [PATCH 55/55] CCIP-4329 modify setChainRateLimiterConfig file for setting multiple rate limits (#15386) * modify setChainRateLimiterConfig file for setting multiple rate limits * Update gethwrappers * [Bot] Update changeset file with jira issues * snapshot fix * fix wrappers after merge * fix test that was broken in merge * fix liquidityManager snapshot which is affected by token pool changes * fix broken integration tests from removing critical setup function * add array length check for setChainRateLimitConfigs * formatting and snapshot fix * Update gethwrappers * simplify test setups * Update gethwrappers * update wrappers and snapshots which were broken in merge * Update gethwrappers * update wrappers and snapshot * changeset * snapshot update * Delete contracts/.changeset/orange-buckets-live.md * attempt fix changeset * attempt changeset fix with update pnpm package * re-add function that was removed early in PR to prevent any required tooling changes * update liquidityManager snapshot because of changes to token pools --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/.changeset/small-countries-flow.md | 5 + contracts/gas-snapshots/ccip.gas-snapshot | 127 ++++++++--------- .../liquiditymanager.gas-snapshot | 8 +- contracts/src/v0.8/ccip/pools/TokenPool.sol | 20 +++ ...TokenPool.setChainRateLimiterConfigs.t.sol | 128 ++++++++++++++++++ .../burn_from_mint_token_pool.go | 18 ++- .../burn_mint_token_pool.go | 18 ++- .../burn_with_from_mint_token_pool.go | 18 ++- .../lock_release_token_pool.go | 18 ++- .../ccip/generated/token_pool/token_pool.go | 16 ++- .../usdc_token_pool/usdc_token_pool.go | 18 ++- ...rapper-dependency-versions-do-not-edit.txt | 12 +- .../ccip-tests/contracts/contract_models.go | 7 +- 13 files changed, 329 insertions(+), 84 deletions(-) create mode 100644 contracts/.changeset/small-countries-flow.md create mode 100644 contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol diff --git a/contracts/.changeset/small-countries-flow.md b/contracts/.changeset/small-countries-flow.md new file mode 100644 index 00000000000..953102874bc --- /dev/null +++ b/contracts/.changeset/small-countries-flow.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +Modify TokenPool.sol function setChainRateLimiterConfig to now accept an array of configs and set sequentially. Requested by front-end. PR issue CCIP-4329 #bugfix diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 955000e016f..4ed7d38afd6 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -68,7 +68,7 @@ CCIPHome_setCandidate:test_setCandidate_success() (gas: 1365439) CCIPHome_supportsInterface:test_supportsInterface_success() (gas: 9885) DefensiveExampleTest:test_HappyPath_Success() (gas: 200540) DefensiveExampleTest:test_Recovery() (gas: 425013) -E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512127) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512391) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96980) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49812) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17479) @@ -226,29 +226,29 @@ FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() ( FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10906) FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6841) FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6567) -HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 176837) -HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity_Success() (gas: 166986) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism_Success() (gas: 135860) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_WhileMigrationPause_Revert() (gas: 109696) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_Success() (gas: 146915) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209124) +HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 176859) +HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity_Success() (gas: 167004) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism_Success() (gas: 135878) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_WhileMigrationPause_Revert() (gas: 109718) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_Success() (gas: 146937) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209160) HybridLockReleaseUSDCTokenPool_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 213127) HybridLockReleaseUSDCTokenPool_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 109646) HybridLockReleaseUSDCTokenPool_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 265910) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3099863) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3209936) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29734) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 80625) LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59227) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3096192) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3206264) LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11511) LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 74100) LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 54745) LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 223256) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10936) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18115) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11003) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18182) LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10250) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83283) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 56056) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83328) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 56101) LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60188) LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5456) @@ -386,7 +386,7 @@ OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276839) OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168529) OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188173) OffRamp_batchExecute:test_SingleReport_Success() (gas: 156527) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545255) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 545431) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10643) OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92450) OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63117) @@ -429,12 +429,12 @@ OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6933352) OffRamp_execute:test_ZeroReports_Revert() (gas: 17248) OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 56213) OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20508) -OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 238042) +OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 238130) OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 91994) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 268135) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 268223) OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28659) OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 15530) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 474650) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 474738) OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48296) OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34101) OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28824) @@ -447,15 +447,15 @@ OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212456) OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 243699) OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141510) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 402534) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 402622) OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58242) OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73812) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 574160) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 522711) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 574336) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 522887) OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 26795) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 540787) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 540734) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 451824) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 540963) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 540910) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 452000) OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135231) OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164892) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3905742) @@ -482,20 +482,20 @@ OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36790) OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91430) OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 83518) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 168784) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 168872) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenInvalidDataLengthReturnData() (gas: 62822) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_RevertWhenPoolDoesNotSupportDest() (gas: 78426) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 170654) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 181893) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 170742) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 181981) OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11465) OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13975) OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 47491) OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 25464) -OffRamp_trialExecute:test_trialExecute() (gas: 271771) -OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 127457) -OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 138767) -OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 289412) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 251706) +OffRamp_trialExecute:test_trialExecute() (gas: 271859) +OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 127545) +OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 138855) +OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 289500) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 251641) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17227) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Revert() (gas: 67101) OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Success() (gas: 325983) @@ -525,7 +525,7 @@ OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 213144) OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147070) OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161303) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3963792) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 4073863) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24015) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75854) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38588) @@ -671,14 +671,14 @@ TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 3 TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18202) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49592) TokenPoolFactory_constructor:test_constructor_Revert() (gas: 1121653) -TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict_Success() (gas: 12386310) -TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool_Success() (gas: 6364709) -TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() (gas: 13167390) -TokenPoolFactory_createTokenPool:test_createTokenPool_RemoteTokenHasDifferentDecimals_Success() (gas: 13174692) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() (gas: 13504109) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() (gas: 6150583) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool_Success() (gas: 6361166) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2717776) +TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict_Success() (gas: 12612969) +TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool_Success() (gas: 6513874) +TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() (gas: 13434268) +TokenPoolFactory_createTokenPool:test_createTokenPool_RemoteTokenHasDifferentDecimals_Success() (gas: 13441570) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() (gas: 13771048) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() (gas: 6301066) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool_Success() (gas: 6510314) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2827849) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12119) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23567) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 178398) @@ -699,7 +699,7 @@ TokenPool_applyChainUpdates:test_applyChainUpdates_UpdatesRemotePoolHashes() (ga TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 226472) TokenPool_calculateLocalAmount:test_calculateLocalAmount() (gas: 93680) TokenPool_constructor:test_constructor() (gas: 21930) -TokenPool_constructor:test_constructor_DecimalCallFails() (gas: 2714089) +TokenPool_constructor:test_constructor_DecimalCallFails() (gas: 2824157) TokenPool_getRemotePool:test_getRemotePools() (gas: 330500) TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21504) TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 240435) @@ -714,44 +714,47 @@ TokenPool_removeRemotePool:test_NonExistentChain_Revert() (gas: 14344) TokenPool_removeRemotePool:test_removeRemotePool_Success() (gas: 188387) TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17214) TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15307) +TokenPool_setChainRateLimiterConfigs:test_MismatchedArrayLengths_Revert() (gas: 23960) +TokenPool_setChainRateLimiterConfigs:test_NonExistentChain_Revert() (gas: 19424) +TokenPool_setChainRateLimiterConfigs:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 16511) TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11002) TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 37606) -USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism_Success() (gas: 135869) -USDCBridgeMigrator_BurnLockedUSDC:test_WhileMigrationPause_Revert() (gas: 109729) +USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism_Success() (gas: 135887) +USDCBridgeMigrator_BurnLockedUSDC:test_WhileMigrationPause_Revert() (gas: 109751) USDCBridgeMigrator_BurnLockedUSDC:test_invalidPermissions_Revert() (gas: 39493) -USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309798) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_Success() (gas: 146939) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209089) +USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309833) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_Success() (gas: 146961) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209124) USDCBridgeMigrator_cancelMigrationProposal:test_cancelExistingCCTPMigrationProposal_Success() (gas: 56155) USDCBridgeMigrator_cancelMigrationProposal:test_cannotCancelANonExistentMigrationProposal_Revert() (gas: 12669) USDCBridgeMigrator_excludeTokensFromBurn:test_excludeTokensWhenNoMigrationProposalPending_Revert() (gas: 13579) USDCBridgeMigrator_proposeMigration:test_ChainNotUsingLockRelease_Revert() (gas: 15765) -USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism_Success() (gas: 135986) -USDCBridgeMigrator_provideLiquidity:test_WhileMigrationPause_Revert() (gas: 109871) +USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism_Success() (gas: 136004) +USDCBridgeMigrator_provideLiquidity:test_WhileMigrationPause_Revert() (gas: 109893) USDCBridgeMigrator_provideLiquidity:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13390) USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() (gas: 67428) -USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidity_AfterMigration_Revert() (gas: 313898) +USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidity_AfterMigration_Revert() (gas: 313933) USDCBridgeMigrator_provideLiquidity:test_invalidPermissions_Revert() (gas: 39493) -USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310057) -USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_Success() (gas: 147080) -USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209395) +USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310092) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_Success() (gas: 147102) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209430) USDCBridgeMigrator_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 213160) USDCBridgeMigrator_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 109679) USDCBridgeMigrator_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 265963) USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_destChain_Success() (gas: 150538) USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 511783) -USDCBridgeMigrator_updateChainSelectorMechanism:test_PrimaryMechanism_Success() (gas: 136004) -USDCBridgeMigrator_updateChainSelectorMechanism:test_WhileMigrationPause_Revert() (gas: 109849) -USDCBridgeMigrator_updateChainSelectorMechanism:test_cannotRevertChainMechanism_afterMigration_Revert() (gas: 313496) +USDCBridgeMigrator_updateChainSelectorMechanism:test_PrimaryMechanism_Success() (gas: 136021) +USDCBridgeMigrator_updateChainSelectorMechanism:test_WhileMigrationPause_Revert() (gas: 109871) +USDCBridgeMigrator_updateChainSelectorMechanism:test_cannotRevertChainMechanism_afterMigration_Revert() (gas: 313532) USDCBridgeMigrator_updateChainSelectorMechanism:test_invalidPermissions_Revert() (gas: 39471) -USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310057) -USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_Success() (gas: 147035) -USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209448) +USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 310092) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_Success() (gas: 147057) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209483) USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 26049) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35297) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29875) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133408) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 433408) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35319) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29897) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133426) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 433430) USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 265695) USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 47231) USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 95262) diff --git a/contracts/gas-snapshots/liquiditymanager.gas-snapshot b/contracts/gas-snapshots/liquiditymanager.gas-snapshot index 2e2d0962186..bc545b69d38 100644 --- a/contracts/gas-snapshots/liquiditymanager.gas-snapshot +++ b/contracts/gas-snapshots/liquiditymanager.gas-snapshot @@ -3,9 +3,9 @@ LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279198) LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206764) LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192374) LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141798) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 9306766) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 9301906) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 9231739) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 9435757) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 9430897) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 9360730) LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382928) LiquidityManager_receive:test_receive_success() (gas: 21182) LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184959) @@ -19,7 +19,7 @@ LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987) LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836) LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11030) LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10621) -LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3847203) +LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3976150) LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925) LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389) LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180396) diff --git a/contracts/src/v0.8/ccip/pools/TokenPool.sol b/contracts/src/v0.8/ccip/pools/TokenPool.sol index 69bab031f57..9d8e77a7928 100644 --- a/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -52,6 +52,7 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { error PoolAlreadyAdded(uint64 remoteChainSelector, bytes remotePoolAddress); error InvalidRemotePoolForChain(uint64 remoteChainSelector, bytes remotePoolAddress); error InvalidRemoteChainDecimals(bytes sourcePoolData); + error MismatchedArrayLengths(); error OverflowDetected(uint8 remoteDecimals, uint8 localDecimals, uint256 remoteAmount); error InvalidDecimalArgs(uint8 expected, uint8 actual); @@ -536,6 +537,25 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { return s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); } + /// @notice Sets multiple chain rate limiter configs. + /// @param remoteChainSelectors The remote chain selector for which the rate limits apply. + /// @param outboundConfigs The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. + /// @param inboundConfigs The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. + function setChainRateLimiterConfigs( + uint64[] calldata remoteChainSelectors, + RateLimiter.Config[] calldata outboundConfigs, + RateLimiter.Config[] calldata inboundConfigs + ) external { + if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); + if (remoteChainSelectors.length != outboundConfigs.length || remoteChainSelectors.length != inboundConfigs.length) { + revert MismatchedArrayLengths(); + } + + for (uint256 i = 0; i < remoteChainSelectors.length; ++i) { + _setRateLimitConfig(remoteChainSelectors[i], outboundConfigs[i], inboundConfigs[i]); + } + } + /// @notice Sets the chain rate limiter config. /// @param remoteChainSelector The remote chain selector for which the rate limits apply. /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol new file mode 100644 index 00000000000..716e06734ee --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_setChainRateLimiterConfigs is TokenPoolSetup { + uint64 internal s_remoteChainSelector; + + function setUp() public virtual override { + TokenPoolSetup.setUp(); + + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(address(2)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + s_remoteChainSelector = 123124; + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: s_remoteChainSelector, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(address(3)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + } + + function testFuzz_SetChainRateLimiterConfigs_Success(uint128 capacity, uint128 rate, uint32 newTime) public { + // Cap the lower bound to 4 so 4/2 is still >= 2 + vm.assume(capacity >= 4); + // Cap the lower bound to 2 so 2/2 is still >= 1 + rate = uint128(bound(rate, 2, capacity - 2)); + // Bucket updates only work on increasing time + newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); + vm.warp(newTime); + + uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; + uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; + + RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); + RateLimiter.Config memory newInboundConfig = + RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); + + uint64[] memory chainSelectors = new uint64[](1); + chainSelectors[0] = DEST_CHAIN_SELECTOR; + + RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); + newOutboundConfigs[0] = newOutboundConfig; + + RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](1); + newInboundConfigs[0] = newInboundConfig; + + vm.expectEmit(); + emit RateLimiter.ConfigChanged(newOutboundConfig); + vm.expectEmit(); + emit RateLimiter.ConfigChanged(newInboundConfig); + vm.expectEmit(); + emit TokenPool.ChainConfigured(DEST_CHAIN_SELECTOR, newOutboundConfig, newInboundConfig); + + s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); + + uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); + + RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR); + assertEq(bucket.capacity, newOutboundConfig.capacity); + assertEq(bucket.rate, newOutboundConfig.rate); + assertEq(bucket.tokens, expectedTokens); + assertEq(bucket.lastUpdated, newTime); + + expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); + + bucket = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR); + assertEq(bucket.capacity, newInboundConfig.capacity); + assertEq(bucket.rate, newInboundConfig.rate); + assertEq(bucket.tokens, expectedTokens); + assertEq(bucket.lastUpdated, newTime); + } + + // Reverts + + function test_OnlyOwnerOrRateLimitAdmin_Revert() public { + uint64[] memory chainSelectors = new uint64[](1); + chainSelectors[0] = DEST_CHAIN_SELECTOR; + + RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); + newOutboundConfigs[0] = _getOutboundRateLimiterConfig(); + + RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](1); + newInboundConfigs[0] = _getInboundRateLimiterConfig(); + + vm.startPrank(STRANGER); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); + s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); + } + + function test_NonExistentChain_Revert() public { + uint64 wrongChainSelector = 9084102894; + + uint64[] memory chainSelectors = new uint64[](1); + chainSelectors[0] = wrongChainSelector; + + RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); + RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](1); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); + s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); + } + + function test_MismatchedArrayLengths_Revert() public { + uint64[] memory chainSelectors = new uint64[](1); + + RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); + RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](2); + + // test mismatched array lengths between rate limiters + vm.expectRevert(abi.encodeWithSelector(TokenPool.MismatchedArrayLengths.selector)); + s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); + + newInboundConfigs = new RateLimiter.Config[](1); + chainSelectors = new uint64[](2); + + // test mismatched array lengths between chain selectors and rate limiters + vm.expectRevert(abi.encodeWithSelector(TokenPool.MismatchedArrayLengths.selector)); + s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); + } +} diff --git a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go index def5c4bc258..884dc9e52e5 100644 --- a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004c6338038062004c63833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161402e62000c356000396000818161054f01528181611d8201526127d30152600081816105290152818161189f015261206e0152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b6901528181611bce01528181611c270152611cc90152600081816102470152818161029c01528181610708015281816121f10152818161276901526129be015261402e6000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e236600461317e565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000081525081565b6040516101f39190613224565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a366004613259565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d610318366004613276565b61067e565b604051905181526020016101f3565b6101e761033a3660046132cf565b61084d565b61035261034d36600461339e565b610897565b005b6103526103623660046132cf565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b366004613259565b610a7d565b6101e76103ae36600461340a565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df366004613425565b610b15565b6040516101f39190613460565b6104046103ff36600461340a565b610bee565b6040516101f391906134b7565b610419610d59565b6040516101f39190613539565b6103526104343660046132cf565b610d6a565b61044c61044736600461340a565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d436600461340a565b610f57565b6103526104e7366004613259565b611007565b6104f46110e2565b6040516101f39190613593565b61044c61050f36600461340a565b61119a565b61035261052236600461371b565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b61035261058136600461339e565b6112f0565b610352610594366004613259565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c0870187613760565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d6060860160408701613259565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d3925050506060840160408501613259565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f83836040516108629291906137c5565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d12565b949350505050565b61089f611d2d565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d8092505050565b50505050565b61091a611d2d565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3692505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611d2d565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611d12565b6040805180820190915260608082526020820152610b3282612030565b610b3f82606001356121bc565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d4919061340a565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c179060050161225e565b90506000815167ffffffffffffffff811115610c3557610c356135d5565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6137d5565b602002602001015181526020019081526020016000208054610cae90613804565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda90613804565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6137d5565b6020908102919091010152600101610c6e565b509392505050565b6060610d65600261225e565b905090565b610d72611d2d565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd09291906137c5565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061226b565b610e39578282826040517f74f23c7c000000000000000000000000000000000000000000000000000000008152600401610961939291906138a0565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e759291906138c4565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067890612277565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f8290613804565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae90613804565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611d2d565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f0600561225e565b90506000815167ffffffffffffffff81111561110e5761110e6135d5565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586137d5565b6020026020010151828281518110611172576111726137d5565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067890612277565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa838383612329565b6112f8611d2d565b60005b838110156114e5576000858583818110611317576113176137d5565b905060200201602081019061132c919061340a565b9050611343600567ffffffffffffffff831661226b565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa9060050161225e565b905060005b81518110156114165761140d8282815181106113cd576113cd6137d5565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226b90919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f6004830182613111565b6005820160008181611491828261314b565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056137d5565b905060200281019061151791906138d8565b611520906139a4565b905061153181606001516000612413565b61154081608001516000612413565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff16612550565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f9082613b1b565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6137d5565b6020026020010151611f36565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613c35565b60405180910390a150506001016114e9565b5050505050565b61180a611d2d565b6118138161255c565b50565b61182961029a60a0830160808401613259565b6118885761183d60a0820160808301613259565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d4604084016020850161340a565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613cce565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b3604083016020840161340a565b612620565b6119d86119cb604083016020840161340a565b61033a60a0840184613760565b611a1d576119e960a0820182613760565b6040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109619291906138c4565b611813611a30604083016020840161340a565b8260600135612746565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109619190613224565b600082806020019051810190611abf9190613ceb565b905060ff81111561067857826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109619190613224565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c1f576000611b8e7f000000000000000000000000000000000000000000000000000000000000000084613d33565b9050604d8160ff161115611c02576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611c0d81600a613e6c565b611c179085613e7b565b915050610678565b6000611c4b837f0000000000000000000000000000000000000000000000000000000000000000613d33565b9050604d8160ff161180611c925750611c6581600a613e6c565b611c8f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e7b565b84115b15611cfd576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611d0881600a613e6c565b61088f9085613eb6565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d7e576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd7576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e6d576000838281518110611df757611df76137d5565b60200260200101519050611e1581600261278d90919063ffffffff16565b15611e645760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dda565b5060005b81518110156109aa576000828281518110611e8e57611e8e6137d5565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ed25750611f2e565b611edd6002826127af565b15611f2c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e71565b8051600003611f71576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611fa39060050182612550565b611fdd5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613ecd565b6000818152600860205260409020611ff58382613b1b565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e759190613224565b61204361029a60a0830160808401613259565b6120575761183d60a0820160808301613259565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6120a3604084016020850161340a565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121389190613cce565b1561216f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121876121826060830160408401613259565b6127d1565b61219f61219a604083016020840161340a565b612850565b6118136121b2604083016020840161340a565b826060013561299e565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b15801561224a57600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611d26836129e2565b6000611d268383612a3d565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261230582606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e99190613ef0565b85608001516fffffffffffffffffffffffffffffffff16612b30565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61233283610afe565b612374576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b61237f826000612413565b67ffffffffffffffff831660009081526007602052604090206123a29083612b58565b6123ad816000612413565b67ffffffffffffffff831660009081526007602052604090206123d39060020182612b58565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161240693929190613f03565b60405180910390a1505050565b8151156124de5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612469575060408201516fffffffffffffffffffffffffffffffff16155b156124a257816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613f86565b80156124da576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612517575060208201516fffffffffffffffffffffffffffffffff1615155b156124da57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613f86565b6000611d268383612cfa565b3373ffffffffffffffffffffffffffffffffffffffff8216036125ab576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262981610afe565b61266b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270e9190613cce565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124da90600201827f0000000000000000000000000000000000000000000000000000000000000000612d49565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612a3d565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612cfa565b7f000000000000000000000000000000000000000000000000000000000000000015611813576128026002826130cc565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61285981610afe565b61289b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129389190613fc2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124da90827f0000000000000000000000000000000000000000000000000000000000000000612d49565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b815481526020019060010190808311612a1e5750505050509050919050565b60008181526001830160205260408120548015612b26576000612a61600183613ef0565b8554909150600090612a7590600190613ef0565b9050808214612ada576000866000018281548110612a9557612a956137d5565b9060005260206000200154905080876000018481548110612ab857612ab86137d5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612aeb57612aeb613fdf565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612b4f85612b408486613eb6565b612b4a908761400e565b6130fb565b95945050505050565b8154600090612b8190700100000000000000000000000000000000900463ffffffff1642613ef0565b90508015612c235760018301548354612bc9916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b30565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c49916fffffffffffffffffffffffffffffffff90811691166130fb565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612406908490613f86565b6000818152600183016020526040812054612d4157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612d70575081155b15612d7a57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612dc090700100000000000000000000000000000000900463ffffffff1642613ef0565b90508015612e805781831115612e02576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e3c9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b30565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f375773ffffffffffffffffffffffffffffffffffffffff8416612edf576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b8483101561304a5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f7b9082613ef0565b612f85878a613ef0565b612f8f919061400e565b612f999190613e7b565b905073ffffffffffffffffffffffffffffffffffffffff8616612ff2576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b6130548584613ef0565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d26565b600081831061310a5781611d26565b5090919050565b50805461311d90613804565b6000825580601f1061312d575050565b601f0160209004906000526020600020908101906118139190613165565b508054600082559060005260206000209081019061181391905b5b8082111561317a5760008155600101613166565b5090565b60006020828403121561319057600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d2657600080fd5b6000815180845260005b818110156131e6576020818501810151868301820152016131ca565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d2660208301846131c0565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561326b57600080fd5b8135611d2681613237565b60006020828403121561328857600080fd5b813567ffffffffffffffff81111561329f57600080fd5b82016101008185031215611d2657600080fd5b803567ffffffffffffffff811681146132ca57600080fd5b919050565b6000806000604084860312156132e457600080fd5b6132ed846132b2565b9250602084013567ffffffffffffffff8082111561330a57600080fd5b818601915086601f83011261331e57600080fd5b81358181111561332d57600080fd5b87602082850101111561333f57600080fd5b6020830194508093505050509250925092565b60008083601f84011261336457600080fd5b50813567ffffffffffffffff81111561337c57600080fd5b6020830191508360208260051b850101111561339757600080fd5b9250929050565b600080600080604085870312156133b457600080fd5b843567ffffffffffffffff808211156133cc57600080fd5b6133d888838901613352565b909650945060208701359150808211156133f157600080fd5b506133fe87828801613352565b95989497509550505050565b60006020828403121561341c57600080fd5b611d26826132b2565b60006020828403121561343757600080fd5b813567ffffffffffffffff81111561344e57600080fd5b820160a08185031215611d2657600080fd5b60208152600082516040602084015261347c60608401826131c0565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4f82826131c0565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561352c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261351a8583516131c0565b945092850192908501906001016134e0565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613555565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358757835167ffffffffffffffff16835292840192918401916001016135af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613627576136276135d5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613674576136746135d5565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff811681146132ca57600080fd5b6000606082840312156136bc57600080fd5b6040516060810181811067ffffffffffffffff821117156136df576136df6135d5565b60405290508082356136f08161367c565b81526136fe6020840161368a565b602082015261370f6040840161368a565b60408201525092915050565b600080600060e0848603121561373057600080fd5b613739846132b2565b925061374885602086016136aa565b915061375785608086016136aa565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261379557600080fd5b83018035915067ffffffffffffffff8211156137b057600080fd5b60200191503681900382131561339757600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381857607f821691505b602082108103613851577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b4f604083018486613857565b60208152600061088f602083018486613857565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390c57600080fd5b9190910192915050565b600082601f83011261392757600080fd5b813567ffffffffffffffff811115613941576139416135d5565b61397260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161362d565b81815284602083860101111561398757600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b757600080fd5b6139bf613604565b6139c8836132b2565b815260208084013567ffffffffffffffff808211156139e657600080fd5b9085019036601f8301126139f957600080fd5b813581811115613a0b57613a0b6135d5565b8060051b613a1a85820161362d565b9182528381018501918581019036841115613a3457600080fd5b86860192505b83831015613a7057823585811115613a525760008081fd5b613a603689838a0101613916565b8352509186019190860190613a3a565b8087890152505050506040860135925080831115613a8d57600080fd5b5050613a9b36828601613916565b604083015250613aae36606085016136aa565b6060820152613ac03660c085016136aa565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c81016020861015613af45750805b601f850160051c820191505b81811015613b1357828155600101613b00565b505050505050565b815167ffffffffffffffff811115613b3557613b356135d5565b613b4981613b438454613804565b84613acb565b602080601f831160018114613b9c5760008415613b665750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b13565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be957888601518255948401946001909101908401613bca565b5085821015613c2557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c59818401876131c0565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c979050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b4f565b600060208284031215613ce057600080fd5b8151611d268161367c565b600060208284031215613cfd57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613d04565b600181815b80851115613da557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8b57613d8b613d04565b80851615613d9857918102915b93841c9390800290613d51565b509250929050565b600082613dbc57506001610678565b81613dc957506000610678565b8160018114613ddf5760028114613de957613e05565b6001915050610678565b60ff841115613dfa57613dfa613d04565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613e28575081810a610678565b613e328383613d4c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e6457613e64613d04565b029392505050565b6000611d2660ff841683613dad565b600082613eb1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613d04565b67ffffffffffffffff8316815260406020820152600061088f60408301846131c0565b8181038181111561067857610678613d04565b67ffffffffffffffff8416815260e08101613f4f60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fd457600080fd5b8151611d2681613237565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613d0456fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004ed638038062004ed6833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516142a162000c356000396000818161056d01528181611efa0152612aed01526000818161054701528181611a1701526122d00152600081816102eb01528181610d2101528181611bc001528181611c7a01528181611cae01528181611ce101528181611d4601528181611d9f0152611e41015260008181610252015281816102a70152818161072601528181612453015281816128e10152612cd801526142a16000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610545578063e0351e131461056b578063e8a1da1714610591578063f2fde38b146105a457600080fd5b8063c0d78655146104f7578063c4bffe2b1461050a578063c75eea9c1461051f578063cf7401f31461053257600080fd5b8063acfecf91116100de578063acfecf9114610444578063af58d59f14610457578063b0f479a1146104c6578063b7946580146104e457600080fd5b80639a4575b9146103ef578063a42a7b8b1461040f578063a7cd63b71461042f57600080fd5b806354c8a4f31161017c5780637d54534e1161014b5780637d54534e146103985780638926f54f146103ab5780638da5cb5b146103be578063962d4020146103dc57600080fd5b806354c8a4f31461034a57806362ddd3c41461035f5780636d3d1a581461037257806379ba50971461039057600080fd5b8063240028e8116101b8578063240028e81461029757806324f65ee7146102e457806339077537146103155780634c5ef0ed1461033757600080fd5b806301ffc9a7146101df578063181f5a771461020757806321df0da714610250575b600080fd5b6101f26101ed3660046132f6565b6105b7565b60405190151581526020015b60405180910390f35b6102436040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000081525081565b6040516101fe919061339c565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f26102a53660046133d1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101fe565b6103286103233660046133ee565b61069c565b604051905181526020016101fe565b6101f2610345366004613447565b61086b565b61035d610358366004613516565b6108b5565b005b61035d61036d366004613447565b610930565b60095473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6109cd565b61035d6103a63660046133d1565b610a9b565b6101f26103b9366004613582565b610b1c565b60015473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6103ea3660046135e2565b610b33565b6104026103fd36600461367c565b610c8d565b6040516101fe91906136b7565b61042261041d366004613582565b610d66565b6040516101fe919061370e565b610437610ed1565b6040516101fe9190613790565b61035d610452366004613447565b610ee2565b61046a610465366004613582565b610ffa565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610272565b6102436104f2366004613582565b6110cf565b61035d6105053660046133d1565b61117f565b61051261125a565b6040516101fe91906137ea565b61046a61052d366004613582565b611312565b61035d610540366004613972565b6113e4565b7f0000000000000000000000000000000000000000000000000000000000000000610272565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b61035d61059f366004613516565b611468565b61035d6105b23660046133d1565b61197a565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061064a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061069657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526106b48261198e565b600061070d60608401356107086106ce60c08701876139b7565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb292505050565b611c76565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961075b60608601604087016133d1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107c857600080fd5b505af11580156107dc573d6000803e3d6000fd5b506107f19250505060608401604085016133d1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161084f91815260200190565b60405180910390a3604080516020810190915290815292915050565b60006108ad8383604051610880929190613a1c565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611e8a565b949350505050565b6108bd611ea5565b61092a84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ef892505050565b50505050565b610938611ea5565b61094183610b1c565b610988576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109c88383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506120ae92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a1e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610aa3611ea5565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610696600567ffffffffffffffff8416611e8a565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610b73575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610bac576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b8483141580610bbb5750848114155b15610bf2576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610c8457610c7c878783818110610c1257610c12613a2c565b9050602002016020810190610c279190613582565b868684818110610c3957610c39613a2c565b905060600201803603810190610c4f9190613a5b565b858585818110610c6157610c61613a2c565b905060600201803603810190610c779190613a5b565b6121a8565b600101610bf5565b50505050505050565b6040805180820190915260608082526020820152610caa82612292565b610cb7826060013561241e565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610d118460200160208101906104f29190613582565b8152602001610d5e6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610d8f906005016124c0565b90506000815167ffffffffffffffff811115610dad57610dad61382c565b604051908082528060200260200182016040528015610de057816020015b6060815260200190600190039081610dcb5790505b50905060005b8251811015610ec95760086000848381518110610e0557610e05613a2c565b602002602001015181526020019081526020016000208054610e2690613a77565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5290613a77565b8015610e9f5780601f10610e7457610100808354040283529160200191610e9f565b820191906000526020600020905b815481529060010190602001808311610e8257829003601f168201915b5050505050828281518110610eb657610eb6613a2c565b6020908102919091010152600101610de6565b509392505050565b6060610edd60026124c0565b905090565b610eea611ea5565b610ef383610b1c565b610f35576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b610f758282604051610f48929190613a1c565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906124cd565b610fb1578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161097f93929190613b13565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610fed929190613b37565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526003909101548084166060830152919091049091166080820152610696906124d9565b67ffffffffffffffff811660009081526007602052604090206004018054606091906110fa90613a77565b80601f016020809104026020016040519081016040528092919081815260200182805461112690613a77565b80156111735780601f1061114857610100808354040283529160200191611173565b820191906000526020600020905b81548152906001019060200180831161115657829003601f168201915b50505050509050919050565b611187611ea5565b73ffffffffffffffffffffffffffffffffffffffff81166111d4576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061126860056124c0565b90506000815167ffffffffffffffff8111156112865761128661382c565b6040519080825280602002602001820160405280156112af578160200160208202803683370190505b50905060005b825181101561130b578281815181106112d0576112d0613a2c565b60200260200101518282815181106112ea576112ea613a2c565b67ffffffffffffffff909216602092830291909101909101526001016112b5565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526001909101548084166060830152919091049091166080820152610696906124d9565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590611424575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561145d576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b6109c88383836121a8565b611470611ea5565b60005b8381101561165d57600085858381811061148f5761148f613a2c565b90506020020160208101906114a49190613582565b90506114bb600567ffffffffffffffff83166124cd565b6114fd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b67ffffffffffffffff81166000908152600760205260408120611522906005016124c0565b905060005b815181101561158e5761158582828151811061154557611545613a2c565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016124cd90919063ffffffff16565b50600101611527565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115f76004830182613289565b600582016000818161160982826132c3565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169450602001925061164b915050565b60405180910390a15050600101611473565b5060005b8181101561197357600083838381811061167d5761167d613a2c565b905060200281019061168f9190613b4b565b61169890613c17565b90506116a98160600151600061258b565b6116b88160800151600061258b565b8060400151516000036116f7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805161170f9060059067ffffffffffffffff166126c8565b6117545780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161097f565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906118d79082613d8e565b5060005b82602001515181101561191b5761191383600001518460200151838151811061190657611906613a2c565b60200260200101516120ae565b6001016118db565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516119619493929190613ea8565b60405180910390a15050600101611661565b5050505050565b611982611ea5565b61198b816126d4565b50565b6119a16102a560a08301608084016133d1565b611a00576119b560a08201608083016133d1565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161097f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611a4c6040840160208501613582565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae19190613f41565b15611b18576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b30611b2b6040830160208401613582565b612798565b611b50611b436040830160208401613582565b61034560a08401846139b7565b611b9557611b6160a08201826139b7565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161097f929190613b37565b61198b611ba86040830160208401613582565b82606001356128be565b60008151600003611be457507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611c2157816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f919061339c565b600082806020019051810190611c379190613f5e565b905060ff81111561069657826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f919061339c565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611cac575081610696565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611d97576000611d067f000000000000000000000000000000000000000000000000000000000000000084613fa6565b9050604d8160ff161115611d7a576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611d8581600a6140df565b611d8f90856140ee565b915050610696565b6000611dc3837f0000000000000000000000000000000000000000000000000000000000000000613fa6565b9050604d8160ff161180611e0a5750611ddd81600a6140df565b611e07907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6140ee565b84115b15611e75576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611e8081600a6140df565b6108ad9085614129565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611ef6576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611f4f576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611fe5576000838281518110611f6f57611f6f613a2c565b60200260200101519050611f8d81600261290590919063ffffffff16565b15611fdc5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f52565b5060005b81518110156109c857600082828151811061200657612006613a2c565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361204a57506120a6565b612055600282612927565b156120a45760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611fe9565b80516000036120e9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061211b90600501826126c8565b6121555782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161097f929190614140565b600081815260086020526040902061216d8382613d8e565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610fed919061339c565b6121b183610b1c565b6121f3576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b6121fe82600061258b565b67ffffffffffffffff831660009081526007602052604090206122219083612949565b61222c81600061258b565b67ffffffffffffffff831660009081526007602052604090206122529060020182612949565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161228593929190614163565b60405180910390a1505050565b6122a56102a560a08301608084016133d1565b6122b9576119b560a08201608083016133d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6123056040840160208501613582565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612376573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239a9190613f41565b156123d1576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e96123e460608301604084016133d1565b612aeb565b6124016123fc6040830160208401613582565b612b6a565b61198b6124146040830160208401613582565b8260600135612cb8565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b1580156124ac57600080fd5b505af1158015611973573d6000803e3d6000fd5b60606000611e9e83612cfc565b6000611e9e8383612d57565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261256782606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261254b91906141e6565b85608001516fffffffffffffffffffffffffffffffff16612e4a565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b8151156126565781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806125e1575060408201516fffffffffffffffffffffffffffffffff16155b1561261a57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161097f91906141f9565b8015612652576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff1615158061268f575060208201516fffffffffffffffffffffffffffffffff1615155b1561265257816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161097f91906141f9565b6000611e9e8383612e72565b3373ffffffffffffffffffffffffffffffffffffffff821603612723576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6127a181610b1c565b6127e3576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128869190613f41565b61198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061265290600201827f0000000000000000000000000000000000000000000000000000000000000000612ec1565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612d57565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612e72565b815460009061297290700100000000000000000000000000000000900463ffffffff16426141e6565b90508015612a1457600183015483546129ba916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612e4a565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612a3a916fffffffffffffffffffffffffffffffff9081169116613244565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906122859084906141f9565b7f00000000000000000000000000000000000000000000000000000000000000001561198b57612b1c60028261325a565b61198b576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161097f565b612b7381610b1c565b612bb5576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612c2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c529190614235565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061265290827f0000000000000000000000000000000000000000000000000000000000000000612ec1565b60608160000180548060200260200160405190810160405280929190818152602001828054801561117357602002820191906000526020600020905b815481526020019060010190808311612d385750505050509050919050565b60008181526001830160205260408120548015612e40576000612d7b6001836141e6565b8554909150600090612d8f906001906141e6565b9050808214612df4576000866000018281548110612daf57612daf613a2c565b9060005260206000200154905080876000018481548110612dd257612dd2613a2c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e0557612e05614252565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610696565b6000915050610696565b6000612e6985612e5a8486614129565b612e649087614281565b613244565b95945050505050565b6000818152600183016020526040812054612eb957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610696565b506000610696565b825474010000000000000000000000000000000000000000900460ff161580612ee8575081155b15612ef257505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612f3890700100000000000000000000000000000000900463ffffffff16426141e6565b90508015612ff85781831115612f7a576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612fb49083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612e4a565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156130af5773ffffffffffffffffffffffffffffffffffffffff8416613057576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161097f565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161097f565b848310156131c25760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906130f390826141e6565b6130fd878a6141e6565b6131079190614281565b61311191906140ee565b905073ffffffffffffffffffffffffffffffffffffffff861661316a576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161097f565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161097f565b6131cc85846141e6565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b60008183106132535781611e9e565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611e9e565b50805461329590613a77565b6000825580601f106132a5575050565b601f01602090049060005260206000209081019061198b91906132dd565b508054600082559060005260206000209081019061198b91905b5b808211156132f257600081556001016132de565b5090565b60006020828403121561330857600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9e57600080fd5b6000815180845260005b8181101561335e57602081850181015186830182015201613342565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611e9e6020830184613338565b73ffffffffffffffffffffffffffffffffffffffff8116811461198b57600080fd5b6000602082840312156133e357600080fd5b8135611e9e816133af565b60006020828403121561340057600080fd5b813567ffffffffffffffff81111561341757600080fd5b82016101008185031215611e9e57600080fd5b803567ffffffffffffffff8116811461344257600080fd5b919050565b60008060006040848603121561345c57600080fd5b6134658461342a565b9250602084013567ffffffffffffffff8082111561348257600080fd5b818601915086601f83011261349657600080fd5b8135818111156134a557600080fd5b8760208285010111156134b757600080fd5b6020830194508093505050509250925092565b60008083601f8401126134dc57600080fd5b50813567ffffffffffffffff8111156134f457600080fd5b6020830191508360208260051b850101111561350f57600080fd5b9250929050565b6000806000806040858703121561352c57600080fd5b843567ffffffffffffffff8082111561354457600080fd5b613550888389016134ca565b9096509450602087013591508082111561356957600080fd5b50613576878288016134ca565b95989497509550505050565b60006020828403121561359457600080fd5b611e9e8261342a565b60008083601f8401126135af57600080fd5b50813567ffffffffffffffff8111156135c757600080fd5b60208301915083602060608302850101111561350f57600080fd5b600080600080600080606087890312156135fb57600080fd5b863567ffffffffffffffff8082111561361357600080fd5b61361f8a838b016134ca565b9098509650602089013591508082111561363857600080fd5b6136448a838b0161359d565b9096509450604089013591508082111561365d57600080fd5b5061366a89828a0161359d565b979a9699509497509295939492505050565b60006020828403121561368e57600080fd5b813567ffffffffffffffff8111156136a557600080fd5b820160a08185031215611e9e57600080fd5b6020815260008251604060208401526136d36060840182613338565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e698282613338565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613783577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613771858351613338565b94509285019290850190600101613737565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137de57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016137ac565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137de57835167ffffffffffffffff1683529284019291840191600101613806565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561387e5761387e61382c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138cb576138cb61382c565b604052919050565b801515811461198b57600080fd5b80356fffffffffffffffffffffffffffffffff8116811461344257600080fd5b60006060828403121561391357600080fd5b6040516060810181811067ffffffffffffffff821117156139365761393661382c565b6040529050808235613947816138d3565b8152613955602084016138e1565b6020820152613966604084016138e1565b60408201525092915050565b600080600060e0848603121561398757600080fd5b6139908461342a565b925061399f8560208601613901565b91506139ae8560808601613901565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139ec57600080fd5b83018035915067ffffffffffffffff821115613a0757600080fd5b60200191503681900382131561350f57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608284031215613a6d57600080fd5b611e9e8383613901565b600181811c90821680613a8b57607f821691505b602082108103613ac4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612e69604083018486613aca565b6020815260006108ad602083018486613aca565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1833603018112613b7f57600080fd5b9190910192915050565b600082601f830112613b9a57600080fd5b813567ffffffffffffffff811115613bb457613bb461382c565b613be560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613884565b818152846020838601011115613bfa57600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215613c2a57600080fd5b613c3261385b565b613c3b8361342a565b815260208084013567ffffffffffffffff80821115613c5957600080fd5b9085019036601f830112613c6c57600080fd5b813581811115613c7e57613c7e61382c565b8060051b613c8d858201613884565b9182528381018501918581019036841115613ca757600080fd5b86860192505b83831015613ce357823585811115613cc55760008081fd5b613cd33689838a0101613b89565b8352509186019190860190613cad565b8087890152505050506040860135925080831115613d0057600080fd5b5050613d0e36828601613b89565b604083015250613d213660608501613901565b6060820152613d333660c08501613901565b608082015292915050565b601f8211156109c8576000816000526020600020601f850160051c81016020861015613d675750805b601f850160051c820191505b81811015613d8657828155600101613d73565b505050505050565b815167ffffffffffffffff811115613da857613da861382c565b613dbc81613db68454613a77565b84613d3e565b602080601f831160018114613e0f5760008415613dd95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613d86565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e5c57888601518255948401946001909101908401613e3d565b5085821015613e9857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ecc81840187613338565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613f0a9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e69565b600060208284031215613f5357600080fd5b8151611e9e816138d3565b600060208284031215613f7057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561069657610696613f77565b600181815b8085111561401857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613ffe57613ffe613f77565b8085161561400b57918102915b93841c9390800290613fc4565b509250929050565b60008261402f57506001610696565b8161403c57506000610696565b8160018114614052576002811461405c57614078565b6001915050610696565b60ff84111561406d5761406d613f77565b50506001821b610696565b5060208310610133831016604e8410600b841016171561409b575081810a610696565b6140a58383613fbf565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156140d7576140d7613f77565b029392505050565b6000611e9e60ff841683614020565b600082614124577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761069657610696613f77565b67ffffffffffffffff831681526040602082015260006108ad6040830184613338565b67ffffffffffffffff8416815260e081016141af60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526108ad565b8181038181111561069657610696613f77565b6060810161069682848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561424757600080fd5b8151611e9e816133af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561069657610696613f7756fea164736f6c6343000818000a", } var BurnFromMintTokenPoolABI = BurnFromMintTokenPoolMetaData.ABI @@ -713,6 +713,18 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetChainRa return _BurnFromMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -3033,6 +3045,8 @@ type BurnFromMintTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go index ecfad493c2c..d789ab8e3bf 100644 --- a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004809380380620048098339810160408190526200003591620005a2565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001eb565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006c4565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db908462000265565b5050505050505050505062000730565b336001600160a01b038216036200021557604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000286576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000311576000838281518110620002aa57620002aa620006e2565b60209081029190910101519050620002c4600282620003c2565b1562000307576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000289565b5060005b8151811015620003bd576000828281518110620003365762000336620006e2565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003625750620003b4565b6200036f600282620003e2565b15620003b2576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000315565b505050565b6000620003d9836001600160a01b038416620003f9565b90505b92915050565b6000620003d9836001600160a01b038416620004fd565b60008181526001830160205260408120548015620004f257600062000420600183620006f8565b85549091506000906200043690600190620006f8565b9050808214620004a25760008660000182815481106200045a576200045a620006e2565b9060005260206000200154905080876000018481548110620004805762000480620006e2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004b657620004b66200071a565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003dc565b6000915050620003dc565b60008181526001830160205260408120546200054657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003dc565b506000620003dc565b6001600160a01b03811681146200056557600080fd5b50565b805160ff811681146200057a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b80516200057a816200054f565b600080600080600060a08688031215620005bb57600080fd5b8551620005c8816200054f565b94506020620005d987820162000568565b60408801519095506001600160401b0380821115620005f757600080fd5b818901915089601f8301126200060c57600080fd5b8151818111156200062157620006216200057f565b8060051b604051601f19603f830116810181811085821117156200064957620006496200057f565b60405291825284820192508381018501918c8311156200066857600080fd5b938501935b828510156200069157620006818562000595565b845293850193928501926200066d565b809850505050505050620006a86060870162000595565b9150620006b86080870162000595565b90509295509295909350565b600060208284031215620006d757600080fd5b620003d98262000568565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003dc57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051614028620007e16000396000818161054f01528181611d8201526127cd0152600081816105290152818161189f015261206e0152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b6901528181611bce01528181611c270152611cc90152600081816102470152818161029c01528181610708015281816121eb0152818161276301526129b801526140286000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e2366004613178565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000081525081565b6040516101f3919061321e565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a366004613253565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d610318366004613270565b61067e565b604051905181526020016101f3565b6101e761033a3660046132c9565b61084d565b61035261034d366004613398565b610897565b005b6103526103623660046132c9565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b366004613253565b610a7d565b6101e76103ae366004613404565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df36600461341f565b610b15565b6040516101f3919061345a565b6104046103ff366004613404565b610bee565b6040516101f391906134b1565b610419610d59565b6040516101f39190613533565b6103526104343660046132c9565b610d6a565b61044c610447366004613404565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d4366004613404565b610f57565b6103526104e7366004613253565b611007565b6104f46110e2565b6040516101f3919061358d565b61044c61050f366004613404565b61119a565b610352610522366004613715565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b610352610581366004613398565b6112f0565b610352610594366004613253565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c087018761375a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d6060860160408701613253565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d3925050506060840160408501613253565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f83836040516108629291906137bf565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d12565b949350505050565b61089f611d2d565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d8092505050565b50505050565b61091a611d2d565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3692505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611d2d565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611d12565b6040805180820190915260608082526020820152610b3282612030565b610b3f82606001356121bc565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d49190613404565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1790600501612258565b90506000815167ffffffffffffffff811115610c3557610c356135cf565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6137cf565b602002602001015181526020019081526020016000208054610cae906137fe565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda906137fe565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6137cf565b6020908102919091010152600101610c6e565b509392505050565b6060610d656002612258565b905090565b610d72611d2d565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd09291906137bf565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612265565b610e39578282826040517f74f23c7c0000000000000000000000000000000000000000000000000000000081526004016109619392919061389a565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e759291906138be565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067890612271565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f82906137fe565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae906137fe565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611d2d565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f06005612258565b90506000815167ffffffffffffffff81111561110e5761110e6135cf565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586137cf565b6020026020010151828281518110611172576111726137cf565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067890612271565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa838383612323565b6112f8611d2d565b60005b838110156114e5576000858583818110611317576113176137cf565b905060200201602081019061132c9190613404565b9050611343600567ffffffffffffffff8316612265565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa90600501612258565b905060005b81518110156114165761140d8282815181106113cd576113cd6137cf565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226590919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f600483018261310b565b60058201600081816114918282613145565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056137cf565b905060200281019061151791906138d2565b6115209061399e565b90506115318160600151600061240d565b6115408160800151600061240d565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff1661254a565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f9082613b15565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6137cf565b6020026020010151611f36565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613c2f565b60405180910390a150506001016114e9565b5050505050565b61180a611d2d565b61181381612556565b50565b61182961029a60a0830160808401613253565b6118885761183d60a0820160808301613253565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d46040840160208501613404565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613cc8565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b36040830160208401613404565b61261a565b6119d86119cb6040830160208401613404565b61033a60a084018461375a565b611a1d576119e960a082018261375a565b6040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109619291906138be565b611813611a306040830160208401613404565b8260600135612740565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f7000000000000000000000000000000000000000000000000000000008152600401610961919061321e565b600082806020019051810190611abf9190613ce5565b905060ff81111561067857826040517f953576f7000000000000000000000000000000000000000000000000000000008152600401610961919061321e565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c1f576000611b8e7f000000000000000000000000000000000000000000000000000000000000000084613d2d565b9050604d8160ff161115611c02576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611c0d81600a613e66565b611c179085613e75565b915050610678565b6000611c4b837f0000000000000000000000000000000000000000000000000000000000000000613d2d565b9050604d8160ff161180611c925750611c6581600a613e66565b611c8f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e75565b84115b15611cfd576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611d0881600a613e66565b61088f9085613eb0565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d7e576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd7576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e6d576000838281518110611df757611df76137cf565b60200260200101519050611e1581600261278790919063ffffffff16565b15611e645760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dda565b5060005b81518110156109aa576000828281518110611e8e57611e8e6137cf565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ed25750611f2e565b611edd6002826127a9565b15611f2c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e71565b8051600003611f71576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611fa3906005018261254a565b611fdd5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613ec7565b6000818152600860205260409020611ff58382613b15565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e75919061321e565b61204361029a60a0830160808401613253565b6120575761183d60a0820160808301613253565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6120a36040840160208501613404565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121389190613cc8565b1561216f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121876121826060830160408401613253565b6127cb565b61219f61219a6040830160208401613404565b61284a565b6118136121b26040830160208401613404565b8260600135612998565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b15801561224457600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611d26836129dc565b6000611d268383612a37565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526122ff82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e39190613eea565b85608001516fffffffffffffffffffffffffffffffff16612b2a565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61232c83610afe565b61236e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b61237982600061240d565b67ffffffffffffffff8316600090815260076020526040902061239c9083612b52565b6123a781600061240d565b67ffffffffffffffff831660009081526007602052604090206123cd9060020182612b52565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161240093929190613efd565b60405180910390a1505050565b8151156124d85781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612463575060408201516fffffffffffffffffffffffffffffffff16155b1561249c57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613f80565b80156124d4576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612511575060208201516fffffffffffffffffffffffffffffffff1615155b156124d457816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613f80565b6000611d268383612cf4565b3373ffffffffffffffffffffffffffffffffffffffff8216036125a5576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262381610afe565b612665576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127089190613cc8565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124d490600201827f0000000000000000000000000000000000000000000000000000000000000000612d43565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612a37565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612cf4565b7f000000000000000000000000000000000000000000000000000000000000000015611813576127fc6002826130c6565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61285381610afe565b612895576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561290e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129329190613fbc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124d490827f0000000000000000000000000000000000000000000000000000000000000000612d43565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b815481526020019060010190808311612a185750505050509050919050565b60008181526001830160205260408120548015612b20576000612a5b600183613eea565b8554909150600090612a6f90600190613eea565b9050808214612ad4576000866000018281548110612a8f57612a8f6137cf565b9060005260206000200154905080876000018481548110612ab257612ab26137cf565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ae557612ae5613fd9565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612b4985612b3a8486613eb0565b612b449087614008565b6130f5565b95945050505050565b8154600090612b7b90700100000000000000000000000000000000900463ffffffff1642613eea565b90508015612c1d5760018301548354612bc3916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b2a565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c43916fffffffffffffffffffffffffffffffff90811691166130f5565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612400908490613f80565b6000818152600183016020526040812054612d3b57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612d6a575081155b15612d7457505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612dba90700100000000000000000000000000000000900463ffffffff1642613eea565b90508015612e7a5781831115612dfc576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e369083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b2a565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f315773ffffffffffffffffffffffffffffffffffffffff8416612ed9576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b848310156130445760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f759082613eea565b612f7f878a613eea565b612f899190614008565b612f939190613e75565b905073ffffffffffffffffffffffffffffffffffffffff8616612fec576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b61304e8584613eea565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d26565b60008183106131045781611d26565b5090919050565b508054613117906137fe565b6000825580601f10613127575050565b601f016020900490600052602060002090810190611813919061315f565b508054600082559060005260206000209081019061181391905b5b808211156131745760008155600101613160565b5090565b60006020828403121561318a57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d2657600080fd5b6000815180845260005b818110156131e0576020818501810151868301820152016131c4565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d2660208301846131ba565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561326557600080fd5b8135611d2681613231565b60006020828403121561328257600080fd5b813567ffffffffffffffff81111561329957600080fd5b82016101008185031215611d2657600080fd5b803567ffffffffffffffff811681146132c457600080fd5b919050565b6000806000604084860312156132de57600080fd5b6132e7846132ac565b9250602084013567ffffffffffffffff8082111561330457600080fd5b818601915086601f83011261331857600080fd5b81358181111561332757600080fd5b87602082850101111561333957600080fd5b6020830194508093505050509250925092565b60008083601f84011261335e57600080fd5b50813567ffffffffffffffff81111561337657600080fd5b6020830191508360208260051b850101111561339157600080fd5b9250929050565b600080600080604085870312156133ae57600080fd5b843567ffffffffffffffff808211156133c657600080fd5b6133d28883890161334c565b909650945060208701359150808211156133eb57600080fd5b506133f88782880161334c565b95989497509550505050565b60006020828403121561341657600080fd5b611d26826132ac565b60006020828403121561343157600080fd5b813567ffffffffffffffff81111561344857600080fd5b820160a08185031215611d2657600080fd5b60208152600082516040602084015261347660608401826131ba565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4982826131ba565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613526577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526135148583516131ba565b945092850192908501906001016134da565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161354f565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358157835167ffffffffffffffff16835292840192918401916001016135a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613621576136216135cf565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561366e5761366e6135cf565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff811681146132c457600080fd5b6000606082840312156136b657600080fd5b6040516060810181811067ffffffffffffffff821117156136d9576136d96135cf565b60405290508082356136ea81613676565b81526136f860208401613684565b602082015261370960408401613684565b60408201525092915050565b600080600060e0848603121561372a57600080fd5b613733846132ac565b925061374285602086016136a4565b915061375185608086016136a4565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261378f57600080fd5b83018035915067ffffffffffffffff8211156137aa57600080fd5b60200191503681900382131561339157600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381257607f821691505b60208210810361384b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b49604083018486613851565b60208152600061088f602083018486613851565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390657600080fd5b9190910192915050565b600082601f83011261392157600080fd5b813567ffffffffffffffff81111561393b5761393b6135cf565b61396c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613627565b81815284602083860101111561398157600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b157600080fd5b6139b96135fe565b6139c2836132ac565b815260208084013567ffffffffffffffff808211156139e057600080fd5b9085019036601f8301126139f357600080fd5b813581811115613a0557613a056135cf565b8060051b613a14858201613627565b9182528381018501918581019036841115613a2e57600080fd5b86860192505b83831015613a6a57823585811115613a4c5760008081fd5b613a5a3689838a0101613910565b8352509186019190860190613a34565b8087890152505050506040860135925080831115613a8757600080fd5b5050613a9536828601613910565b604083015250613aa836606085016136a4565b6060820152613aba3660c085016136a4565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c81016020861015613aee5750805b601f850160051c820191505b81811015613b0d57828155600101613afa565b505050505050565b815167ffffffffffffffff811115613b2f57613b2f6135cf565b613b4381613b3d84546137fe565b84613ac5565b602080601f831160018114613b965760008415613b605750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b0d565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be357888601518255948401946001909101908401613bc4565b5085821015613c1f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c53818401876131ba565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c919050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b49565b600060208284031215613cda57600080fd5b8151611d2681613676565b600060208284031215613cf757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613cfe565b600181815b80851115613d9f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8557613d85613cfe565b80851615613d9257918102915b93841c9390800290613d4b565b509250929050565b600082613db657506001610678565b81613dc357506000610678565b8160018114613dd95760028114613de357613dff565b6001915050610678565b60ff841115613df457613df4613cfe565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613e22575081810a610678565b613e2c8383613d46565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e5e57613e5e613cfe565b029392505050565b6000611d2660ff841683613da7565b600082613eab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613cfe565b67ffffffffffffffff8316815260406020820152600061088f60408301846131ba565b8181038181111561067857610678613cfe565b67ffffffffffffffff8416815260e08101613f4960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fce57600080fd5b8151611d2681613231565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613cfe56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004a7c38038062004a7c8339810160408190526200003591620005a2565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001eb565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006c4565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db908462000265565b5050505050505050505062000730565b336001600160a01b038216036200021557604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000286576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000311576000838281518110620002aa57620002aa620006e2565b60209081029190910101519050620002c4600282620003c2565b1562000307576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000289565b5060005b8151811015620003bd576000828281518110620003365762000336620006e2565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003625750620003b4565b6200036f600282620003e2565b15620003b2576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000315565b505050565b6000620003d9836001600160a01b038416620003f9565b90505b92915050565b6000620003d9836001600160a01b038416620004fd565b60008181526001830160205260408120548015620004f257600062000420600183620006f8565b85549091506000906200043690600190620006f8565b9050808214620004a25760008660000182815481106200045a576200045a620006e2565b9060005260206000200154905080876000018481548110620004805762000480620006e2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004b657620004b66200071a565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003dc565b6000915050620003dc565b60008181526001830160205260408120546200054657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003dc565b506000620003dc565b6001600160a01b03811681146200056557600080fd5b50565b805160ff811681146200057a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b80516200057a816200054f565b600080600080600060a08688031215620005bb57600080fd5b8551620005c8816200054f565b94506020620005d987820162000568565b60408801519095506001600160401b0380821115620005f757600080fd5b818901915089601f8301126200060c57600080fd5b8151818111156200062157620006216200057f565b8060051b604051601f19603f830116810181811085821117156200064957620006496200057f565b60405291825284820192508381018501918c8311156200066857600080fd5b938501935b828510156200069157620006818562000595565b845293850193928501926200066d565b809850505050505050620006a86060870162000595565b9150620006b86080870162000595565b90509295509295909350565b600060208284031215620006d757600080fd5b620003d98262000568565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003dc57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161429b620007e16000396000818161056d01528181611efa0152612ae701526000818161054701528181611a1701526122d00152600081816102eb01528181610d2101528181611bc001528181611c7a01528181611cae01528181611ce101528181611d4601528181611d9f0152611e41015260008181610252015281816102a7015281816107260152818161244d015281816128db0152612cd2015261429b6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610545578063e0351e131461056b578063e8a1da1714610591578063f2fde38b146105a457600080fd5b8063c0d78655146104f7578063c4bffe2b1461050a578063c75eea9c1461051f578063cf7401f31461053257600080fd5b8063acfecf91116100de578063acfecf9114610444578063af58d59f14610457578063b0f479a1146104c6578063b7946580146104e457600080fd5b80639a4575b9146103ef578063a42a7b8b1461040f578063a7cd63b71461042f57600080fd5b806354c8a4f31161017c5780637d54534e1161014b5780637d54534e146103985780638926f54f146103ab5780638da5cb5b146103be578063962d4020146103dc57600080fd5b806354c8a4f31461034a57806362ddd3c41461035f5780636d3d1a581461037257806379ba50971461039057600080fd5b8063240028e8116101b8578063240028e81461029757806324f65ee7146102e457806339077537146103155780634c5ef0ed1461033757600080fd5b806301ffc9a7146101df578063181f5a771461020757806321df0da714610250575b600080fd5b6101f26101ed3660046132f0565b6105b7565b60405190151581526020015b60405180910390f35b6102436040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000081525081565b6040516101fe9190613396565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f26102a53660046133cb565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101fe565b6103286103233660046133e8565b61069c565b604051905181526020016101fe565b6101f2610345366004613441565b61086b565b61035d610358366004613510565b6108b5565b005b61035d61036d366004613441565b610930565b60095473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6109cd565b61035d6103a63660046133cb565b610a9b565b6101f26103b936600461357c565b610b1c565b60015473ffffffffffffffffffffffffffffffffffffffff16610272565b61035d6103ea3660046135dc565b610b33565b6104026103fd366004613676565b610c8d565b6040516101fe91906136b1565b61042261041d36600461357c565b610d66565b6040516101fe9190613708565b610437610ed1565b6040516101fe919061378a565b61035d610452366004613441565b610ee2565b61046a61046536600461357c565b610ffa565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610272565b6102436104f236600461357c565b6110cf565b61035d6105053660046133cb565b61117f565b61051261125a565b6040516101fe91906137e4565b61046a61052d36600461357c565b611312565b61035d61054036600461396c565b6113e4565b7f0000000000000000000000000000000000000000000000000000000000000000610272565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b61035d61059f366004613510565b611468565b61035d6105b23660046133cb565b61197a565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061064a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061069657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526106b48261198e565b600061070d60608401356107086106ce60c08701876139b1565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb292505050565b611c76565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961075b60608601604087016133cb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107c857600080fd5b505af11580156107dc573d6000803e3d6000fd5b506107f19250505060608401604085016133cb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161084f91815260200190565b60405180910390a3604080516020810190915290815292915050565b60006108ad8383604051610880929190613a16565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611e8a565b949350505050565b6108bd611ea5565b61092a84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ef892505050565b50505050565b610938611ea5565b61094183610b1c565b610988576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109c88383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506120ae92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a1e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610aa3611ea5565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610696600567ffffffffffffffff8416611e8a565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610b73575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610bac576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b8483141580610bbb5750848114155b15610bf2576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610c8457610c7c878783818110610c1257610c12613a26565b9050602002016020810190610c27919061357c565b868684818110610c3957610c39613a26565b905060600201803603810190610c4f9190613a55565b858585818110610c6157610c61613a26565b905060600201803603810190610c779190613a55565b6121a8565b600101610bf5565b50505050505050565b6040805180820190915260608082526020820152610caa82612292565b610cb7826060013561241e565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610d118460200160208101906104f2919061357c565b8152602001610d5e6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610d8f906005016124ba565b90506000815167ffffffffffffffff811115610dad57610dad613826565b604051908082528060200260200182016040528015610de057816020015b6060815260200190600190039081610dcb5790505b50905060005b8251811015610ec95760086000848381518110610e0557610e05613a26565b602002602001015181526020019081526020016000208054610e2690613a71565b80601f0160208091040260200160405190810160405280929190818152602001828054610e5290613a71565b8015610e9f5780601f10610e7457610100808354040283529160200191610e9f565b820191906000526020600020905b815481529060010190602001808311610e8257829003601f168201915b5050505050828281518110610eb657610eb6613a26565b6020908102919091010152600101610de6565b509392505050565b6060610edd60026124ba565b905090565b610eea611ea5565b610ef383610b1c565b610f35576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b610f758282604051610f48929190613a16565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906124c7565b610fb1578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161097f93929190613b0d565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610fed929190613b31565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526003909101548084166060830152919091049091166080820152610696906124d3565b67ffffffffffffffff811660009081526007602052604090206004018054606091906110fa90613a71565b80601f016020809104026020016040519081016040528092919081815260200182805461112690613a71565b80156111735780601f1061114857610100808354040283529160200191611173565b820191906000526020600020905b81548152906001019060200180831161115657829003601f168201915b50505050509050919050565b611187611ea5565b73ffffffffffffffffffffffffffffffffffffffff81166111d4576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061126860056124ba565b90506000815167ffffffffffffffff81111561128657611286613826565b6040519080825280602002602001820160405280156112af578160200160208202803683370190505b50905060005b825181101561130b578281815181106112d0576112d0613a26565b60200260200101518282815181106112ea576112ea613a26565b67ffffffffffffffff909216602092830291909101909101526001016112b5565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526001909101548084166060830152919091049091166080820152610696906124d3565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590611424575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561145d576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b6109c88383836121a8565b611470611ea5565b60005b8381101561165d57600085858381811061148f5761148f613a26565b90506020020160208101906114a4919061357c565b90506114bb600567ffffffffffffffff83166124c7565b6114fd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b67ffffffffffffffff81166000908152600760205260408120611522906005016124ba565b905060005b815181101561158e5761158582828151811061154557611545613a26565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016124c790919063ffffffff16565b50600101611527565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115f76004830182613283565b600582016000818161160982826132bd565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169450602001925061164b915050565b60405180910390a15050600101611473565b5060005b8181101561197357600083838381811061167d5761167d613a26565b905060200281019061168f9190613b45565b61169890613c11565b90506116a981606001516000612585565b6116b881608001516000612585565b8060400151516000036116f7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805161170f9060059067ffffffffffffffff166126c2565b6117545780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161097f565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906118d79082613d88565b5060005b82602001515181101561191b5761191383600001518460200151838151811061190657611906613a26565b60200260200101516120ae565b6001016118db565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516119619493929190613ea2565b60405180910390a15050600101611661565b5050505050565b611982611ea5565b61198b816126ce565b50565b6119a16102a560a08301608084016133cb565b611a00576119b560a08201608083016133cb565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161097f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611a4c604084016020850161357c565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae19190613f3b565b15611b18576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b30611b2b604083016020840161357c565b612792565b611b50611b43604083016020840161357c565b61034560a08401846139b1565b611b9557611b6160a08201826139b1565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161097f929190613b31565b61198b611ba8604083016020840161357c565b82606001356128b8565b60008151600003611be457507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611c2157816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f9190613396565b600082806020019051810190611c379190613f58565b905060ff81111561069657826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161097f9190613396565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611cac575081610696565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611d97576000611d067f000000000000000000000000000000000000000000000000000000000000000084613fa0565b9050604d8160ff161115611d7a576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611d8581600a6140d9565b611d8f90856140e8565b915050610696565b6000611dc3837f0000000000000000000000000000000000000000000000000000000000000000613fa0565b9050604d8160ff161180611e0a5750611ddd81600a6140d9565b611e07907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6140e8565b84115b15611e75576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161097f565b611e8081600a6140d9565b6108ad9085614123565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611ef6576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611f4f576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611fe5576000838281518110611f6f57611f6f613a26565b60200260200101519050611f8d8160026128ff90919063ffffffff16565b15611fdc5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f52565b5060005b81518110156109c857600082828151811061200657612006613a26565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361204a57506120a6565b612055600282612921565b156120a45760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611fe9565b80516000036120e9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061211b90600501826126c2565b6121555782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161097f92919061413a565b600081815260086020526040902061216d8382613d88565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610fed9190613396565b6121b183610b1c565b6121f3576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161097f565b6121fe826000612585565b67ffffffffffffffff831660009081526007602052604090206122219083612943565b61222c816000612585565b67ffffffffffffffff831660009081526007602052604090206122529060020182612943565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516122859392919061415d565b60405180910390a1505050565b6122a56102a560a08301608084016133cb565b6122b9576119b560a08201608083016133cb565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb612305604084016020850161357c565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612376573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239a9190613f3b565b156123d1576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e96123e460608301604084016133cb565b612ae5565b6124016123fc604083016020840161357c565b612b64565b61198b612414604083016020840161357c565b8260600135612cb2565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b1580156124a657600080fd5b505af1158015611973573d6000803e3d6000fd5b60606000611e9e83612cf6565b6000611e9e8383612d51565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261256182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261254591906141e0565b85608001516fffffffffffffffffffffffffffffffff16612e44565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b8151156126505781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806125db575060408201516fffffffffffffffffffffffffffffffff16155b1561261457816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161097f91906141f3565b801561264c576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612689575060208201516fffffffffffffffffffffffffffffffff1615155b1561264c57816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161097f91906141f3565b6000611e9e8383612e6c565b3373ffffffffffffffffffffffffffffffffffffffff82160361271d576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61279b81610b1c565b6127dd576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561285c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128809190613f3b565b61198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061264c90600201827f0000000000000000000000000000000000000000000000000000000000000000612ebb565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612d51565b6000611e9e8373ffffffffffffffffffffffffffffffffffffffff8416612e6c565b815460009061296c90700100000000000000000000000000000000900463ffffffff16426141e0565b90508015612a0e57600183015483546129b4916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612e44565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612a34916fffffffffffffffffffffffffffffffff908116911661323e565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906122859084906141f3565b7f00000000000000000000000000000000000000000000000000000000000000001561198b57612b16600282613254565b61198b576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161097f565b612b6d81610b1c565b612baf576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161097f565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4c919061422f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461198b576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161097f565b67ffffffffffffffff8216600090815260076020526040902061264c90827f0000000000000000000000000000000000000000000000000000000000000000612ebb565b60608160000180548060200260200160405190810160405280929190818152602001828054801561117357602002820191906000526020600020905b815481526020019060010190808311612d325750505050509050919050565b60008181526001830160205260408120548015612e3a576000612d756001836141e0565b8554909150600090612d89906001906141e0565b9050808214612dee576000866000018281548110612da957612da9613a26565b9060005260206000200154905080876000018481548110612dcc57612dcc613a26565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612dff57612dff61424c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610696565b6000915050610696565b6000612e6385612e548486614123565b612e5e908761427b565b61323e565b95945050505050565b6000818152600183016020526040812054612eb357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610696565b506000610696565b825474010000000000000000000000000000000000000000900460ff161580612ee2575081155b15612eec57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612f3290700100000000000000000000000000000000900463ffffffff16426141e0565b90508015612ff25781831115612f74576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612fae9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612e44565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156130a95773ffffffffffffffffffffffffffffffffffffffff8416613051576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161097f565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161097f565b848310156131bc5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906130ed90826141e0565b6130f7878a6141e0565b613101919061427b565b61310b91906140e8565b905073ffffffffffffffffffffffffffffffffffffffff8616613164576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161097f565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161097f565b6131c685846141e0565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600081831061324d5781611e9e565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611e9e565b50805461328f90613a71565b6000825580601f1061329f575050565b601f01602090049060005260206000209081019061198b91906132d7565b508054600082559060005260206000209081019061198b91905b5b808211156132ec57600081556001016132d8565b5090565b60006020828403121561330257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9e57600080fd5b6000815180845260005b818110156133585760208185018101518683018201520161333c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611e9e6020830184613332565b73ffffffffffffffffffffffffffffffffffffffff8116811461198b57600080fd5b6000602082840312156133dd57600080fd5b8135611e9e816133a9565b6000602082840312156133fa57600080fd5b813567ffffffffffffffff81111561341157600080fd5b82016101008185031215611e9e57600080fd5b803567ffffffffffffffff8116811461343c57600080fd5b919050565b60008060006040848603121561345657600080fd5b61345f84613424565b9250602084013567ffffffffffffffff8082111561347c57600080fd5b818601915086601f83011261349057600080fd5b81358181111561349f57600080fd5b8760208285010111156134b157600080fd5b6020830194508093505050509250925092565b60008083601f8401126134d657600080fd5b50813567ffffffffffffffff8111156134ee57600080fd5b6020830191508360208260051b850101111561350957600080fd5b9250929050565b6000806000806040858703121561352657600080fd5b843567ffffffffffffffff8082111561353e57600080fd5b61354a888389016134c4565b9096509450602087013591508082111561356357600080fd5b50613570878288016134c4565b95989497509550505050565b60006020828403121561358e57600080fd5b611e9e82613424565b60008083601f8401126135a957600080fd5b50813567ffffffffffffffff8111156135c157600080fd5b60208301915083602060608302850101111561350957600080fd5b600080600080600080606087890312156135f557600080fd5b863567ffffffffffffffff8082111561360d57600080fd5b6136198a838b016134c4565b9098509650602089013591508082111561363257600080fd5b61363e8a838b01613597565b9096509450604089013591508082111561365757600080fd5b5061366489828a01613597565b979a9699509497509295939492505050565b60006020828403121561368857600080fd5b813567ffffffffffffffff81111561369f57600080fd5b820160a08185031215611e9e57600080fd5b6020815260008251604060208401526136cd6060840182613332565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e638282613332565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561377d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261376b858351613332565b94509285019290850190600101613731565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d857835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016137a6565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d857835167ffffffffffffffff1683529284019291840191600101613800565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561387857613878613826565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c5576138c5613826565b604052919050565b801515811461198b57600080fd5b80356fffffffffffffffffffffffffffffffff8116811461343c57600080fd5b60006060828403121561390d57600080fd5b6040516060810181811067ffffffffffffffff8211171561393057613930613826565b6040529050808235613941816138cd565b815261394f602084016138db565b6020820152613960604084016138db565b60408201525092915050565b600080600060e0848603121561398157600080fd5b61398a84613424565b925061399985602086016138fb565b91506139a885608086016138fb565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139e657600080fd5b83018035915067ffffffffffffffff821115613a0157600080fd5b60200191503681900382131561350957600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608284031215613a6757600080fd5b611e9e83836138fb565b600181811c90821680613a8557607f821691505b602082108103613abe577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612e63604083018486613ac4565b6020815260006108ad602083018486613ac4565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1833603018112613b7957600080fd5b9190910192915050565b600082601f830112613b9457600080fd5b813567ffffffffffffffff811115613bae57613bae613826565b613bdf60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161387e565b818152846020838601011115613bf457600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215613c2457600080fd5b613c2c613855565b613c3583613424565b815260208084013567ffffffffffffffff80821115613c5357600080fd5b9085019036601f830112613c6657600080fd5b813581811115613c7857613c78613826565b8060051b613c8785820161387e565b9182528381018501918581019036841115613ca157600080fd5b86860192505b83831015613cdd57823585811115613cbf5760008081fd5b613ccd3689838a0101613b83565b8352509186019190860190613ca7565b8087890152505050506040860135925080831115613cfa57600080fd5b5050613d0836828601613b83565b604083015250613d1b36606085016138fb565b6060820152613d2d3660c085016138fb565b608082015292915050565b601f8211156109c8576000816000526020600020601f850160051c81016020861015613d615750805b601f850160051c820191505b81811015613d8057828155600101613d6d565b505050505050565b815167ffffffffffffffff811115613da257613da2613826565b613db681613db08454613a71565b84613d38565b602080601f831160018114613e095760008415613dd35750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613d80565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e5657888601518255948401946001909101908401613e37565b5085821015613e9257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ec681840187613332565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613f049050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e63565b600060208284031215613f4d57600080fd5b8151611e9e816138cd565b600060208284031215613f6a57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561069657610696613f71565b600181815b8085111561401257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613ff857613ff8613f71565b8085161561400557918102915b93841c9390800290613fbe565b509250929050565b60008261402957506001610696565b8161403657506000610696565b816001811461404c576002811461405657614072565b6001915050610696565b60ff84111561406757614067613f71565b50506001821b610696565b5060208310610133831016604e8410600b8410161715614095575081810a610696565b61409f8383613fb9565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156140d1576140d1613f71565b029392505050565b6000611e9e60ff84168361401a565b60008261411e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761069657610696613f71565b67ffffffffffffffff831681526040602082015260006108ad6040830184613332565b67ffffffffffffffff8416815260e081016141a960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526108ad565b8181038181111561069657610696613f71565b6060810161069682848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561424157600080fd5b8151611e9e816133a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561069657610696613f7156fea164736f6c6343000818000a", } var BurnMintTokenPoolABI = BurnMintTokenPoolMetaData.ABI @@ -713,6 +713,18 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetChainRateLimite return _BurnMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -3033,6 +3045,8 @@ type BurnMintTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go index 7315989c076..46f233948ce 100644 --- a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var BurnWithFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162004c5c38038062004c5c833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161402762000c356000396000818161054801528181611d7b01526127cc0152600081816105220152818161189801526120670152600081816102d901528181610ba201528181611a4101528181611afb01528181611b2f01528181611b6201528181611bc701528181611c200152611cc20152600081816102400152818161029501528181610701015281816121ea0152818161276201526129b701526140276000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610520578063e0351e1314610546578063e8a1da171461056c578063f2fde38b1461057f57600080fd5b8063c0d78655146104d2578063c4bffe2b146104e5578063c75eea9c146104fa578063cf7401f31461050d57600080fd5b8063acfecf91116100de578063acfecf911461041f578063af58d59f14610432578063b0f479a1146104a1578063b7946580146104bf57600080fd5b80639a4575b9146103ca578063a42a7b8b146103ea578063a7cd63b71461040a57600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba50971461037e5780637d54534e146103865780638926f54f146103995780638da5cb5b146103ac57600080fd5b806354c8a4f31461033857806362ddd3c41461034d5780636d3d1a581461036057600080fd5b8063240028e8116101ad578063240028e81461028557806324f65ee7146102d257806339077537146103035780634c5ef0ed1461032557600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da71461023e575b600080fd5b6101e76101e2366004613177565b610592565b60405190151581526020015b60405180910390f35b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e310060208201525b6040516101f3919061321d565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e7610293366004613252565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031661031136600461326f565b610677565b604051905181526020016101f3565b6101e76103333660046132c8565b610846565b61034b610346366004613397565b610890565b005b61034b61035b3660046132c8565b61090b565b60095473ffffffffffffffffffffffffffffffffffffffff16610260565b61034b6109a8565b61034b610394366004613252565b610a76565b6101e76103a7366004613403565b610af7565b60015473ffffffffffffffffffffffffffffffffffffffff16610260565b6103dd6103d836600461341e565b610b0e565b6040516101f39190613459565b6103fd6103f8366004613403565b610be7565b6040516101f391906134b0565b610412610d52565b6040516101f39190613532565b61034b61042d3660046132c8565b610d63565b610445610440366004613403565b610e7b565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610260565b6102316104cd366004613403565b610f50565b61034b6104e0366004613252565b611000565b6104ed6110db565b6040516101f3919061358c565b610445610508366004613403565b611193565b61034b61051b366004613714565b611265565b7f0000000000000000000000000000000000000000000000000000000000000000610260565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b61034b61057a366004613397565b6112e9565b61034b61058d366004613252565b6117fb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062557507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261068f8261180f565b60006106e860608401356106e36106a960c0870187613759565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3392505050565b611af7565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107366060860160408701613252565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107a357600080fd5b505af11580156107b7573d6000803e3d6000fd5b506107cc925050506060840160408501613252565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161082a91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610888838360405161085b9291906137be565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d0b565b949350505050565b610898611d26565b61090584848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d7992505050565b50505050565b610913611d26565b61091c83610af7565b610963576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109a38383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f2f92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109f9576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a7e611d26565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610671600567ffffffffffffffff8416611d0b565b6040805180820190915260608082526020820152610b2b82612029565b610b3882606001356121b5565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b928460200160208101906104cd9190613403565b8152602001610bdf6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1090600501612257565b90506000815167ffffffffffffffff811115610c2e57610c2e6135ce565b604051908082528060200260200182016040528015610c6157816020015b6060815260200190600190039081610c4c5790505b50905060005b8251811015610d4a5760086000848381518110610c8657610c866137ce565b602002602001015181526020019081526020016000208054610ca7906137fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd3906137fd565b8015610d205780601f10610cf557610100808354040283529160200191610d20565b820191906000526020600020905b815481529060010190602001808311610d0357829003601f168201915b5050505050828281518110610d3757610d376137ce565b6020908102919091010152600101610c67565b509392505050565b6060610d5e6002612257565b905090565b610d6b611d26565b610d7483610af7565b610db6576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b610df68282604051610dc99291906137be565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612264565b610e32578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161095a93929190613899565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e6e9291906138bd565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067190612270565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f7b906137fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610fa7906137fd565b8015610ff45780601f10610fc957610100808354040283529160200191610ff4565b820191906000526020600020905b815481529060010190602001808311610fd757829003601f168201915b50505050509050919050565b611008611d26565b73ffffffffffffffffffffffffffffffffffffffff8116611055576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110e96005612257565b90506000815167ffffffffffffffff811115611107576111076135ce565b604051908082528060200260200182016040528015611130578160200160208202803683370190505b50905060005b825181101561118c57828181518110611151576111516137ce565b602002602001015182828151811061116b5761116b6137ce565b67ffffffffffffffff90921660209283029190910190910152600101611136565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067190612270565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112a5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112de576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b6109a3838383612322565b6112f1611d26565b60005b838110156114de576000858583818110611310576113106137ce565b90506020020160208101906113259190613403565b905061133c600567ffffffffffffffff8316612264565b61137e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b67ffffffffffffffff811660009081526007602052604081206113a390600501612257565b905060005b815181101561140f576114068282815181106113c6576113c66137ce565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226490919063ffffffff16565b506001016113a8565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611478600483018261310a565b600582016000818161148a8282613144565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114cc915050565b60405180910390a150506001016112f4565b5060005b818110156117f45760008383838181106114fe576114fe6137ce565b905060200281019061151091906138d1565b6115199061399d565b905061152a8160600151600061240c565b6115398160800151600061240c565b806040015151600003611578576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115909060059067ffffffffffffffff16612549565b6115d55780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161095a565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906117589082613b14565b5060005b82602001515181101561179c57611794836000015184602001518381518110611787576117876137ce565b6020026020010151611f2f565b60010161175c565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e29493929190613c2e565b60405180910390a150506001016114e2565b5050505050565b611803611d26565b61180c81612555565b50565b61182261029360a0830160808401613252565b6118815761183660a0820160808301613252565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161095a565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118cd6040840160208501613403565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561193e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119629190613cc7565b15611999576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b16119ac6040830160208401613403565b612619565b6119d16119c46040830160208401613403565b61033360a0840184613759565b611a16576119e260a0820182613759565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161095a9291906138bd565b61180c611a296040830160208401613403565b826060013561273f565b60008151600003611a6557507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa257816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a919061321d565b600082806020019051810190611ab89190613ce4565b905060ff81111561067157826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a919061321d565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b2d575081610671565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c18576000611b877f000000000000000000000000000000000000000000000000000000000000000084613d2c565b9050604d8160ff161115611bfb576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161095a565b611c0681600a613e65565b611c109085613e74565b915050610671565b6000611c44837f0000000000000000000000000000000000000000000000000000000000000000613d2c565b9050604d8160ff161180611c8b5750611c5e81600a613e65565b611c88907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e74565b84115b15611cf6576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161095a565b611d0181600a613e65565b6108889085613eaf565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d77576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd0576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e66576000838281518110611df057611df06137ce565b60200260200101519050611e0e81600261278690919063ffffffff16565b15611e5d5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dd3565b5060005b81518110156109a3576000828281518110611e8757611e876137ce565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ecb5750611f27565b611ed66002826127a8565b15611f255760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e6a565b8051600003611f6a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611f9c9060050182612549565b611fd65782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161095a929190613ec6565b6000818152600860205260409020611fee8382613b14565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e6e919061321d565b61203c61029360a0830160808401613252565b6120505761183660a0820160808301613252565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61209c6040840160208501613403565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121319190613cc7565b15612168576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61218061217b6060830160408401613252565b6127ca565b6121986121936040830160208401613403565b612849565b61180c6121ab6040830160208401613403565b8260600135612997565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b15801561224357600080fd5b505af11580156117f4573d6000803e3d6000fd5b60606000611d1f836129db565b6000611d1f8383612a36565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526122fe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e29190613ee9565b85608001516fffffffffffffffffffffffffffffffff16612b29565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61232b83610af7565b61236d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b61237882600061240c565b67ffffffffffffffff8316600090815260076020526040902061239b9083612b51565b6123a681600061240c565b67ffffffffffffffff831660009081526007602052604090206123cc9060020182612b51565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516123ff93929190613efc565b60405180910390a1505050565b8151156124d75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612462575060408201516fffffffffffffffffffffffffffffffff16155b1561249b57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161095a9190613f7f565b80156124d3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612510575060208201516fffffffffffffffffffffffffffffffff1615155b156124d357816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161095a9190613f7f565b6000611d1f8383612cf3565b3373ffffffffffffffffffffffffffffffffffffffff8216036125a4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262281610af7565b612664576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127079190613cc7565b61180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206124d390600201827f0000000000000000000000000000000000000000000000000000000000000000612d42565b6000611d1f8373ffffffffffffffffffffffffffffffffffffffff8416612a36565b6000611d1f8373ffffffffffffffffffffffffffffffffffffffff8416612cf3565b7f00000000000000000000000000000000000000000000000000000000000000001561180c576127fb6002826130c5565b61180c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161095a565b61285281610af7565b612894576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561290d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129319190613fbb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206124d390827f0000000000000000000000000000000000000000000000000000000000000000612d42565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ff457602002820191906000526020600020905b815481526020019060010190808311612a175750505050509050919050565b60008181526001830160205260408120548015612b1f576000612a5a600183613ee9565b8554909150600090612a6e90600190613ee9565b9050808214612ad3576000866000018281548110612a8e57612a8e6137ce565b9060005260206000200154905080876000018481548110612ab157612ab16137ce565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ae457612ae4613fd8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610671565b6000915050610671565b6000612b4885612b398486613eaf565b612b439087614007565b6130f4565b95945050505050565b8154600090612b7a90700100000000000000000000000000000000900463ffffffff1642613ee9565b90508015612c1c5760018301548354612bc2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b29565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c42916fffffffffffffffffffffffffffffffff90811691166130f4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906123ff908490613f7f565b6000818152600183016020526040812054612d3a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610671565b506000610671565b825474010000000000000000000000000000000000000000900460ff161580612d69575081155b15612d7357505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612db990700100000000000000000000000000000000900463ffffffff1642613ee9565b90508015612e795781831115612dfb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e359083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b29565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f305773ffffffffffffffffffffffffffffffffffffffff8416612ed8576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161095a565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161095a565b848310156130435760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f749082613ee9565b612f7e878a613ee9565b612f889190614007565b612f929190613e74565b905073ffffffffffffffffffffffffffffffffffffffff8616612feb576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161095a565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161095a565b61304d8584613ee9565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d1f565b60008183106131035781611d1f565b5090919050565b508054613116906137fd565b6000825580601f10613126575050565b601f01602090049060005260206000209081019061180c919061315e565b508054600082559060005260206000209081019061180c91905b5b80821115613173576000815560010161315f565b5090565b60006020828403121561318957600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d1f57600080fd5b6000815180845260005b818110156131df576020818501810151868301820152016131c3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d1f60208301846131b9565b73ffffffffffffffffffffffffffffffffffffffff8116811461180c57600080fd5b60006020828403121561326457600080fd5b8135611d1f81613230565b60006020828403121561328157600080fd5b813567ffffffffffffffff81111561329857600080fd5b82016101008185031215611d1f57600080fd5b803567ffffffffffffffff811681146132c357600080fd5b919050565b6000806000604084860312156132dd57600080fd5b6132e6846132ab565b9250602084013567ffffffffffffffff8082111561330357600080fd5b818601915086601f83011261331757600080fd5b81358181111561332657600080fd5b87602082850101111561333857600080fd5b6020830194508093505050509250925092565b60008083601f84011261335d57600080fd5b50813567ffffffffffffffff81111561337557600080fd5b6020830191508360208260051b850101111561339057600080fd5b9250929050565b600080600080604085870312156133ad57600080fd5b843567ffffffffffffffff808211156133c557600080fd5b6133d18883890161334b565b909650945060208701359150808211156133ea57600080fd5b506133f78782880161334b565b95989497509550505050565b60006020828403121561341557600080fd5b611d1f826132ab565b60006020828403121561343057600080fd5b813567ffffffffffffffff81111561344757600080fd5b820160a08185031215611d1f57600080fd5b60208152600082516040602084015261347560608401826131b9565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4882826131b9565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613525577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526135138583516131b9565b945092850192908501906001016134d9565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161354e565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358057835167ffffffffffffffff16835292840192918401916001016135a8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613620576136206135ce565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561366d5761366d6135ce565b604052919050565b801515811461180c57600080fd5b80356fffffffffffffffffffffffffffffffff811681146132c357600080fd5b6000606082840312156136b557600080fd5b6040516060810181811067ffffffffffffffff821117156136d8576136d86135ce565b60405290508082356136e981613675565b81526136f760208401613683565b602082015261370860408401613683565b60408201525092915050565b600080600060e0848603121561372957600080fd5b613732846132ab565b925061374185602086016136a3565b915061375085608086016136a3565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261378e57600080fd5b83018035915067ffffffffffffffff8211156137a957600080fd5b60200191503681900382131561339057600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381157607f821691505b60208210810361384a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b48604083018486613850565b602081526000610888602083018486613850565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390557600080fd5b9190910192915050565b600082601f83011261392057600080fd5b813567ffffffffffffffff81111561393a5761393a6135ce565b61396b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613626565b81815284602083860101111561398057600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b057600080fd5b6139b86135fd565b6139c1836132ab565b815260208084013567ffffffffffffffff808211156139df57600080fd5b9085019036601f8301126139f257600080fd5b813581811115613a0457613a046135ce565b8060051b613a13858201613626565b9182528381018501918581019036841115613a2d57600080fd5b86860192505b83831015613a6957823585811115613a4b5760008081fd5b613a593689838a010161390f565b8352509186019190860190613a33565b8087890152505050506040860135925080831115613a8657600080fd5b5050613a943682860161390f565b604083015250613aa736606085016136a3565b6060820152613ab93660c085016136a3565b608082015292915050565b601f8211156109a3576000816000526020600020601f850160051c81016020861015613aed5750805b601f850160051c820191505b81811015613b0c57828155600101613af9565b505050505050565b815167ffffffffffffffff811115613b2e57613b2e6135ce565b613b4281613b3c84546137fd565b84613ac4565b602080601f831160018114613b955760008415613b5f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b0c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be257888601518255948401946001909101908401613bc3565b5085821015613c1e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c52818401876131b9565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c909050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b48565b600060208284031215613cd957600080fd5b8151611d1f81613675565b600060208284031215613cf657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067157610671613cfd565b600181815b80851115613d9e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8457613d84613cfd565b80851615613d9157918102915b93841c9390800290613d4a565b509250929050565b600082613db557506001610671565b81613dc257506000610671565b8160018114613dd85760028114613de257613dfe565b6001915050610671565b60ff841115613df357613df3613cfd565b50506001821b610671565b5060208310610133831016604e8410600b8410161715613e21575081810a610671565b613e2b8383613d45565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e5d57613e5d613cfd565b029392505050565b6000611d1f60ff841683613da6565b600082613eaa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067157610671613cfd565b67ffffffffffffffff8316815260406020820152600061088860408301846131b9565b8181038181111561067157610671613cfd565b67ffffffffffffffff8416815260e08101613f4860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610888565b6060810161067182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fcd57600080fd5b8151611d1f81613230565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067157610671613cfd56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004ecf38038062004ecf833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161429a62000c356000396000818161056601528181611ef30152612ae601526000818161054001528181611a1001526122c90152600081816102e401528181610d1a01528181611bb901528181611c7301528181611ca701528181611cda01528181611d3f01528181611d980152611e3a01526000818161024b015281816102a00152818161071f0152818161244c015281816128da0152612cd1015261429a6000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd9711461053e578063e0351e1314610564578063e8a1da171461058a578063f2fde38b1461059d57600080fd5b8063c0d78655146104f0578063c4bffe2b14610503578063c75eea9c14610518578063cf7401f31461052b57600080fd5b8063acfecf91116100de578063acfecf911461043d578063af58d59f14610450578063b0f479a1146104bf578063b7946580146104dd57600080fd5b80639a4575b9146103e8578063a42a7b8b14610408578063a7cd63b71461042857600080fd5b806354c8a4f31161017c5780637d54534e1161014b5780637d54534e146103915780638926f54f146103a45780638da5cb5b146103b7578063962d4020146103d557600080fd5b806354c8a4f31461034357806362ddd3c4146103585780636d3d1a581461036b57806379ba50971461038957600080fd5b8063240028e8116101b8578063240028e81461029057806324f65ee7146102dd578063390775371461030e5780634c5ef0ed1461033057600080fd5b806301ffc9a7146101df578063181f5a771461020757806321df0da714610249575b600080fd5b6101f26101ed3660046132ef565b6105b0565b60405190151581526020015b60405180910390f35b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e310060208201525b6040516101fe9190613395565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fe565b6101f261029e3660046133ca565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101fe565b61032161031c3660046133e7565b610695565b604051905181526020016101fe565b6101f261033e366004613440565b610864565b61035661035136600461350f565b6108ae565b005b610356610366366004613440565b610929565b60095473ffffffffffffffffffffffffffffffffffffffff1661026b565b6103566109c6565b61035661039f3660046133ca565b610a94565b6101f26103b236600461357b565b610b15565b60015473ffffffffffffffffffffffffffffffffffffffff1661026b565b6103566103e33660046135db565b610b2c565b6103fb6103f6366004613675565b610c86565b6040516101fe91906136b0565b61041b61041636600461357b565b610d5f565b6040516101fe9190613707565b610430610eca565b6040516101fe9190613789565b61035661044b366004613440565b610edb565b61046361045e36600461357b565b610ff3565b6040516101fe919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff1661026b565b61023c6104eb36600461357b565b6110c8565b6103566104fe3660046133ca565b611178565b61050b611253565b6040516101fe91906137e3565b61046361052636600461357b565b61130b565b61035661053936600461396b565b6113dd565b7f000000000000000000000000000000000000000000000000000000000000000061026b565b7f00000000000000000000000000000000000000000000000000000000000000006101f2565b61035661059836600461350f565b611461565b6103566105ab3660046133ca565b611973565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061064357507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061068f57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526106ad82611987565b600061070660608401356107016106c760c08701876139b0565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bab92505050565b611c6f565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961075460608601604087016133ca565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107c157600080fd5b505af11580156107d5573d6000803e3d6000fd5b506107ea9250505060608401604085016133ca565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161084891815260200190565b60405180910390a3604080516020810190915290815292915050565b60006108a68383604051610879929190613a15565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611e83565b949350505050565b6108b6611e9e565b61092384848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611ef192505050565b50505050565b610931611e9e565b61093a83610b15565b610981576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109c18383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506120a792505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a17576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a9c611e9e565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b600061068f600567ffffffffffffffff8416611e83565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610b6c575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610ba5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b8483141580610bb45750848114155b15610beb576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610c7d57610c75878783818110610c0b57610c0b613a25565b9050602002016020810190610c20919061357b565b868684818110610c3257610c32613a25565b905060600201803603810190610c489190613a54565b858585818110610c5a57610c5a613a25565b905060600201803603810190610c709190613a54565b6121a1565b600101610bee565b50505050505050565b6040805180820190915260608082526020820152610ca38261228b565b610cb08260600135612417565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610d0a8460200160208101906104eb919061357b565b8152602001610d576040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610d88906005016124b9565b90506000815167ffffffffffffffff811115610da657610da6613825565b604051908082528060200260200182016040528015610dd957816020015b6060815260200190600190039081610dc45790505b50905060005b8251811015610ec25760086000848381518110610dfe57610dfe613a25565b602002602001015181526020019081526020016000208054610e1f90613a70565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4b90613a70565b8015610e985780601f10610e6d57610100808354040283529160200191610e98565b820191906000526020600020905b815481529060010190602001808311610e7b57829003601f168201915b5050505050828281518110610eaf57610eaf613a25565b6020908102919091010152600101610ddf565b509392505050565b6060610ed660026124b9565b905090565b610ee3611e9e565b610eec83610b15565b610f2e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610978565b610f6e8282604051610f41929190613a15565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906124c6565b610faa578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161097893929190613b0c565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610fe6929190613b30565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261068f906124d2565b67ffffffffffffffff811660009081526007602052604090206004018054606091906110f390613a70565b80601f016020809104026020016040519081016040528092919081815260200182805461111f90613a70565b801561116c5780601f106111415761010080835404028352916020019161116c565b820191906000526020600020905b81548152906001019060200180831161114f57829003601f168201915b50505050509050919050565b611180611e9e565b73ffffffffffffffffffffffffffffffffffffffff81166111cd576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061126160056124b9565b90506000815167ffffffffffffffff81111561127f5761127f613825565b6040519080825280602002602001820160405280156112a8578160200160208202803683370190505b50905060005b8251811015611304578281815181106112c9576112c9613a25565b60200260200101518282815181106112e3576112e3613a25565b67ffffffffffffffff909216602092830291909101909101526001016112ae565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261068f906124d2565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061141d575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15611456576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b6109c18383836121a1565b611469611e9e565b60005b8381101561165657600085858381811061148857611488613a25565b905060200201602081019061149d919061357b565b90506114b4600567ffffffffffffffff83166124c6565b6114f6576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610978565b67ffffffffffffffff8116600090815260076020526040812061151b906005016124b9565b905060005b81518110156115875761157e82828151811061153e5761153e613a25565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016124c690919063ffffffff16565b50600101611520565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906115f06004830182613282565b600582016000818161160282826132bc565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611644915050565b60405180910390a1505060010161146c565b5060005b8181101561196c57600083838381811061167657611676613a25565b90506020028101906116889190613b44565b61169190613c10565b90506116a281606001516000612584565b6116b181608001516000612584565b8060400151516000036116f0576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516117089060059067ffffffffffffffff166126c1565b61174d5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610978565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906118d09082613d87565b5060005b8260200151518110156119145761190c8360000151846020015183815181106118ff576118ff613a25565b60200260200101516120a7565b6001016118d4565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2826000015183604001518460600151856080015160405161195a9493929190613ea1565b60405180910390a1505060010161165a565b5050505050565b61197b611e9e565b611984816126cd565b50565b61199a61029e60a08301608084016133ca565b6119f9576119ae60a08201608083016133ca565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610978565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611a45604084016020850161357b565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ada9190613f3a565b15611b11576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b29611b24604083016020840161357b565b612791565b611b49611b3c604083016020840161357b565b61033e60a08401846139b0565b611b8e57611b5a60a08201826139b0565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610978929190613b30565b611984611ba1604083016020840161357b565b82606001356128b7565b60008151600003611bdd57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611c1a57816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109789190613395565b600082806020019051810190611c309190613f57565b905060ff81111561068f57826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109789190613395565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611ca557508161068f565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611d90576000611cff7f000000000000000000000000000000000000000000000000000000000000000084613f9f565b9050604d8160ff161115611d73576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610978565b611d7e81600a6140d8565b611d8890856140e7565b91505061068f565b6000611dbc837f0000000000000000000000000000000000000000000000000000000000000000613f9f565b9050604d8160ff161180611e035750611dd681600a6140d8565b611e00907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6140e7565b84115b15611e6e576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610978565b611e7981600a6140d8565b6108a69085614122565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611eef576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611f48576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611fde576000838281518110611f6857611f68613a25565b60200260200101519050611f868160026128fe90919063ffffffff16565b15611fd55760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f4b565b5060005b81518110156109c1576000828281518110611fff57611fff613a25565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612043575061209f565b61204e600282612920565b1561209d5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611fe2565b80516000036120e2576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061211490600501826126c1565b61214e5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610978929190614139565b60008181526008602052604090206121668382613d87565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610fe69190613395565b6121aa83610b15565b6121ec576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610978565b6121f7826000612584565b67ffffffffffffffff8316600090815260076020526040902061221a9083612942565b612225816000612584565b67ffffffffffffffff8316600090815260076020526040902061224b9060020182612942565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161227e9392919061415c565b60405180910390a1505050565b61229e61029e60a08301608084016133ca565b6122b2576119ae60a08201608083016133ca565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6122fe604084016020850161357b565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561236f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123939190613f3a565b156123ca576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e26123dd60608301604084016133ca565b612ae4565b6123fa6123f5604083016020840161357b565b612b63565b61198461240d604083016020840161357b565b8260600135612cb1565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b1580156124a557600080fd5b505af115801561196c573d6000803e3d6000fd5b60606000611e9783612cf5565b6000611e978383612d50565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261256082606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261254491906141df565b85608001516fffffffffffffffffffffffffffffffff16612e43565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b81511561264f5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806125da575060408201516fffffffffffffffffffffffffffffffff16155b1561261357816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161097891906141f2565b801561264b576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612688575060208201516fffffffffffffffffffffffffffffffff1615155b1561264b57816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161097891906141f2565b6000611e978383612e6b565b3373ffffffffffffffffffffffffffffffffffffffff82160361271c576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61279a81610b15565b6127dc576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610978565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561285b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287f9190613f3a565b611984576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b67ffffffffffffffff8216600090815260076020526040902061264b90600201827f0000000000000000000000000000000000000000000000000000000000000000612eba565b6000611e978373ffffffffffffffffffffffffffffffffffffffff8416612d50565b6000611e978373ffffffffffffffffffffffffffffffffffffffff8416612e6b565b815460009061296b90700100000000000000000000000000000000900463ffffffff16426141df565b90508015612a0d57600183015483546129b3916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612e43565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612a33916fffffffffffffffffffffffffffffffff908116911661323d565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061227e9084906141f2565b7f00000000000000000000000000000000000000000000000000000000000000001561198457612b15600282613253565b611984576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610978565b612b6c81610b15565b612bae576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610978565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4b919061422e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611984576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610978565b67ffffffffffffffff8216600090815260076020526040902061264b90827f0000000000000000000000000000000000000000000000000000000000000000612eba565b60608160000180548060200260200160405190810160405280929190818152602001828054801561116c57602002820191906000526020600020905b815481526020019060010190808311612d315750505050509050919050565b60008181526001830160205260408120548015612e39576000612d746001836141df565b8554909150600090612d88906001906141df565b9050808214612ded576000866000018281548110612da857612da8613a25565b9060005260206000200154905080876000018481548110612dcb57612dcb613a25565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612dfe57612dfe61424b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061068f565b600091505061068f565b6000612e6285612e538486614122565b612e5d908761427a565b61323d565b95945050505050565b6000818152600183016020526040812054612eb25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561068f565b50600061068f565b825474010000000000000000000000000000000000000000900460ff161580612ee1575081155b15612eeb57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612f3190700100000000000000000000000000000000900463ffffffff16426141df565b90508015612ff15781831115612f73576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612fad9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612e43565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156130a85773ffffffffffffffffffffffffffffffffffffffff8416613050576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610978565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610978565b848310156131bb5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906130ec90826141df565b6130f6878a6141df565b613100919061427a565b61310a91906140e7565b905073ffffffffffffffffffffffffffffffffffffffff8616613163576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610978565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610978565b6131c585846141df565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600081831061324c5781611e97565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611e97565b50805461328e90613a70565b6000825580601f1061329e575050565b601f01602090049060005260206000209081019061198491906132d6565b508054600082559060005260206000209081019061198491905b5b808211156132eb57600081556001016132d7565b5090565b60006020828403121561330157600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9757600080fd5b6000815180845260005b818110156133575760208185018101518683018201520161333b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611e976020830184613331565b73ffffffffffffffffffffffffffffffffffffffff8116811461198457600080fd5b6000602082840312156133dc57600080fd5b8135611e97816133a8565b6000602082840312156133f957600080fd5b813567ffffffffffffffff81111561341057600080fd5b82016101008185031215611e9757600080fd5b803567ffffffffffffffff8116811461343b57600080fd5b919050565b60008060006040848603121561345557600080fd5b61345e84613423565b9250602084013567ffffffffffffffff8082111561347b57600080fd5b818601915086601f83011261348f57600080fd5b81358181111561349e57600080fd5b8760208285010111156134b057600080fd5b6020830194508093505050509250925092565b60008083601f8401126134d557600080fd5b50813567ffffffffffffffff8111156134ed57600080fd5b6020830191508360208260051b850101111561350857600080fd5b9250929050565b6000806000806040858703121561352557600080fd5b843567ffffffffffffffff8082111561353d57600080fd5b613549888389016134c3565b9096509450602087013591508082111561356257600080fd5b5061356f878288016134c3565b95989497509550505050565b60006020828403121561358d57600080fd5b611e9782613423565b60008083601f8401126135a857600080fd5b50813567ffffffffffffffff8111156135c057600080fd5b60208301915083602060608302850101111561350857600080fd5b600080600080600080606087890312156135f457600080fd5b863567ffffffffffffffff8082111561360c57600080fd5b6136188a838b016134c3565b9098509650602089013591508082111561363157600080fd5b61363d8a838b01613596565b9096509450604089013591508082111561365657600080fd5b5061366389828a01613596565b979a9699509497509295939492505050565b60006020828403121561368757600080fd5b813567ffffffffffffffff81111561369e57600080fd5b820160a08185031215611e9757600080fd5b6020815260008251604060208401526136cc6060840182613331565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e628282613331565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561377c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261376a858351613331565b94509285019290850190600101613730565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d757835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016137a5565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156137d757835167ffffffffffffffff16835292840192918401916001016137ff565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561387757613877613825565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c4576138c4613825565b604052919050565b801515811461198457600080fd5b80356fffffffffffffffffffffffffffffffff8116811461343b57600080fd5b60006060828403121561390c57600080fd5b6040516060810181811067ffffffffffffffff8211171561392f5761392f613825565b6040529050808235613940816138cc565b815261394e602084016138da565b602082015261395f604084016138da565b60408201525092915050565b600080600060e0848603121561398057600080fd5b61398984613423565b925061399885602086016138fa565b91506139a785608086016138fa565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139e557600080fd5b83018035915067ffffffffffffffff821115613a0057600080fd5b60200191503681900382131561350857600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608284031215613a6657600080fd5b611e9783836138fa565b600181811c90821680613a8457607f821691505b602082108103613abd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612e62604083018486613ac3565b6020815260006108a6602083018486613ac3565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1833603018112613b7857600080fd5b9190910192915050565b600082601f830112613b9357600080fd5b813567ffffffffffffffff811115613bad57613bad613825565b613bde60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161387d565b818152846020838601011115613bf357600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215613c2357600080fd5b613c2b613854565b613c3483613423565b815260208084013567ffffffffffffffff80821115613c5257600080fd5b9085019036601f830112613c6557600080fd5b813581811115613c7757613c77613825565b8060051b613c8685820161387d565b9182528381018501918581019036841115613ca057600080fd5b86860192505b83831015613cdc57823585811115613cbe5760008081fd5b613ccc3689838a0101613b82565b8352509186019190860190613ca6565b8087890152505050506040860135925080831115613cf957600080fd5b5050613d0736828601613b82565b604083015250613d1a36606085016138fa565b6060820152613d2c3660c085016138fa565b608082015292915050565b601f8211156109c1576000816000526020600020601f850160051c81016020861015613d605750805b601f850160051c820191505b81811015613d7f57828155600101613d6c565b505050505050565b815167ffffffffffffffff811115613da157613da1613825565b613db581613daf8454613a70565b84613d37565b602080601f831160018114613e085760008415613dd25750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613d7f565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613e5557888601518255948401946001909101908401613e36565b5085821015613e9157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613ec581840187613331565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613f039050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e62565b600060208284031215613f4c57600080fd5b8151611e97816138cc565b600060208284031215613f6957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561068f5761068f613f70565b600181815b8085111561401157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613ff757613ff7613f70565b8085161561400457918102915b93841c9390800290613fbd565b509250929050565b6000826140285750600161068f565b816140355750600061068f565b816001811461404b576002811461405557614071565b600191505061068f565b60ff84111561406657614066613f70565b50506001821b61068f565b5060208310610133831016604e8410600b8410161715614094575081810a61068f565b61409e8383613fb8565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156140d0576140d0613f70565b029392505050565b6000611e9760ff841683614019565b60008261411d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761068f5761068f613f70565b67ffffffffffffffff831681526040602082015260006108a66040830184613331565b67ffffffffffffffff8416815260e081016141a860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526108a6565b8181038181111561068f5761068f613f70565b6060810161068f82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561424057600080fd5b8151611e97816133a8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561068f5761068f613f7056fea164736f6c6343000818000a", } var BurnWithFromMintTokenPoolABI = BurnWithFromMintTokenPoolMetaData.ABI @@ -713,6 +713,18 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Se return _BurnWithFromMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -3033,6 +3045,8 @@ type BurnWithFromMintTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go index 32edf6ef6c3..fa5a6a4cdac 100644 --- a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go +++ b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go @@ -81,8 +81,8 @@ type TokenPoolChainUpdate struct { } var LockReleaseTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b506040516200511f3803806200511f8339810160408190526200003591620005bb565b8585858584336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001f3565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006ee565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db90846200026d565b5050505091151561010052506200075a945050505050565b336001600160a01b038216036200021d57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200028e576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000319576000838281518110620002b257620002b26200070c565b60209081029190910101519050620002cc600282620003ca565b156200030f576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000291565b5060005b8151811015620003c55760008282815181106200033e576200033e6200070c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200036a5750620003bc565b62000377600282620003ea565b15620003ba576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200031d565b505050565b6000620003e1836001600160a01b03841662000401565b90505b92915050565b6000620003e1836001600160a01b03841662000505565b60008181526001830160205260408120548015620004fa5760006200042860018362000722565b85549091506000906200043e9060019062000722565b9050808214620004aa5760008660000182815481106200046257620004626200070c565b90600052602060002001549050808760000184815481106200048857620004886200070c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004be57620004be62000744565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003e4565b6000915050620003e4565b60008181526001830160205260408120546200054e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003e4565b506000620003e4565b6001600160a01b03811681146200056d57600080fd5b50565b805160ff811681146200058257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620005828162000557565b805180151581146200058257600080fd5b60008060008060008060c08789031215620005d557600080fd5b8651620005e28162000557565b95506020620005f388820162000570565b60408901519096506001600160401b03808211156200061157600080fd5b818a0191508a601f8301126200062657600080fd5b8151818111156200063b576200063b62000587565b8060051b604051601f19603f8301168101818110858211171562000663576200066362000587565b60405291825284820192508381018501918d8311156200068257600080fd5b938501935b82851015620006ab576200069b856200059d565b8452938501939285019262000687565b809950505050505050620006c2606088016200059d565b9250620006d260808801620005aa565b9150620006e260a088016200059d565b90509295509295509295565b6000602082840312156200070157600080fd5b620003e18262000570565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003e457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051610100516148f46200082b600039600081816105a40152611ac601526000818161063e015281816123180152612e3101526000818161061801528181611e35015261260401526000818161036701528181610e6b01528181611fde01528181612098015281816120cc015281816120ff01528181612164015281816121bd015261225f0152600081816102ce015281816103230152818161077f015281816108510152818161094501528181611b8801528181612dc7015261301c01526148f46000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80638da5cb5b11610145578063c0d78655116100bd578063dc0bd9711161008c578063e8a1da1711610071578063e8a1da1714610662578063eb521a4c14610675578063f2fde38b1461068857600080fd5b8063dc0bd97114610616578063e0351e131461063c57600080fd5b8063c0d78655146105c8578063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f31461060357600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610571578063b79465801461058f578063bb98546b146105a257600080fd5b8063acfecf91146104ef578063af58d59f1461050257600080fd5b80638da5cb5b1461047c5780639a4575b91461049a578063a42a7b8b146104ba578063a7cd63b7146104da57600080fd5b80634c5ef0ed116101d85780636cfd1553116101a757806379ba50971161018c57806379ba50971461044e5780637d54534e146104565780638926f54f1461046957600080fd5b80636cfd15531461041d5780636d3d1a581461043057600080fd5b80634c5ef0ed146103d157806354c8a4f3146103e457806362ddd3c4146103f7578063663200871461040a57600080fd5b8063240028e811610214578063240028e81461031357806324f65ee7146103605780633907753714610391578063432a6ba3146103b357600080fd5b806301ffc9a7146102465780630a861f2a1461026e578063181f5a771461028357806321df0da7146102cc575b600080fd5b6102596102543660046139e3565b61069b565b60405190151581526020015b60405180910390f35b61028161027c366004613a25565b6106f7565b005b6102bf6040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3100000000000081525081565b6040516102659190613aac565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610265565b610259610321366004613ae1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610265565b6103a461039f366004613afe565b6108a8565b60405190518152602001610265565b600a5473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102596103df366004613b57565b6109f6565b6102816103f2366004613c26565b610a40565b610281610405366004613b57565b610abb565b610281610418366004613c92565b610b53565b61028161042b366004613ae1565b610c2f565b60095473ffffffffffffffffffffffffffffffffffffffff166102ee565b610281610c7e565b610281610464366004613ae1565b610d4c565b610259610477366004613cbe565b610dcd565b60015473ffffffffffffffffffffffffffffffffffffffff166102ee565b6104ad6104a8366004613cd9565b610de4565b6040516102659190613d14565b6104cd6104c8366004613cbe565b610eb0565b6040516102659190613d6b565b6104e261101b565b6040516102659190613ded565b6102816104fd366004613b57565b61102c565b610515610510366004613cbe565b611144565b604051610265919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102bf61059d366004613cbe565b611219565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b6102816105d6366004613ae1565b6112c9565b6105e36113a4565b6040516102659190613e47565b6105156105fe366004613cbe565b61145c565b610281610611366004613fcf565b61152e565b7f00000000000000000000000000000000000000000000000000000000000000006102ee565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b610281610670366004613c26565b6115b2565b610281610683366004613a25565b611ac4565b610281610696366004613ae1565b611be0565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d405660000000000000000000000000000000000000000000000000000000014806106f157506106f182611bf4565b92915050565b600a5473ffffffffffffffffffffffffffffffffffffffff16331461074f576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ff9190614014565b1015610837576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611cd8565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108c082611dac565b600061091960608401356109146108da60c087018761402d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fd092505050565b612094565b905061096c61092e6060850160408601613ae1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169083611cd8565b61097c6060840160408501613ae1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52836040516109da91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610a388383604051610a0b929190614092565b604080519182900390912067ffffffffffffffff87166000908152600760205291909120600501906122a8565b949350505050565b610a486122c3565b610ab58484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061231692505050565b50505050565b610ac36122c3565b610acc83610dcd565b610b0e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b610b4e8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124cc92505050565b505050565b610b5b6122c3565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610c2391815260200190565b60405180910390a25050565b610c376122c3565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ccf576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d546122c3565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006106f1600567ffffffffffffffff84166122a8565b6040805180820190915260608082526020820152610e01826125c6565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610e5b84602001602081019061059d9190613cbe565b8152602001610ea86040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610ed990600501612752565b90506000815167ffffffffffffffff811115610ef757610ef7613e89565b604051908082528060200260200182016040528015610f2a57816020015b6060815260200190600190039081610f155790505b50905060005b82518110156110135760086000848381518110610f4f57610f4f6140a2565b602002602001015181526020019081526020016000208054610f70906140d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9c906140d1565b8015610fe95780601f10610fbe57610100808354040283529160200191610fe9565b820191906000526020600020905b815481529060010190602001808311610fcc57829003601f168201915b5050505050828281518110611000576110006140a2565b6020908102919091010152600101610f30565b509392505050565b60606110276002612752565b905090565b6110346122c3565b61103d83610dcd565b61107f576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b6110bf8282604051611092929190614092565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061275f565b6110fb578282826040517f74f23c7c0000000000000000000000000000000000000000000000000000000081526004016107469392919061416d565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051611137929190614191565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526106f19061276b565b67ffffffffffffffff81166000908152600760205260409020600401805460609190611244906140d1565b80601f0160208091040260200160405190810160405280929190818152602001828054611270906140d1565b80156112bd5780601f10611292576101008083540402835291602001916112bd565b820191906000526020600020905b8154815290600101906020018083116112a057829003601f168201915b50505050509050919050565b6112d16122c3565b73ffffffffffffffffffffffffffffffffffffffff811661131e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006113b26005612752565b90506000815167ffffffffffffffff8111156113d0576113d0613e89565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b50905060005b82518110156114555782818151811061141a5761141a6140a2565b6020026020010151828281518110611434576114346140a2565b67ffffffffffffffff909216602092830291909101909101526001016113ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526106f19061276b565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061156e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156115a7576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b610b4e83838361281d565b6115ba6122c3565b60005b838110156117a75760008585838181106115d9576115d96140a2565b90506020020160208101906115ee9190613cbe565b9050611605600567ffffffffffffffff831661275f565b611647576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b67ffffffffffffffff8116600090815260076020526040812061166c90600501612752565b905060005b81518110156116d8576116cf82828151811061168f5761168f6140a2565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161275f90919063ffffffff16565b50600101611671565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906117416004830182613976565b600582016000818161175382826139b0565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611795915050565b60405180910390a150506001016115bd565b5060005b81811015611abd5760008383838181106117c7576117c76140a2565b90506020028101906117d991906141a5565b6117e290614271565b90506117f381606001516000612907565b61180281608001516000612907565b806040015151600003611841576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516118599060059067ffffffffffffffff16612a44565b61189e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610746565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611a2190826143e8565b5060005b826020015151811015611a6557611a5d836000015184602001518381518110611a5057611a506140a2565b60200260200101516124cc565b600101611a25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611aab9493929190614502565b60405180910390a150506001016117ab565b5050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611b1b576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a5473ffffffffffffffffffffffffffffffffffffffff163314611b6e576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b611bb073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612a50565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611be86122c3565b611bf181612aae565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611c8757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806106f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b4e9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612b72565b611dbf61032160a0830160808401613ae1565b611e1e57611dd360a0820160808301613ae1565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610746565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611e6a6040840160208501613cbe565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff919061459b565b15611f36576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f4e611f496040830160208401613cbe565b612c7e565b611f6e611f616040830160208401613cbe565b6103df60a084018461402d565b611fb357611f7f60a082018261402d565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610746929190614191565b611bf1611fc66040830160208401613cbe565b8260600135612da4565b6000815160000361200257507f0000000000000000000000000000000000000000000000000000000000000000919050565b815160201461203f57816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b6000828060200190518101906120559190614014565b905060ff8111156106f157826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff16036120ca5750816106f1565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1611156121b55760006121247f0000000000000000000000000000000000000000000000000000000000000000846145e7565b9050604d8160ff161115612198576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610746565b6121a381600a614720565b6121ad908561472f565b9150506106f1565b60006121e1837f00000000000000000000000000000000000000000000000000000000000000006145e7565b9050604d8160ff16118061222857506121fb81600a614720565b612225907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61472f565b84115b15612293576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610746565b61229e81600a614720565b610a38908561476a565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314612314576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f000000000000000000000000000000000000000000000000000000000000000061236d576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561240357600083828151811061238d5761238d6140a2565b602002602001015190506123ab816002612deb90919063ffffffff16565b156123fa5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612370565b5060005b8151811015610b4e576000828281518110612424576124246140a2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361246857506124c4565b612473600282612e0d565b156124c25760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612407565b8051600003612507576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff84166000908152600790925260409091206125399060050182612a44565b6125735782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610746929190614781565b600081815260086020526040902061258b83826143e8565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516111379190613aac565b6125d961032160a0830160808401613ae1565b6125ed57611dd360a0820160808301613ae1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6126396040840160208501613cbe565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156126aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ce919061459b565b15612705576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61271d6127186060830160408401613ae1565b612e2f565b6127356127306040830160208401613cbe565b612eae565b611bf16127486040830160208401613cbe565b8260600135612ffc565b606060006122bc83613040565b60006122bc838361309b565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526127f982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426127dd91906147a4565b85608001516fffffffffffffffffffffffffffffffff1661318e565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61282683610dcd565b612868576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b612873826000612907565b67ffffffffffffffff8316600090815260076020526040902061289690836131b6565b6128a1816000612907565b67ffffffffffffffff831660009081526007602052604090206128c790600201826131b6565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516128fa939291906147b7565b60405180910390a1505050565b8151156129d25781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061295d575060408201516fffffffffffffffffffffffffffffffff16155b1561299657816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610746919061483a565b80156129ce576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612a0b575060208201516fffffffffffffffffffffffffffffffff1615155b156129ce57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610746919061483a565b60006122bc8383613358565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610ab59085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611d2a565b3373ffffffffffffffffffffffffffffffffffffffff821603612afd576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612bd4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133a79092919063ffffffff16565b805190915015610b4e5780806020019051810190612bf2919061459b565b610b4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610746565b612c8781610dcd565b612cc9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6c919061459b565b611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206129ce90600201827f00000000000000000000000000000000000000000000000000000000000000006133b6565b60006122bc8373ffffffffffffffffffffffffffffffffffffffff841661309b565b60006122bc8373ffffffffffffffffffffffffffffffffffffffff8416613358565b7f000000000000000000000000000000000000000000000000000000000000000015611bf157612e60600282613739565b611bf1576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610746565b612eb781610dcd565b612ef9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f969190614876565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206129ce90827f00000000000000000000000000000000000000000000000000000000000000006133b6565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112bd57602002820191906000526020600020905b81548152602001906001019080831161307c5750505050509050919050565b600081815260018301602052604081205480156131845760006130bf6001836147a4565b85549091506000906130d3906001906147a4565b90508082146131385760008660000182815481106130f3576130f36140a2565b9060005260206000200154905080876000018481548110613116576131166140a2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061314957613149614893565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106f1565b60009150506106f1565b60006131ad8561319e848661476a565b6131a890876148c2565b613768565b95945050505050565b81546000906131df90700100000000000000000000000000000000900463ffffffff16426147a4565b905080156132815760018301548354613227916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661318e565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546132a7916fffffffffffffffffffffffffffffffff9081169116613768565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906128fa90849061483a565b600081815260018301602052604081205461339f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106f1565b5060006106f1565b6060610a38848460008561377e565b825474010000000000000000000000000000000000000000900460ff1615806133dd575081155b156133e757505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061342d90700100000000000000000000000000000000900463ffffffff16426147a4565b905080156134ed578183111561346f576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546134a99083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661318e565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156135a45773ffffffffffffffffffffffffffffffffffffffff841661354c576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610746565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610746565b848310156136b75760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906135e890826147a4565b6135f2878a6147a4565b6135fc91906148c2565b613606919061472f565b905073ffffffffffffffffffffffffffffffffffffffff861661365f576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610746565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610746565b6136c185846147a4565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156122bc565b600081831061377757816122bc565b5090919050565b606082471015613810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610746565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161383991906148d5565b60006040518083038185875af1925050503d8060008114613876576040519150601f19603f3d011682016040523d82523d6000602084013e61387b565b606091505b509150915061388c87838387613897565b979650505050505050565b6060831561392d5782516000036139265773ffffffffffffffffffffffffffffffffffffffff85163b613926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610746565b5081610a38565b610a3883838151156139425781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b508054613982906140d1565b6000825580601f10613992575050565b601f016020900490600052602060002090810190611bf191906139ca565b5080546000825590600052602060002090810190611bf191905b5b808211156139df57600081556001016139cb565b5090565b6000602082840312156139f557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146122bc57600080fd5b600060208284031215613a3757600080fd5b5035919050565b60005b83811015613a59578181015183820152602001613a41565b50506000910152565b60008151808452613a7a816020860160208601613a3e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122bc6020830184613a62565b73ffffffffffffffffffffffffffffffffffffffff81168114611bf157600080fd5b600060208284031215613af357600080fd5b81356122bc81613abf565b600060208284031215613b1057600080fd5b813567ffffffffffffffff811115613b2757600080fd5b820161010081850312156122bc57600080fd5b803567ffffffffffffffff81168114613b5257600080fd5b919050565b600080600060408486031215613b6c57600080fd5b613b7584613b3a565b9250602084013567ffffffffffffffff80821115613b9257600080fd5b818601915086601f830112613ba657600080fd5b813581811115613bb557600080fd5b876020828501011115613bc757600080fd5b6020830194508093505050509250925092565b60008083601f840112613bec57600080fd5b50813567ffffffffffffffff811115613c0457600080fd5b6020830191508360208260051b8501011115613c1f57600080fd5b9250929050565b60008060008060408587031215613c3c57600080fd5b843567ffffffffffffffff80821115613c5457600080fd5b613c6088838901613bda565b90965094506020870135915080821115613c7957600080fd5b50613c8687828801613bda565b95989497509550505050565b60008060408385031215613ca557600080fd5b8235613cb081613abf565b946020939093013593505050565b600060208284031215613cd057600080fd5b6122bc82613b3a565b600060208284031215613ceb57600080fd5b813567ffffffffffffffff811115613d0257600080fd5b820160a081850312156122bc57600080fd5b602081526000825160406020840152613d306060840182613a62565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526131ad8282613a62565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613de0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613dce858351613a62565b94509285019290850190600101613d94565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613e3b57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613e09565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613e3b57835167ffffffffffffffff1683529284019291840191600101613e63565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613edb57613edb613e89565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f2857613f28613e89565b604052919050565b8015158114611bf157600080fd5b80356fffffffffffffffffffffffffffffffff81168114613b5257600080fd5b600060608284031215613f7057600080fd5b6040516060810181811067ffffffffffffffff82111715613f9357613f93613e89565b6040529050808235613fa481613f30565b8152613fb260208401613f3e565b6020820152613fc360408401613f3e565b60408201525092915050565b600080600060e08486031215613fe457600080fd5b613fed84613b3a565b9250613ffc8560208601613f5e565b915061400b8560808601613f5e565b90509250925092565b60006020828403121561402657600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261406257600080fd5b83018035915067ffffffffffffffff82111561407d57600080fd5b602001915036819003821315613c1f57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806140e557607f821691505b60208210810361411e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff841681526040602082015260006131ad604083018486614124565b602081526000610a38602083018486614124565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126141d957600080fd5b9190910192915050565b600082601f8301126141f457600080fd5b813567ffffffffffffffff81111561420e5761420e613e89565b61423f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613ee1565b81815284602083860101111561425457600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561428457600080fd5b61428c613eb8565b61429583613b3a565b815260208084013567ffffffffffffffff808211156142b357600080fd5b9085019036601f8301126142c657600080fd5b8135818111156142d8576142d8613e89565b8060051b6142e7858201613ee1565b918252838101850191858101903684111561430157600080fd5b86860192505b8383101561433d5782358581111561431f5760008081fd5b61432d3689838a01016141e3565b8352509186019190860190614307565b808789015250505050604086013592508083111561435a57600080fd5b5050614368368286016141e3565b60408301525061437b3660608501613f5e565b606082015261438d3660c08501613f5e565b608082015292915050565b601f821115610b4e576000816000526020600020601f850160051c810160208610156143c15750805b601f850160051c820191505b818110156143e0578281556001016143cd565b505050505050565b815167ffffffffffffffff81111561440257614402613e89565b6144168161441084546140d1565b84614398565b602080601f83116001811461446957600084156144335750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556143e0565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156144b657888601518255948401946001909101908401614497565b50858210156144f257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261452681840187613a62565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506145649050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526131ad565b6000602082840312156145ad57600080fd5b81516122bc81613f30565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff82811682821603908111156106f1576106f16145b8565b600181815b8085111561465957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561463f5761463f6145b8565b8085161561464c57918102915b93841c9390800290614605565b509250929050565b600082614670575060016106f1565b8161467d575060006106f1565b8160018114614693576002811461469d576146b9565b60019150506106f1565b60ff8411156146ae576146ae6145b8565b50506001821b6106f1565b5060208310610133831016604e8410600b84101617156146dc575081810a6106f1565b6146e68383614600565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614718576147186145b8565b029392505050565b60006122bc60ff841683614661565b600082614765577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176106f1576106f16145b8565b67ffffffffffffffff83168152604060208201526000610a386040830184613a62565b818103818111156106f1576106f16145b8565b67ffffffffffffffff8416815260e0810161480360208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610a38565b606081016106f182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561488857600080fd5b81516122bc81613abf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b808201808211156106f1576106f16145b8565b600082516141d9818460208701613a3e56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b50604051620053a2380380620053a28339810160408190526200003591620005bb565b8585858584336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001f3565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006ee565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db90846200026d565b5050505091151561010052506200075a945050505050565b336001600160a01b038216036200021d57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200028e576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000319576000838281518110620002b257620002b26200070c565b60209081029190910101519050620002cc600282620003ca565b156200030f576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000291565b5060005b8151811015620003c55760008282815181106200033e576200033e6200070c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200036a5750620003bc565b62000377600282620003ea565b15620003ba576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200031d565b505050565b6000620003e1836001600160a01b03841662000401565b90505b92915050565b6000620003e1836001600160a01b03841662000505565b60008181526001830160205260408120548015620004fa5760006200042860018362000722565b85549091506000906200043e9060019062000722565b9050808214620004aa5760008660000182815481106200046257620004626200070c565b90600052602060002001549050808760000184815481106200048857620004886200070c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004be57620004be62000744565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003e4565b6000915050620003e4565b60008181526001830160205260408120546200054e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003e4565b506000620003e4565b6001600160a01b03811681146200056d57600080fd5b50565b805160ff811681146200058257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620005828162000557565b805180151581146200058257600080fd5b60008060008060008060c08789031215620005d557600080fd5b8651620005e28162000557565b95506020620005f388820162000570565b60408901519096506001600160401b03808211156200061157600080fd5b818a0191508a601f8301126200062657600080fd5b8151818111156200063b576200063b62000587565b8060051b604051601f19603f8301168101818110858211171562000663576200066362000587565b60405291825284820192508381018501918d8311156200068257600080fd5b938501935b82851015620006ab576200069b856200059d565b8452938501939285019262000687565b809950505050505050620006c2606088016200059d565b9250620006d260808801620005aa565b9150620006e260a088016200059d565b90509295509295509295565b6000602082840312156200070157600080fd5b620003e18262000570565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003e457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161010051614b776200082b600039600081816105d20152611c4e01526000818161066c015281816124a0015261315b01526000818161064601528181611fbd015261287601526000818161038201528181610ff301528181612166015281816122200152818161225401528181612287015281816122ec0152818161234501526123e70152600081816102e90152818161033e015281816107ad0152818161087f0152818161097301528181611d1001528181612f4f01526133460152614b776000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c8063962d402011610145578063c0d78655116100bd578063dc0bd9711161008c578063e8a1da1711610071578063e8a1da1714610690578063eb521a4c146106a3578063f2fde38b146106b657600080fd5b8063dc0bd97114610644578063e0351e131461066a57600080fd5b8063c0d78655146105f6578063c4bffe2b14610609578063c75eea9c1461061e578063cf7401f31461063157600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a11461059f578063b7946580146105bd578063bb98546b146105d057600080fd5b8063acfecf911461051d578063af58d59f1461053057600080fd5b8063962d4020146104b55780639a4575b9146104c8578063a42a7b8b146104e8578063a7cd63b71461050857600080fd5b806354c8a4f3116101d85780636d3d1a58116101a75780637d54534e1161018c5780637d54534e146104715780638926f54f146104845780638da5cb5b1461049757600080fd5b80636d3d1a581461044b57806379ba50971461046957600080fd5b806354c8a4f3146103ff57806362ddd3c41461041257806366320087146104255780636cfd15531461043857600080fd5b8063240028e81161022f578063390775371161021457806339077537146103ac578063432a6ba3146103ce5780634c5ef0ed146103ec57600080fd5b8063240028e81461032e57806324f65ee71461037b57600080fd5b806301ffc9a7146102615780630a861f2a14610289578063181f5a771461029e57806321df0da7146102e7575b600080fd5b61027461026f366004613b6b565b6106c9565b60405190151581526020015b60405180910390f35b61029c610297366004613bad565b610725565b005b6102da6040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3100000000000081525081565b6040516102809190613c34565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610280565b61027461033c366004613c69565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610280565b6103bf6103ba366004613c86565b6108d6565b60405190518152602001610280565b600a5473ffffffffffffffffffffffffffffffffffffffff16610309565b6102746103fa366004613cdf565b610a24565b61029c61040d366004613dae565b610a6e565b61029c610420366004613cdf565b610ae9565b61029c610433366004613e1a565b610b81565b61029c610446366004613c69565b610c5d565b60095473ffffffffffffffffffffffffffffffffffffffff16610309565b61029c610cac565b61029c61047f366004613c69565b610d7a565b610274610492366004613e46565b610dfb565b60015473ffffffffffffffffffffffffffffffffffffffff16610309565b61029c6104c3366004613ea6565b610e12565b6104db6104d6366004613f40565b610f6c565b6040516102809190613f7b565b6104fb6104f6366004613e46565b611038565b6040516102809190613fd2565b6105106111a3565b6040516102809190614054565b61029c61052b366004613cdf565b6111b4565b61054361053e366004613e46565b6112cc565b604051610280919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610309565b6102da6105cb366004613e46565b6113a1565b7f0000000000000000000000000000000000000000000000000000000000000000610274565b61029c610604366004613c69565b611451565b61061161152c565b60405161028091906140ae565b61054361062c366004613e46565b6115e4565b61029c61063f366004614236565b6116b6565b7f0000000000000000000000000000000000000000000000000000000000000000610309565b7f0000000000000000000000000000000000000000000000000000000000000000610274565b61029c61069e366004613dae565b61173a565b61029c6106b1366004613bad565b611c4c565b61029c6106c4366004613c69565b611d68565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d4056600000000000000000000000000000000000000000000000000000000148061071f575061071f82611d7c565b92915050565b600a5473ffffffffffffffffffffffffffffffffffffffff16331461077d576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082d919061427b565b1015610865576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108a673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611e60565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108ee82611f34565b6000610947606084013561094261090860c0870187614294565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061215892505050565b61221c565b905061099a61095c6060850160408601613c69565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169083611e60565b6109aa6060840160408501613c69565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f5283604051610a0891815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610a668383604051610a399291906142f9565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612430565b949350505050565b610a7661244b565b610ae38484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061249e92505050565b50505050565b610af161244b565b610afa83610dfb565b610b3c576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610774565b610b7c8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061265492505050565b505050565b610b8961244b565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610bf157600080fd5b505af1158015610c05573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610c5191815260200190565b60405180910390a25050565b610c6561244b565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cfd576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d8261244b565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b600061071f600567ffffffffffffffff8416612430565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610e52575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610e8b576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b8483141580610e9a5750848114155b15610ed1576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610f6357610f5b878783818110610ef157610ef1614309565b9050602002016020810190610f069190613e46565b868684818110610f1857610f18614309565b905060600201803603810190610f2e9190614338565b858585818110610f4057610f40614309565b905060600201803603810190610f569190614338565b61274e565b600101610ed4565b50505050505050565b6040805180820190915260608082526020820152610f8982612838565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610fe38460200160208101906105cb9190613e46565b81526020016110306040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190611061906005016129c4565b90506000815167ffffffffffffffff81111561107f5761107f6140f0565b6040519080825280602002602001820160405280156110b257816020015b606081526020019060019003908161109d5790505b50905060005b825181101561119b57600860008483815181106110d7576110d7614309565b6020026020010151815260200190815260200160002080546110f890614354565b80601f016020809104026020016040519081016040528092919081815260200182805461112490614354565b80156111715780601f1061114657610100808354040283529160200191611171565b820191906000526020600020905b81548152906001019060200180831161115457829003601f168201915b505050505082828151811061118857611188614309565b60209081029190910101526001016110b8565b509392505050565b60606111af60026129c4565b905090565b6111bc61244b565b6111c583610dfb565b611207576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610774565b611247828260405161121a9291906142f9565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906129d1565b611283578282826040517f74f23c7c000000000000000000000000000000000000000000000000000000008152600401610774939291906143f0565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7683836040516112bf929190614414565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261071f906129dd565b67ffffffffffffffff811660009081526007602052604090206004018054606091906113cc90614354565b80601f01602080910402602001604051908101604052809291908181526020018280546113f890614354565b80156114455780601f1061141a57610100808354040283529160200191611445565b820191906000526020600020905b81548152906001019060200180831161142857829003601f168201915b50505050509050919050565b61145961244b565b73ffffffffffffffffffffffffffffffffffffffff81166114a6576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b6060600061153a60056129c4565b90506000815167ffffffffffffffff811115611558576115586140f0565b604051908082528060200260200182016040528015611581578160200160208202803683370190505b50905060005b82518110156115dd578281815181106115a2576115a2614309565b60200260200101518282815181106115bc576115bc614309565b67ffffffffffffffff90921660209283029190910190910152600101611587565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261071f906129dd565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906116f6575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561172f576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b610b7c83838361274e565b61174261244b565b60005b8381101561192f57600085858381811061176157611761614309565b90506020020160208101906117769190613e46565b905061178d600567ffffffffffffffff83166129d1565b6117cf576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610774565b67ffffffffffffffff811660009081526007602052604081206117f4906005016129c4565b905060005b81518110156118605761185782828151811061181757611817614309565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016129d190919063ffffffff16565b506001016117f9565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906118c96004830182613afe565b60058201600081816118db8282613b38565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169450602001925061191d915050565b60405180910390a15050600101611745565b5060005b81811015611c4557600083838381811061194f5761194f614309565b90506020028101906119619190614428565b61196a906144f4565b905061197b81606001516000612a8f565b61198a81608001516000612a8f565b8060400151516000036119c9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516119e19060059067ffffffffffffffff16612bcc565b611a265780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610774565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611ba9908261466b565b5060005b826020015151811015611bed57611be5836000015184602001518381518110611bd857611bd8614309565b6020026020010151612654565b600101611bad565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611c339493929190614785565b60405180910390a15050600101611933565b5050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611ca3576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a5473ffffffffffffffffffffffffffffffffffffffff163314611cf6576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b611d3873ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612bd8565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611d7061244b565b611d7981612c36565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611e0f57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061071f57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b7c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612cfa565b611f4761033c60a0830160808401613c69565b611fa657611f5b60a0820160808301613c69565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610774565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611ff26040840160208501613e46565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612063573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612087919061481e565b156120be576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120d66120d16040830160208401613e46565b612e06565b6120f66120e96040830160208401613e46565b6103fa60a0840184614294565b61213b5761210760a0820182614294565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610774929190614414565b611d7961214e6040830160208401613e46565b8260600135612f2c565b6000815160000361218a57507f0000000000000000000000000000000000000000000000000000000000000000919050565b81516020146121c757816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107749190613c34565b6000828060200190518101906121dd919061427b565b905060ff81111561071f57826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107749190613c34565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff160361225257508161071f565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff16111561233d5760006122ac7f00000000000000000000000000000000000000000000000000000000000000008461486a565b9050604d8160ff161115612320576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610774565b61232b81600a6149a3565b61233590856149b2565b91505061071f565b6000612369837f000000000000000000000000000000000000000000000000000000000000000061486a565b9050604d8160ff1611806123b0575061238381600a6149a3565b6123ad907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6149b2565b84115b1561241b576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610774565b61242681600a6149a3565b610a6690856149ed565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461249c576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f00000000000000000000000000000000000000000000000000000000000000006124f5576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561258b57600083828151811061251557612515614309565b60200260200101519050612533816002612f7390919063ffffffff16565b156125825760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016124f8565b5060005b8151811015610b7c5760008282815181106125ac576125ac614309565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125f0575061264c565b6125fb600282612f95565b1561264a5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161258f565b805160000361268f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff84166000908152600790925260409091206126c19060050182612bcc565b6126fb5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610774929190614a04565b6000818152600860205260409020612713838261466b565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516112bf9190613c34565b61275783610dfb565b612799576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610774565b6127a4826000612a8f565b67ffffffffffffffff831660009081526007602052604090206127c79083612fb7565b6127d2816000612a8f565b67ffffffffffffffff831660009081526007602052604090206127f89060020182612fb7565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161282b93929190614a27565b60405180910390a1505050565b61284b61033c60a0830160808401613c69565b61285f57611f5b60a0820160808301613c69565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6128ab6040840160208501613e46565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561291c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612940919061481e565b15612977576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61298f61298a6060830160408401613c69565b613159565b6129a76129a26040830160208401613e46565b6131d8565b611d796129ba6040830160208401613e46565b8260600135613326565b606060006124448361336a565b600061244483836133c5565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152612a6b82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642612a4f9190614aaa565b85608001516fffffffffffffffffffffffffffffffff166134b8565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b815115612b5a5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612ae5575060408201516fffffffffffffffffffffffffffffffff16155b15612b1e57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107749190614abd565b8015612b56576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612b93575060208201516fffffffffffffffffffffffffffffffff1615155b15612b5657816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107749190614abd565b600061244483836134e0565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610ae39085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611eb2565b3373ffffffffffffffffffffffffffffffffffffffff821603612c85576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612d5c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661352f9092919063ffffffff16565b805190915015610b7c5780806020019051810190612d7a919061481e565b610b7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610774565b612e0f81610dfb565b612e51576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610774565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612ed0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ef4919061481e565b611d79576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b67ffffffffffffffff82166000908152600760205260409020612b5690600201827f000000000000000000000000000000000000000000000000000000000000000061353e565b60006124448373ffffffffffffffffffffffffffffffffffffffff84166133c5565b60006124448373ffffffffffffffffffffffffffffffffffffffff84166134e0565b8154600090612fe090700100000000000000000000000000000000900463ffffffff1642614aaa565b905080156130825760018301548354613028916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166134b8565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546130a8916fffffffffffffffffffffffffffffffff90811691166138c1565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061282b908490614abd565b7f000000000000000000000000000000000000000000000000000000000000000015611d795761318a6002826138d7565b611d79576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610774565b6131e181610dfb565b613223576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610774565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561329c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132c09190614af9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d79576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610774565b67ffffffffffffffff82166000908152600760205260409020612b5690827f000000000000000000000000000000000000000000000000000000000000000061353e565b60608160000180548060200260200160405190810160405280929190818152602001828054801561144557602002820191906000526020600020905b8154815260200190600101908083116133a65750505050509050919050565b600081815260018301602052604081205480156134ae5760006133e9600183614aaa565b85549091506000906133fd90600190614aaa565b905080821461346257600086600001828154811061341d5761341d614309565b906000526020600020015490508087600001848154811061344057613440614309565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061347357613473614b16565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061071f565b600091505061071f565b60006134d7856134c884866149ed565b6134d29087614b45565b6138c1565b95945050505050565b60008181526001830160205260408120546135275750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561071f565b50600061071f565b6060610a668484600085613906565b825474010000000000000000000000000000000000000000900460ff161580613565575081155b1561356f57505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906135b590700100000000000000000000000000000000900463ffffffff1642614aaa565b9050801561367557818311156135f7576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546136319083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166134b8565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561372c5773ffffffffffffffffffffffffffffffffffffffff84166136d4576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610774565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610774565b8483101561383f5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906137709082614aaa565b61377a878a614aaa565b6137849190614b45565b61378e91906149b2565b905073ffffffffffffffffffffffffffffffffffffffff86166137e7576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610774565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610774565b6138498584614aaa565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b60008183106138d05781612444565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515612444565b606082471015613998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610774565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516139c19190614b58565b60006040518083038185875af1925050503d80600081146139fe576040519150601f19603f3d011682016040523d82523d6000602084013e613a03565b606091505b5091509150613a1487838387613a1f565b979650505050505050565b60608315613ab5578251600003613aae5773ffffffffffffffffffffffffffffffffffffffff85163b613aae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610774565b5081610a66565b610a668383815115613aca5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107749190613c34565b508054613b0a90614354565b6000825580601f10613b1a575050565b601f016020900490600052602060002090810190611d799190613b52565b5080546000825590600052602060002090810190611d7991905b5b80821115613b675760008155600101613b53565b5090565b600060208284031215613b7d57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461244457600080fd5b600060208284031215613bbf57600080fd5b5035919050565b60005b83811015613be1578181015183820152602001613bc9565b50506000910152565b60008151808452613c02816020860160208601613bc6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006124446020830184613bea565b73ffffffffffffffffffffffffffffffffffffffff81168114611d7957600080fd5b600060208284031215613c7b57600080fd5b813561244481613c47565b600060208284031215613c9857600080fd5b813567ffffffffffffffff811115613caf57600080fd5b8201610100818503121561244457600080fd5b803567ffffffffffffffff81168114613cda57600080fd5b919050565b600080600060408486031215613cf457600080fd5b613cfd84613cc2565b9250602084013567ffffffffffffffff80821115613d1a57600080fd5b818601915086601f830112613d2e57600080fd5b813581811115613d3d57600080fd5b876020828501011115613d4f57600080fd5b6020830194508093505050509250925092565b60008083601f840112613d7457600080fd5b50813567ffffffffffffffff811115613d8c57600080fd5b6020830191508360208260051b8501011115613da757600080fd5b9250929050565b60008060008060408587031215613dc457600080fd5b843567ffffffffffffffff80821115613ddc57600080fd5b613de888838901613d62565b90965094506020870135915080821115613e0157600080fd5b50613e0e87828801613d62565b95989497509550505050565b60008060408385031215613e2d57600080fd5b8235613e3881613c47565b946020939093013593505050565b600060208284031215613e5857600080fd5b61244482613cc2565b60008083601f840112613e7357600080fd5b50813567ffffffffffffffff811115613e8b57600080fd5b602083019150836020606083028501011115613da757600080fd5b60008060008060008060608789031215613ebf57600080fd5b863567ffffffffffffffff80821115613ed757600080fd5b613ee38a838b01613d62565b90985096506020890135915080821115613efc57600080fd5b613f088a838b01613e61565b90965094506040890135915080821115613f2157600080fd5b50613f2e89828a01613e61565b979a9699509497509295939492505050565b600060208284031215613f5257600080fd5b813567ffffffffffffffff811115613f6957600080fd5b820160a0818503121561244457600080fd5b602081526000825160406020840152613f976060840182613bea565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526134d78282613bea565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015614047577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614035858351613bea565b94509285019290850190600101613ffb565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156140a257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614070565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156140a257835167ffffffffffffffff16835292840192918401916001016140ca565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715614142576141426140f0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561418f5761418f6140f0565b604052919050565b8015158114611d7957600080fd5b80356fffffffffffffffffffffffffffffffff81168114613cda57600080fd5b6000606082840312156141d757600080fd5b6040516060810181811067ffffffffffffffff821117156141fa576141fa6140f0565b604052905080823561420b81614197565b8152614219602084016141a5565b602082015261422a604084016141a5565b60408201525092915050565b600080600060e0848603121561424b57600080fd5b61425484613cc2565b925061426385602086016141c5565b915061427285608086016141c5565b90509250925092565b60006020828403121561428d57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126142c957600080fd5b83018035915067ffffffffffffffff8211156142e457600080fd5b602001915036819003821315613da757600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006060828403121561434a57600080fd5b61244483836141c5565b600181811c9082168061436857607f821691505b6020821081036143a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff841681526040602082015260006134d76040830184866143a7565b602081526000610a666020830184866143a7565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261445c57600080fd5b9190910192915050565b600082601f83011261447757600080fd5b813567ffffffffffffffff811115614491576144916140f0565b6144c260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614148565b8181528460208386010111156144d757600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561450757600080fd5b61450f61411f565b61451883613cc2565b815260208084013567ffffffffffffffff8082111561453657600080fd5b9085019036601f83011261454957600080fd5b81358181111561455b5761455b6140f0565b8060051b61456a858201614148565b918252838101850191858101903684111561458457600080fd5b86860192505b838310156145c0578235858111156145a25760008081fd5b6145b03689838a0101614466565b835250918601919086019061458a565b80878901525050505060408601359250808311156145dd57600080fd5b50506145eb36828601614466565b6040830152506145fe36606085016141c5565b60608201526146103660c085016141c5565b608082015292915050565b601f821115610b7c576000816000526020600020601f850160051c810160208610156146445750805b601f850160051c820191505b8181101561466357828155600101614650565b505050505050565b815167ffffffffffffffff811115614685576146856140f0565b614699816146938454614354565b8461461b565b602080601f8311600181146146ec57600084156146b65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614663565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156147395788860151825594840194600190910190840161471a565b508582101561477557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526147a981840187613bea565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506147e79050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526134d7565b60006020828403121561483057600080fd5b815161244481614197565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561071f5761071f61483b565b600181815b808511156148dc57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156148c2576148c261483b565b808516156148cf57918102915b93841c9390800290614888565b509250929050565b6000826148f35750600161071f565b816149005750600061071f565b816001811461491657600281146149205761493c565b600191505061071f565b60ff8411156149315761493161483b565b50506001821b61071f565b5060208310610133831016604e8410600b841016171561495f575081810a61071f565b6149698383614883565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561499b5761499b61483b565b029392505050565b600061244460ff8416836148e4565b6000826149e8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761071f5761071f61483b565b67ffffffffffffffff83168152604060208201526000610a666040830184613bea565b67ffffffffffffffff8416815260e08101614a7360208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610a66565b8181038181111561071f5761071f61483b565b6060810161071f82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215614b0b57600080fd5b815161244481613c47565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561071f5761071f61483b565b6000825161445c818460208701613bc656fea164736f6c6343000818000a", } var LockReleaseTokenPoolABI = LockReleaseTokenPoolMetaData.ABI @@ -769,6 +769,18 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetChainRate return _LockReleaseTokenPool.Contract.SetChainRateLimiterConfig(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _LockReleaseTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.SetChainRateLimiterConfigs(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.SetChainRateLimiterConfigs(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -3549,6 +3561,8 @@ type LockReleaseTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) SetRebalancer(opts *bind.TransactOpts, rebalancer common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/token_pool/token_pool.go b/core/gethwrappers/ccip/generated/token_pool/token_pool.go index 5032b336e0a..c7c947d8636 100644 --- a/core/gethwrappers/ccip/generated/token_pool/token_pool.go +++ b/core/gethwrappers/ccip/generated/token_pool/token_pool.go @@ -81,7 +81,7 @@ type TokenPoolChainUpdate struct { } var TokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var TokenPoolABI = TokenPoolMetaData.ABI @@ -672,6 +672,18 @@ func (_TokenPool *TokenPoolTransactorSession) SetChainRateLimiterConfig(remoteCh return _TokenPool.Contract.SetChainRateLimiterConfig(&_TokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_TokenPool *TokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _TokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_TokenPool *TokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _TokenPool.Contract.SetChainRateLimiterConfigs(&_TokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_TokenPool *TokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _TokenPool.Contract.SetChainRateLimiterConfigs(&_TokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + func (_TokenPool *TokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -2867,6 +2879,8 @@ type TokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) + SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go index ca6c4a1977f..fb9493b24ac 100644 --- a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go +++ b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go @@ -94,8 +94,8 @@ type USDCTokenPoolDomainUpdate struct { } var USDCTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101606040523480156200001257600080fd5b50604051620054b7380380620054b7833981016040819052620000359162000b93565b836006848484336000816200005d57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200009057620000908162000493565b50506001600160a01b0385161580620000b057506001600160a01b038116155b80620000c357506001600160a01b038216155b15620000e2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000152575060408051601f3d908101601f191682019092526200014f9181019062000cb9565b60015b1562000193578060ff168560ff161462000191576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dd57604080516000815260208101909152620001dd90846200050d565b5050506001600160a01b03871691506200020c9050576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000273919062000ce5565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002dc919062000d05565b905063ffffffff8116156200030d576040516334697c6b60e11b815263ffffffff8216600482015260240162000188565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000374919062000d05565b905063ffffffff811615620003a5576040516316ba39c560e31b815263ffffffff8216600482015260240162000188565b6001600160a01b038089166101005283166101208190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa158015620003f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041e919062000d05565b63ffffffff16610140526101005160805162000449916001600160a01b03909116906000196200066a565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000e52565b336001600160a01b03821603620004bd57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200052e576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005b957600083828151811062000552576200055262000d2d565b602090810291909101015190506200056c60028262000750565b15620005af576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000531565b5060005b815181101562000665576000828281518110620005de57620005de62000d2d565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200060a57506200065c565b6200061760028262000770565b156200065a576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620005bd565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620006bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006e2919062000d43565b620006ee919062000d73565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200074a918691906200078716565b50505050565b600062000767836001600160a01b03841662000858565b90505b92915050565b600062000767836001600160a01b0384166200095c565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620007d6906001600160a01b038516908490620009ae565b805190915015620006655780806020019051810190620007f7919062000d89565b620006655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000188565b60008181526001830160205260408120548015620009515760006200087f60018362000dad565b8554909150600090620008959060019062000dad565b905080821462000901576000866000018281548110620008b957620008b962000d2d565b9060005260206000200154905080876000018481548110620008df57620008df62000d2d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000915576200091562000dc3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200076a565b60009150506200076a565b6000818152600183016020526040812054620009a5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200076a565b5060006200076a565b6060620009bf8484600085620009c7565b949350505050565b60608247101562000a2a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000188565b600080866001600160a01b0316858760405162000a48919062000dff565b60006040518083038185875af1925050503d806000811462000a87576040519150601f19603f3d011682016040523d82523d6000602084013e62000a8c565b606091505b50909250905062000aa08783838762000aab565b979650505050505050565b6060831562000b1f57825160000362000b17576001600160a01b0385163b62000b175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000188565b5081620009bf565b620009bf838381511562000b365781518083602001fd5b8060405162461bcd60e51b815260040162000188919062000e1d565b6001600160a01b038116811462000b6857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b8e8162000b52565b919050565b600080600080600060a0868803121562000bac57600080fd5b855162000bb98162000b52565b8095505060208087015162000bce8162000b52565b60408801519095506001600160401b038082111562000bec57600080fd5b818901915089601f83011262000c0157600080fd5b81518181111562000c165762000c1662000b6b565b8060051b604051601f19603f8301168101818110858211171562000c3e5762000c3e62000b6b565b60405291825284820192508381018501918c83111562000c5d57600080fd5b938501935b8285101562000c865762000c768562000b81565b8452938501939285019262000c62565b80985050505050505062000c9d6060870162000b81565b915062000cad6080870162000b81565b90509295509295909350565b60006020828403121562000ccc57600080fd5b815160ff8116811462000cde57600080fd5b9392505050565b60006020828403121562000cf857600080fd5b815162000cde8162000b52565b60006020828403121562000d1857600080fd5b815163ffffffff8116811462000cde57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000d5657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200076a576200076a62000d5d565b60006020828403121562000d9c57600080fd5b8151801515811462000cde57600080fd5b818103818111156200076a576200076a62000d5d565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000df657818101518382015260200162000ddc565b50506000910152565b6000825162000e1381846020870162000dd9565b9190910192915050565b602081526000825180602084015262000e3e81604085016020870162000dd9565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516101005161012051610140516145af62000f08600039600081816104170152818161113c01528181612107015261216501526000818161072b0152610a750152600081816103dd01526110520152600081816106dc0152818161221d0152612bcc01526000818161061801528181611eb40152612509015260006103660152600081816102cd015281816103220152818161101c01528181612b620152612db701526145af6000f3fe608060405234801561001057600080fd5b50600436106102405760003560e01c80639a4575b911610145578063c4bffe2b116100bd578063dfadfa351161008c578063e8a1da1711610071578063e8a1da1714610700578063f2fde38b14610713578063fbf84dd71461072657600080fd5b8063dfadfa351461063c578063e0351e13146106da57600080fd5b8063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f314610603578063dc0bd9711461061657600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610597578063b7946580146105b5578063c0d78655146105c857600080fd5b8063acfecf9114610515578063af58d59f1461052857600080fd5b80639a4575b9146104b85780639fdf13ff146104d8578063a42a7b8b146104e0578063a7cd63b71461050057600080fd5b806354c8a4f3116101d85780636d3d1a58116101a75780637d54534e1161018c5780637d54534e146104745780638926f54f146104875780638da5cb5b1461049a57600080fd5b80636d3d1a581461044e57806379ba50971461046c57600080fd5b806354c8a4f3146103c55780636155cda0146103d857806362ddd3c4146103ff5780636b716b0d1461041257600080fd5b8063240028e811610214578063240028e81461031257806324f65ee71461035f57806339077537146103905780634c5ef0ed146103b257600080fd5b806241d3c11461024557806301ffc9a71461025a578063181f5a771461028257806321df0da7146102cb575b600080fd5b610258610253366004613577565b61074d565b005b61026d6102683660046135ec565b6108ea565b60405190151581526020015b60405180910390f35b6102be6040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e310000000000000000000000000081525081565b6040516102799190613692565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610279565b61026d6103203660046136c7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610279565b6103a361039e3660046136e4565b6109cf565b60405190518152602001610279565b61026d6103c0366004613736565b610bb4565b6102586103d3366004613807565b610bfe565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b61025861040d366004613736565b610c79565b6104397f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610279565b60095473ffffffffffffffffffffffffffffffffffffffff166102ed565b610258610d11565b6102586104823660046136c7565b610ddf565b61026d610495366004613873565b610e60565b60015473ffffffffffffffffffffffffffffffffffffffff166102ed565b6104cb6104c6366004613890565b610e77565b60405161027991906138cb565b610439600081565b6104f36104ee366004613873565b6111b7565b6040516102799190613922565b610508611322565b60405161027991906139a4565b610258610523366004613736565b611333565b61053b610536366004613873565b61144b565b604051610279919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ed565b6102be6105c3366004613873565b611520565b6102586105d63660046136c7565b6115d0565b6105e36116a4565b60405161027991906139fe565b61053b6105fe366004613873565b61175c565b610258610611366004613b8b565b61182e565b7f00000000000000000000000000000000000000000000000000000000000000006102ed565b6106b061064a366004613873565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600a82529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610279565b7f000000000000000000000000000000000000000000000000000000000000000061026d565b61025861070e366004613807565b6118b2565b6102586107213660046136c7565b611dc4565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b610755611dd8565b60005b818110156108ac57600083838381811061077457610774613bd2565b90506080020180360381019061078a9190613c15565b805190915015806107a75750604081015167ffffffffffffffff16155b1561081657604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600a90925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909516919093161792909217905501610758565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5682826040516108de929190613c8f565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061097d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806109c957507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526109e782611e2b565b60006109f660c0840184613d16565b810190610a039190613d7b565b90506000610a1460e0850185613d16565b810190610a219190613e48565b9050610a3181600001518361204f565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610aa892600401613ed9565b6020604051808303816000875af1158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190613efe565b610b21576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3160608501604086016136c7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9391815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b6000610bf68383604051610bc9929190613f1b565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612200565b949350505050565b610c06611dd8565b610c738484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061221b92505050565b50505050565b610c81611dd8565b610c8a83610e60565b610ccc576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b610d0c8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123d192505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d62576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610de7611dd8565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006109c9600567ffffffffffffffff8416612200565b6040805180820190915260608082526020820152610e94826124cb565b6000600a81610ea96040860160208701613873565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610f5057610f116040840160208501613873565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b610f5a8380613d16565b9050602014610fa157610f6d8380613d16565b6040517fa3c8cf0900000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b6000610fad8480613d16565b810190610fba9190613f88565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190613fa1565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a2604051806040016040528061111c8760200160208101906105c39190613873565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b67ffffffffffffffff81166000908152600760205260408120606091906111e090600501612657565b90506000815167ffffffffffffffff8111156111fe576111fe613a40565b60405190808252806020026020018201604052801561123157816020015b606081526020019060019003908161121c5790505b50905060005b825181101561131a576008600084838151811061125657611256613bd2565b60200260200101518152602001908152602001600020805461127790613fbe565b80601f01602080910402602001604051908101604052809291908181526020018280546112a390613fbe565b80156112f05780601f106112c5576101008083540402835291602001916112f0565b820191906000526020600020905b8154815290600101906020018083116112d357829003601f168201915b505050505082828151811061130757611307613bd2565b6020908102919091010152600101611237565b509392505050565b606061132e6002612657565b905090565b61133b611dd8565b61134483610e60565b611386576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b6113c68282604051611399929190613f1b565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612664565b611402578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161080d93929190614011565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76838360405161143e929190613f74565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526109c990612670565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061154b90613fbe565b80601f016020809104026020016040519081016040528092919081815260200182805461157790613fbe565b80156115c45780601f10611599576101008083540402835291602001916115c4565b820191906000526020600020905b8154815290600101906020018083116115a757829003601f168201915b50505050509050919050565b6115d8611dd8565b73ffffffffffffffffffffffffffffffffffffffff8116611625576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f168491016108de565b606060006116b26005612657565b90506000815167ffffffffffffffff8111156116d0576116d0613a40565b6040519080825280602002602001820160405280156116f9578160200160208202803683370190505b50905060005b82518110156117555782818151811061171a5761171a613bd2565b602002602001015182828151811061173457611734613bd2565b67ffffffffffffffff909216602092830291909101909101526001016116ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526109c990612670565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061186e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156118a7576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b610d0c838383612722565b6118ba611dd8565b60005b83811015611aa75760008585838181106118d9576118d9613bd2565b90506020020160208101906118ee9190613873565b9050611905600567ffffffffffffffff8316612664565b611947576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b67ffffffffffffffff8116600090815260076020526040812061196c90600501612657565b905060005b81518110156119d8576119cf82828151811061198f5761198f613bd2565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161266490919063ffffffff16565b50600101611971565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611a41600483018261350a565b6005820160008181611a538282613544565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611a95915050565b60405180910390a150506001016118bd565b5060005b81811015611dbd576000838383818110611ac757611ac7613bd2565b9050602002810190611ad99190614035565b611ae290614112565b9050611af38160600151600061280c565b611b028160800151600061280c565b806040015151600003611b41576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051611b599060059067ffffffffffffffff16612949565b611b9e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611d21908261421a565b5060005b826020015151811015611d6557611d5d836000015184602001518381518110611d5057611d50613bd2565b60200260200101516123d1565b600101611d25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611dab9493929190614334565b60405180910390a15050600101611aab565b5050505050565b611dcc611dd8565b611dd581612955565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e29576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611e3e61032060a08301608084016136c7565b611e9d57611e5260a08201608083016136c7565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161080d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611ee96040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190613efe565b15611fb5576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fcd611fc86040830160208401613873565b612a19565b611fed611fe06040830160208401613873565b6103c060a0840184613d16565b61203257611ffe60a0820182613d16565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b611dd56120456040830160208401613873565b8260600135612b3f565b600482015163ffffffff81161561209a576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff8216600482015260240161080d565b6008830151600c8401516014850151602085015163ffffffff8085169116146121055760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161080d565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff161461219a576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161080d565b845167ffffffffffffffff8281169116146121f85784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152908216602482015260440161080d565b505050505050565b600081815260018301602052604081205415155b9392505050565b7f0000000000000000000000000000000000000000000000000000000000000000612272576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561230857600083828151811061229257612292613bd2565b602002602001015190506122b0816002612b8690919063ffffffff16565b156122ff5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612275565b5060005b8151811015610d0c57600082828151811061232957612329613bd2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361236d57506123c9565b612378600282612ba8565b156123c75760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161230c565b805160000361240c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061243e9060050182612949565b6124785782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161080d9291906143cd565b6000818152600860205260409020612490838261421a565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea8360405161143e9190613692565b6124de61032060a08301608084016136c7565b6124f257611e5260a08201608083016136c7565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61253e6040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156125af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d39190613efe565b1561260a576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61262261261d60608301604084016136c7565b612bca565b61263a6126356040830160208401613873565b612c49565b611dd561264d6040830160208401613873565b8260600135612d97565b6060600061221483612ddb565b60006122148383612e36565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526126fe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426126e2919061441f565b85608001516fffffffffffffffffffffffffffffffff16612f29565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61272b83610e60565b61276d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b61277882600061280c565b67ffffffffffffffff8316600090815260076020526040902061279b9083612f51565b6127a681600061280c565b67ffffffffffffffff831660009081526007602052604090206127cc9060020182612f51565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516127ff93929190614432565b60405180910390a1505050565b8151156128d75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612862575060408201516fffffffffffffffffffffffffffffffff16155b1561289b57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b80156128d3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612910575060208201516fffffffffffffffffffffffffffffffff1615155b156128d357816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b600061221483836130f3565b3373ffffffffffffffffffffffffffffffffffffffff8216036129a4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612a2281610e60565b612a64576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b079190613efe565b611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390600201827f0000000000000000000000000000000000000000000000000000000000000000613142565b60006122148373ffffffffffffffffffffffffffffffffffffffff8416612e36565b60006122148373ffffffffffffffffffffffffffffffffffffffff84166130f3565b7f000000000000000000000000000000000000000000000000000000000000000015611dd557612bfb6002826134c5565b611dd5576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161080d565b612c5281610e60565b612c94576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3191906144f1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390827f0000000000000000000000000000000000000000000000000000000000000000613142565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115c457602002820191906000526020600020905b815481526020019060010190808311612e175750505050509050919050565b60008181526001830160205260408120548015612f1f576000612e5a60018361441f565b8554909150600090612e6e9060019061441f565b9050808214612ed3576000866000018281548110612e8e57612e8e613bd2565b9060005260206000200154905080876000018481548110612eb157612eb1613bd2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ee457612ee461450e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506109c9565b60009150506109c9565b6000612f4885612f39848661453d565b612f439087614554565b6134f4565b95945050505050565b8154600090612f7a90700100000000000000000000000000000000900463ffffffff164261441f565b9050801561301c5760018301548354612fc2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612f29565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354613042916fffffffffffffffffffffffffffffffff90811691166134f4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906127ff9084906144b5565b600081815260018301602052604081205461313a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556109c9565b5060006109c9565b825474010000000000000000000000000000000000000000900460ff161580613169575081155b1561317357505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906131b990700100000000000000000000000000000000900463ffffffff164261441f565b9050801561327957818311156131fb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546132359083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612f29565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156133305773ffffffffffffffffffffffffffffffffffffffff84166132d8576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161080d565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161080d565b848310156134435760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290613374908261441f565b61337e878a61441f565b6133889190614554565b6133929190614567565b905073ffffffffffffffffffffffffffffffffffffffff86166133eb576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161080d565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161080d565b61344d858461441f565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515612214565b60008183106135035781612214565b5090919050565b50805461351690613fbe565b6000825580601f10613526575050565b601f016020900490600052602060002090810190611dd5919061355e565b5080546000825590600052602060002090810190611dd591905b5b80821115613573576000815560010161355f565b5090565b6000806020838503121561358a57600080fd5b823567ffffffffffffffff808211156135a257600080fd5b818501915085601f8301126135b657600080fd5b8135818111156135c557600080fd5b8660208260071b85010111156135da57600080fd5b60209290920196919550909350505050565b6000602082840312156135fe57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461221457600080fd5b6000815180845260005b8181101561365457602081850181015186830182015201613638565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612214602083018461362e565b73ffffffffffffffffffffffffffffffffffffffff81168114611dd557600080fd5b6000602082840312156136d957600080fd5b8135612214816136a5565b6000602082840312156136f657600080fd5b813567ffffffffffffffff81111561370d57600080fd5b8201610100818503121561221457600080fd5b67ffffffffffffffff81168114611dd557600080fd5b60008060006040848603121561374b57600080fd5b833561375681613720565b9250602084013567ffffffffffffffff8082111561377357600080fd5b818601915086601f83011261378757600080fd5b81358181111561379657600080fd5b8760208285010111156137a857600080fd5b6020830194508093505050509250925092565b60008083601f8401126137cd57600080fd5b50813567ffffffffffffffff8111156137e557600080fd5b6020830191508360208260051b850101111561380057600080fd5b9250929050565b6000806000806040858703121561381d57600080fd5b843567ffffffffffffffff8082111561383557600080fd5b613841888389016137bb565b9096509450602087013591508082111561385a57600080fd5b50613867878288016137bb565b95989497509550505050565b60006020828403121561388557600080fd5b813561221481613720565b6000602082840312156138a257600080fd5b813567ffffffffffffffff8111156138b957600080fd5b820160a0818503121561221457600080fd5b6020815260008251604060208401526138e7606084018261362e565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612f48828261362e565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613997577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261398585835161362e565b9450928501929085019060010161394b565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139c0565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835167ffffffffffffffff1683529284019291840191600101613a1a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613a9257613a92613a40565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613adf57613adf613a40565b604052919050565b8015158114611dd557600080fd5b80356fffffffffffffffffffffffffffffffff81168114613b1557600080fd5b919050565b600060608284031215613b2c57600080fd5b6040516060810181811067ffffffffffffffff82111715613b4f57613b4f613a40565b6040529050808235613b6081613ae7565b8152613b6e60208401613af5565b6020820152613b7f60408401613af5565b60408201525092915050565b600080600060e08486031215613ba057600080fd5b8335613bab81613720565b9250613bba8560208601613b1a565b9150613bc98560808601613b1a565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff81168114613b1557600080fd5b600060808284031215613c2757600080fd5b6040516080810181811067ffffffffffffffff82111715613c4a57613c4a613a40565b60405282358152613c5d60208401613c01565b60208201526040830135613c7081613720565b60408201526060830135613c8381613ae7565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613d09578135835263ffffffff613cc1868401613c01565b168584015283820135613cd381613720565b67ffffffffffffffff1683850152606082810135613cf081613ae7565b1515908401526080928301929190910190600101613ca5565b5090979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d4b57600080fd5b83018035915067ffffffffffffffff821115613d6657600080fd5b60200191503681900382131561380057600080fd5b600060408284031215613d8d57600080fd5b613d95613a6f565b8235613da081613720565b8152613dae60208401613c01565b60208201529392505050565b600082601f830112613dcb57600080fd5b813567ffffffffffffffff811115613de557613de5613a40565b613e1660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613a98565b818152846020838601011115613e2b57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613e5a57600080fd5b813567ffffffffffffffff80821115613e7257600080fd5b9083019060408286031215613e8657600080fd5b613e8e613a6f565b823582811115613e9d57600080fd5b613ea987828601613dba565b825250602083013582811115613ebe57600080fd5b613eca87828601613dba565b60208301525095945050505050565b604081526000613eec604083018561362e565b8281036020840152612f48818561362e565b600060208284031215613f1057600080fd5b815161221481613ae7565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610bf6602083018486613f2b565b600060208284031215613f9a57600080fd5b5035919050565b600060208284031215613fb357600080fd5b815161221481613720565b600181811c90821680613fd257607f821691505b60208210810361400b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b67ffffffffffffffff84168152604060208201526000612f48604083018486613f2b565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261406957600080fd5b9190910192915050565b600082601f83011261408457600080fd5b8135602067ffffffffffffffff808311156140a1576140a1613a40565b8260051b6140b0838201613a98565b93845285810183019383810190888611156140ca57600080fd5b84880192505b85831015614106578235848111156140e85760008081fd5b6140f68a87838c0101613dba565b83525091840191908401906140d0565b98975050505050505050565b6000610120823603121561412557600080fd5b60405160a0810167ffffffffffffffff828210818311171561414957614149613a40565b816040528435915061415a82613720565b9082526020840135908082111561417057600080fd5b61417c36838701614073565b6020840152604085013591508082111561419557600080fd5b506141a236828601613dba565b6040830152506141b53660608501613b1a565b60608201526141c73660c08501613b1a565b608082015292915050565b601f821115610d0c576000816000526020600020601f850160051c810160208610156141fb5750805b601f850160051c820191505b818110156121f857828155600101614207565b815167ffffffffffffffff81111561423457614234613a40565b614248816142428454613fbe565b846141d2565b602080601f83116001811461429b57600084156142655750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556121f8565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142e8578886015182559484019460019091019084016142c9565b508582101561432457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526143588184018761362e565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506143969050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612f48565b67ffffffffffffffff83168152604060208201526000610bf6604083018461362e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109c9576109c96143f0565b67ffffffffffffffff8416815260e0810161447e60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610bf6565b606081016109c982848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561450357600080fd5b8151612214816136a5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b80820281158282048414176109c9576109c96143f0565b808201808211156109c9576109c96143f0565b60008261459d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101606040523480156200001257600080fd5b506040516200573a3803806200573a833981016040819052620000359162000b93565b836006848484336000816200005d57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200009057620000908162000493565b50506001600160a01b0385161580620000b057506001600160a01b038116155b80620000c357506001600160a01b038216155b15620000e2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000152575060408051601f3d908101601f191682019092526200014f9181019062000cb9565b60015b1562000193578060ff168560ff161462000191576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dd57604080516000815260208101909152620001dd90846200050d565b5050506001600160a01b03871691506200020c9050576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000273919062000ce5565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002dc919062000d05565b905063ffffffff8116156200030d576040516334697c6b60e11b815263ffffffff8216600482015260240162000188565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000374919062000d05565b905063ffffffff811615620003a5576040516316ba39c560e31b815263ffffffff8216600482015260240162000188565b6001600160a01b038089166101005283166101208190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa158015620003f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041e919062000d05565b63ffffffff16610140526101005160805162000449916001600160a01b03909116906000196200066a565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000e52565b336001600160a01b03821603620004bd57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200052e576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005b957600083828151811062000552576200055262000d2d565b602090810291909101015190506200056c60028262000750565b15620005af576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000531565b5060005b815181101562000665576000828281518110620005de57620005de62000d2d565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200060a57506200065c565b6200061760028262000770565b156200065a576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620005bd565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620006bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006e2919062000d43565b620006ee919062000d73565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200074a918691906200078716565b50505050565b600062000767836001600160a01b03841662000858565b90505b92915050565b600062000767836001600160a01b0384166200095c565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620007d6906001600160a01b038516908490620009ae565b805190915015620006655780806020019051810190620007f7919062000d89565b620006655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000188565b60008181526001830160205260408120548015620009515760006200087f60018362000dad565b8554909150600090620008959060019062000dad565b905080821462000901576000866000018281548110620008b957620008b962000d2d565b9060005260206000200154905080876000018481548110620008df57620008df62000d2d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000915576200091562000dc3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200076a565b60009150506200076a565b6000818152600183016020526040812054620009a5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200076a565b5060006200076a565b6060620009bf8484600085620009c7565b949350505050565b60608247101562000a2a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000188565b600080866001600160a01b0316858760405162000a48919062000dff565b60006040518083038185875af1925050503d806000811462000a87576040519150601f19603f3d011682016040523d82523d6000602084013e62000a8c565b606091505b50909250905062000aa08783838762000aab565b979650505050505050565b6060831562000b1f57825160000362000b17576001600160a01b0385163b62000b175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000188565b5081620009bf565b620009bf838381511562000b365781518083602001fd5b8060405162461bcd60e51b815260040162000188919062000e1d565b6001600160a01b038116811462000b6857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b8e8162000b52565b919050565b600080600080600060a0868803121562000bac57600080fd5b855162000bb98162000b52565b8095505060208087015162000bce8162000b52565b60408801519095506001600160401b038082111562000bec57600080fd5b818901915089601f83011262000c0157600080fd5b81518181111562000c165762000c1662000b6b565b8060051b604051601f19603f8301168101818110858211171562000c3e5762000c3e62000b6b565b60405291825284820192508381018501918c83111562000c5d57600080fd5b938501935b8285101562000c865762000c768562000b81565b8452938501939285019262000c62565b80985050505050505062000c9d6060870162000b81565b915062000cad6080870162000b81565b90509295509295909350565b60006020828403121562000ccc57600080fd5b815160ff8116811462000cde57600080fd5b9392505050565b60006020828403121562000cf857600080fd5b815162000cde8162000b52565b60006020828403121562000d1857600080fd5b815163ffffffff8116811462000cde57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000d5657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200076a576200076a62000d5d565b60006020828403121562000d9c57600080fd5b8151801515811462000cde57600080fd5b818103818111156200076a576200076a62000d5d565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000df657818101518382015260200162000ddc565b50506000910152565b6000825162000e1381846020870162000dd9565b9190910192915050565b602081526000825180602084015262000e3e81604085016020870162000dd9565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051610120516101405161483262000f0860003960008181610432015281816112c40152818161228f01526122ed0152600081816107590152610aa30152600081816103f801526111da01526000818161070a015281816123a50152612ef60152600081816106460152818161203c015261277b015260006103810152600081816102e80152818161033d015281816111a401528181612cea01526130e101526148326000f3fe608060405234801561001057600080fd5b506004361061025b5760003560e01c80639a4575b911610145578063c4bffe2b116100bd578063dfadfa351161008c578063e8a1da1711610071578063e8a1da171461072e578063f2fde38b14610741578063fbf84dd71461075457600080fd5b8063dfadfa351461066a578063e0351e131461070857600080fd5b8063c4bffe2b14610609578063c75eea9c1461061e578063cf7401f314610631578063dc0bd9711461064457600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a1146105c5578063b7946580146105e3578063c0d78655146105f657600080fd5b8063acfecf9114610543578063af58d59f1461055657600080fd5b80639a4575b9146104e65780639fdf13ff14610506578063a42a7b8b1461050e578063a7cd63b71461052e57600080fd5b80636155cda0116101d857806379ba5097116101a75780638926f54f1161018c5780638926f54f146104a25780638da5cb5b146104b5578063962d4020146104d357600080fd5b806379ba5097146104875780637d54534e1461048f57600080fd5b80636155cda0146103f357806362ddd3c41461041a5780636b716b0d1461042d5780636d3d1a581461046957600080fd5b8063240028e81161022f578063390775371161021457806339077537146103ab5780634c5ef0ed146103cd57806354c8a4f3146103e057600080fd5b8063240028e81461032d57806324f65ee71461037a57600080fd5b806241d3c11461026057806301ffc9a714610275578063181f5a771461029d57806321df0da7146102e6575b600080fd5b61027361026e3660046136ff565b61077b565b005b610288610283366004613774565b610918565b60405190151581526020015b60405180910390f35b6102d96040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e310000000000000000000000000081525081565b604051610294919061381a565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610294565b61028861033b36600461384f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610294565b6103be6103b936600461386c565b6109fd565b60405190518152602001610294565b6102886103db3660046138be565b610be2565b6102736103ee36600461398f565b610c2c565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b6102736104283660046138be565b610ca7565b6104547f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610294565b60095473ffffffffffffffffffffffffffffffffffffffff16610308565b610273610d3f565b61027361049d36600461384f565b610e0d565b6102886104b03660046139fb565b610e8e565b60015473ffffffffffffffffffffffffffffffffffffffff16610308565b6102736104e1366004613a5d565b610ea5565b6104f96104f4366004613af7565b610fff565b6040516102949190613b32565b610454600081565b61052161051c3660046139fb565b61133f565b6040516102949190613b89565b6105366114aa565b6040516102949190613c0b565b6102736105513660046138be565b6114bb565b6105696105643660046139fb565b6115d3565b604051610294919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610308565b6102d96105f13660046139fb565b6116a8565b61027361060436600461384f565b611758565b61061161182c565b6040516102949190613c65565b61056961062c3660046139fb565b6118e4565b61027361063f366004613df2565b6119b6565b7f0000000000000000000000000000000000000000000000000000000000000000610308565b6106de6106783660046139fb565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600a82529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610294565b7f0000000000000000000000000000000000000000000000000000000000000000610288565b61027361073c36600461398f565b611a3a565b61027361074f36600461384f565b611f4c565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b610783611f60565b60005b818110156108da5760008383838181106107a2576107a2613e39565b9050608002018036038101906107b89190613e7c565b805190915015806107d55750604081015167ffffffffffffffff16155b1561084457604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600a90925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909516919093161792909217905501610786565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee56828260405161090c929190613ef6565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806109ab57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806109f757507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b604080516020810190915260008152610a1582611fb3565b6000610a2460c0840184613f7d565b810190610a319190613fe2565b90506000610a4260e0850185613f7d565b810190610a4f91906140af565b9050610a5f8160000151836121d7565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610ad692600401614140565b6020604051808303816000875af1158015610af5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b199190614165565b610b4f576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b5f606085016040860161384f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610bc191815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b6000610c248383604051610bf7929190614182565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612388565b949350505050565b610c34611f60565b610ca1848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284376000920191909152506123a392505050565b50505050565b610caf611f60565b610cb883610e8e565b610cfa576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161083b565b610d3a8383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061255992505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d90576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e15611f60565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006109f7600567ffffffffffffffff8416612388565b60095473ffffffffffffffffffffffffffffffffffffffff163314801590610ee5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610f1e576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b8483141580610f2d5750848114155b15610f64576040517f568efce200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85811015610ff657610fee878783818110610f8457610f84613e39565b9050602002016020810190610f9991906139fb565b868684818110610fab57610fab613e39565b905060600201803603810190610fc19190614192565b858585818110610fd357610fd3613e39565b905060600201803603810190610fe99190614192565b612653565b600101610f67565b50505050505050565b604080518082019091526060808252602082015261101c8261273d565b6000600a8161103160408601602087016139fb565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff1615159082018190529091506110d85761109960408401602085016139fb565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161083b565b6110e28380613f7d565b9050602014611129576110f58380613f7d565b6040517fa3c8cf0900000000000000000000000000000000000000000000000000000000815260040161083b9291906141f7565b60006111358480613f7d565b810190611142919061420b565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af1158015611223573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112479190614224565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a260405180604001604052806112a48760200160208101906105f191906139fb565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b67ffffffffffffffff8116600090815260076020526040812060609190611368906005016128c9565b90506000815167ffffffffffffffff81111561138657611386613ca7565b6040519080825280602002602001820160405280156113b957816020015b60608152602001906001900390816113a45790505b50905060005b82518110156114a257600860008483815181106113de576113de613e39565b6020026020010151815260200190815260200160002080546113ff90614241565b80601f016020809104026020016040519081016040528092919081815260200182805461142b90614241565b80156114785780601f1061144d57610100808354040283529160200191611478565b820191906000526020600020905b81548152906001019060200180831161145b57829003601f168201915b505050505082828151811061148f5761148f613e39565b60209081029190910101526001016113bf565b509392505050565b60606114b660026128c9565b905090565b6114c3611f60565b6114cc83610e8e565b61150e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161083b565b61154e8282604051611521929190614182565b604080519182900390912067ffffffffffffffff86166000908152600760205291909120600501906128d6565b61158a578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161083b93929190614294565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7683836040516115c69291906141f7565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526109f7906128e2565b67ffffffffffffffff811660009081526007602052604090206004018054606091906116d390614241565b80601f01602080910402602001604051908101604052809291908181526020018280546116ff90614241565b801561174c5780601f106117215761010080835404028352916020019161174c565b820191906000526020600020905b81548152906001019060200180831161172f57829003601f168201915b50505050509050919050565b611760611f60565b73ffffffffffffffffffffffffffffffffffffffff81166117ad576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910161090c565b6060600061183a60056128c9565b90506000815167ffffffffffffffff81111561185857611858613ca7565b604051908082528060200260200182016040528015611881578160200160208202803683370190505b50905060005b82518110156118dd578281815181106118a2576118a2613e39565b60200260200101518282815181106118bc576118bc613e39565b67ffffffffffffffff90921660209283029190910190910152600101611887565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526109f7906128e2565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906119f6575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15611a2f576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b610d3a838383612653565b611a42611f60565b60005b83811015611c2f576000858583818110611a6157611a61613e39565b9050602002016020810190611a7691906139fb565b9050611a8d600567ffffffffffffffff83166128d6565b611acf576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161083b565b67ffffffffffffffff81166000908152600760205260408120611af4906005016128c9565b905060005b8151811015611b6057611b57828281518110611b1757611b17613e39565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206005016128d690919063ffffffff16565b50600101611af9565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611bc96004830182613692565b6005820160008181611bdb82826136cc565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611c1d915050565b60405180910390a15050600101611a45565b5060005b81811015611f45576000838383818110611c4f57611c4f613e39565b9050602002810190611c6191906142b8565b611c6a90614395565b9050611c7b81606001516000612994565b611c8a81608001516000612994565b806040015151600003611cc9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051611ce19060059067ffffffffffffffff16612ad1565b611d265780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161083b565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611ea9908261449d565b5060005b826020015151811015611eed57611ee5836000015184602001518381518110611ed857611ed8613e39565b6020026020010151612559565b600101611ead565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611f3394939291906145b7565b60405180910390a15050600101611c33565b5050505050565b611f54611f60565b611f5d81612add565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611fb1576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611fc661033b60a083016080840161384f565b61202557611fda60a082016080830161384f565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161083b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61207160408401602085016139fb565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121069190614165565b1561213d576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61215561215060408301602084016139fb565b612ba1565b61217561216860408301602084016139fb565b6103db60a0840184613f7d565b6121ba5761218660a0820182613f7d565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161083b9291906141f7565b611f5d6121cd60408301602084016139fb565b8260600135612cc7565b600482015163ffffffff811615612222576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff8216600482015260240161083b565b6008830151600c8401516014850151602085015163ffffffff80851691161461228d5760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161083b565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff1614612322576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161083b565b845167ffffffffffffffff8281169116146123805784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152908216602482015260440161083b565b505050505050565b600081815260018301602052604081205415155b9392505050565b7f00000000000000000000000000000000000000000000000000000000000000006123fa576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561249057600083828151811061241a5761241a613e39565b60200260200101519050612438816002612d0e90919063ffffffff16565b156124875760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016123fd565b5060005b8151811015610d3a5760008282815181106124b1576124b1613e39565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124f55750612551565b612500600282612d30565b1561254f5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612494565b8051600003612594576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff84166000908152600790925260409091206125c69060050182612ad1565b6126005782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161083b929190614650565b6000818152600860205260409020612618838261449d565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516115c6919061381a565b61265c83610e8e565b61269e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161083b565b6126a9826000612994565b67ffffffffffffffff831660009081526007602052604090206126cc9083612d52565b6126d7816000612994565b67ffffffffffffffff831660009081526007602052604090206126fd9060020182612d52565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161273093929190614673565b60405180910390a1505050565b61275061033b60a083016080840161384f565b61276457611fda60a082016080830161384f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6127b060408401602085016139fb565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128459190614165565b1561287c576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61289461288f606083016040840161384f565b612ef4565b6128ac6128a760408301602084016139fb565b612f73565b611f5d6128bf60408301602084016139fb565b82606001356130c1565b6060600061239c83613105565b600061239c8383613160565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261297082606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426129549190614725565b85608001516fffffffffffffffffffffffffffffffff16613253565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b815115612a5f5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806129ea575060408201516fffffffffffffffffffffffffffffffff16155b15612a2357816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161083b9190614738565b8015612a5b576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612a98575060208201516fffffffffffffffffffffffffffffffff1615155b15612a5b57816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161083b9190614738565b600061239c838361327b565b3373ffffffffffffffffffffffffffffffffffffffff821603612b2c576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612baa81610e8e565b612bec576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161083b565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612c6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8f9190614165565b611f5d576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b67ffffffffffffffff82166000908152600760205260409020612a5b90600201827f00000000000000000000000000000000000000000000000000000000000000006132ca565b600061239c8373ffffffffffffffffffffffffffffffffffffffff8416613160565b600061239c8373ffffffffffffffffffffffffffffffffffffffff841661327b565b8154600090612d7b90700100000000000000000000000000000000900463ffffffff1642614725565b90508015612e1d5760018301548354612dc3916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416613253565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612e43916fffffffffffffffffffffffffffffffff908116911661364d565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612730908490614738565b7f000000000000000000000000000000000000000000000000000000000000000015611f5d57612f25600282613663565b611f5d576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161083b565b612f7c81610e8e565b612fbe576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161083b565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015613037573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305b9190614774565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f5d576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161083b565b67ffffffffffffffff82166000908152600760205260409020612a5b90827f00000000000000000000000000000000000000000000000000000000000000006132ca565b60608160000180548060200260200160405190810160405280929190818152602001828054801561174c57602002820191906000526020600020905b8154815260200190600101908083116131415750505050509050919050565b60008181526001830160205260408120548015613249576000613184600183614725565b855490915060009061319890600190614725565b90508082146131fd5760008660000182815481106131b8576131b8613e39565b90600052602060002001549050808760000184815481106131db576131db613e39565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061320e5761320e614791565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506109f7565b60009150506109f7565b60006132728561326384866147c0565b61326d90876147d7565b61364d565b95945050505050565b60008181526001830160205260408120546132c2575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556109f7565b5060006109f7565b825474010000000000000000000000000000000000000000900460ff1615806132f1575081155b156132fb57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061334190700100000000000000000000000000000000900463ffffffff1642614725565b905080156134015781831115613383576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546133bd9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613253565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156134b85773ffffffffffffffffffffffffffffffffffffffff8416613460576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161083b565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161083b565b848310156135cb5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906134fc9082614725565b613506878a614725565b61351091906147d7565b61351a91906147ea565b905073ffffffffffffffffffffffffffffffffffffffff8616613573576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161083b565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161083b565b6135d58584614725565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600081831061365c578161239c565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561239c565b50805461369e90614241565b6000825580601f106136ae575050565b601f016020900490600052602060002090810190611f5d91906136e6565b5080546000825590600052602060002090810190611f5d91905b5b808211156136fb57600081556001016136e7565b5090565b6000806020838503121561371257600080fd5b823567ffffffffffffffff8082111561372a57600080fd5b818501915085601f83011261373e57600080fd5b81358181111561374d57600080fd5b8660208260071b850101111561376257600080fd5b60209290920196919550909350505050565b60006020828403121561378657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461239c57600080fd5b6000815180845260005b818110156137dc576020818501810151868301820152016137c0565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061239c60208301846137b6565b73ffffffffffffffffffffffffffffffffffffffff81168114611f5d57600080fd5b60006020828403121561386157600080fd5b813561239c8161382d565b60006020828403121561387e57600080fd5b813567ffffffffffffffff81111561389557600080fd5b8201610100818503121561239c57600080fd5b67ffffffffffffffff81168114611f5d57600080fd5b6000806000604084860312156138d357600080fd5b83356138de816138a8565b9250602084013567ffffffffffffffff808211156138fb57600080fd5b818601915086601f83011261390f57600080fd5b81358181111561391e57600080fd5b87602082850101111561393057600080fd5b6020830194508093505050509250925092565b60008083601f84011261395557600080fd5b50813567ffffffffffffffff81111561396d57600080fd5b6020830191508360208260051b850101111561398857600080fd5b9250929050565b600080600080604085870312156139a557600080fd5b843567ffffffffffffffff808211156139bd57600080fd5b6139c988838901613943565b909650945060208701359150808211156139e257600080fd5b506139ef87828801613943565b95989497509550505050565b600060208284031215613a0d57600080fd5b813561239c816138a8565b60008083601f840112613a2a57600080fd5b50813567ffffffffffffffff811115613a4257600080fd5b60208301915083602060608302850101111561398857600080fd5b60008060008060008060608789031215613a7657600080fd5b863567ffffffffffffffff80821115613a8e57600080fd5b613a9a8a838b01613943565b90985096506020890135915080821115613ab357600080fd5b613abf8a838b01613a18565b90965094506040890135915080821115613ad857600080fd5b50613ae589828a01613a18565b979a9699509497509295939492505050565b600060208284031215613b0957600080fd5b813567ffffffffffffffff811115613b2057600080fd5b820160a0818503121561239c57600080fd5b602081526000825160406020840152613b4e60608401826137b6565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301604085015261327282826137b6565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613bfe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613bec8583516137b6565b94509285019290850190600101613bb2565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613c5957835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613c27565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613c5957835167ffffffffffffffff1683529284019291840191600101613c81565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613cf957613cf9613ca7565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613d4657613d46613ca7565b604052919050565b8015158114611f5d57600080fd5b80356fffffffffffffffffffffffffffffffff81168114613d7c57600080fd5b919050565b600060608284031215613d9357600080fd5b6040516060810181811067ffffffffffffffff82111715613db657613db6613ca7565b6040529050808235613dc781613d4e565b8152613dd560208401613d5c565b6020820152613de660408401613d5c565b60408201525092915050565b600080600060e08486031215613e0757600080fd5b8335613e12816138a8565b9250613e218560208601613d81565b9150613e308560808601613d81565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff81168114613d7c57600080fd5b600060808284031215613e8e57600080fd5b6040516080810181811067ffffffffffffffff82111715613eb157613eb1613ca7565b60405282358152613ec460208401613e68565b60208201526040830135613ed7816138a8565b60408201526060830135613eea81613d4e565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613f70578135835263ffffffff613f28868401613e68565b168584015283820135613f3a816138a8565b67ffffffffffffffff1683850152606082810135613f5781613d4e565b1515908401526080928301929190910190600101613f0c565b5090979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fb257600080fd5b83018035915067ffffffffffffffff821115613fcd57600080fd5b60200191503681900382131561398857600080fd5b600060408284031215613ff457600080fd5b613ffc613cd6565b8235614007816138a8565b815261401560208401613e68565b60208201529392505050565b600082601f83011261403257600080fd5b813567ffffffffffffffff81111561404c5761404c613ca7565b61407d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613cff565b81815284602083860101111561409257600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156140c157600080fd5b813567ffffffffffffffff808211156140d957600080fd5b90830190604082860312156140ed57600080fd5b6140f5613cd6565b82358281111561410457600080fd5b61411087828601614021565b82525060208301358281111561412557600080fd5b61413187828601614021565b60208301525095945050505050565b60408152600061415360408301856137b6565b828103602084015261327281856137b6565b60006020828403121561417757600080fd5b815161239c81613d4e565b8183823760009101908152919050565b6000606082840312156141a457600080fd5b61239c8383613d81565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610c246020830184866141ae565b60006020828403121561421d57600080fd5b5035919050565b60006020828403121561423657600080fd5b815161239c816138a8565b600181811c9082168061425557607f821691505b60208210810361428e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b67ffffffffffffffff841681526040602082015260006132726040830184866141ae565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126142ec57600080fd5b9190910192915050565b600082601f83011261430757600080fd5b8135602067ffffffffffffffff8083111561432457614324613ca7565b8260051b614333838201613cff565b938452858101830193838101908886111561434d57600080fd5b84880192505b858310156143895782358481111561436b5760008081fd5b6143798a87838c0101614021565b8352509184019190840190614353565b98975050505050505050565b600061012082360312156143a857600080fd5b60405160a0810167ffffffffffffffff82821081831117156143cc576143cc613ca7565b81604052843591506143dd826138a8565b908252602084013590808211156143f357600080fd5b6143ff368387016142f6565b6020840152604085013591508082111561441857600080fd5b5061442536828601614021565b6040830152506144383660608501613d81565b606082015261444a3660c08501613d81565b608082015292915050565b601f821115610d3a576000816000526020600020601f850160051c8101602086101561447e5750805b601f850160051c820191505b818110156123805782815560010161448a565b815167ffffffffffffffff8111156144b7576144b7613ca7565b6144cb816144c58454614241565b84614455565b602080601f83116001811461451e57600084156144e85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612380565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561456b5788860151825594840194600190910190840161454c565b50858210156145a757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526145db818401876137b6565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506146199050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613272565b67ffffffffffffffff83168152604060208201526000610c2460408301846137b6565b67ffffffffffffffff8416815260e081016146bf60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610c24565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109f7576109f76146f6565b606081016109f782848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561478657600080fd5b815161239c8161382d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b80820281158282048414176109f7576109f76146f6565b808201808211156109f7576109f76146f6565b600082614820577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var USDCTokenPoolABI = USDCTokenPoolMetaData.ABI @@ -836,6 +836,18 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetChainRateLimiterConfig( return _USDCTokenPool.Contract.SetChainRateLimiterConfig(&_USDCTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } +func (_USDCTokenPool *USDCTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _USDCTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_USDCTokenPool *USDCTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _USDCTokenPool.Contract.SetChainRateLimiterConfigs(&_USDCTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + +func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { + return _USDCTokenPool.Contract.SetChainRateLimiterConfigs(&_USDCTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) +} + func (_USDCTokenPool *USDCTokenPoolTransactor) SetDomains(opts *bind.TransactOpts, domains []USDCTokenPoolDomainUpdate) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "setDomains", domains) } @@ -3424,6 +3436,8 @@ type USDCTokenPoolInterface interface { SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) + SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) + SetDomains(opts *bind.TransactOpts, domains []USDCTokenPoolDomainUpdate) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index dd2799ba810..3d084f43606 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 @@ -1,13 +1,13 @@ GETH_VERSION: 1.14.11 -burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 642919607d5642aa98713b88f737c918487adba682535cf630b7c7d5fd80dc43 -burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 054d95f302a142f7b64eea27237e0889bee6c9eb8a487579c7279c09646dc42b -burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin c3f723e7f6394297c095a9d9696f1bceec4a2e85b5be2159f7a21d257eb6b480 +burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 76c31f52fe1df85528c08b2e772e37dcf99ca1ec492d83a221abc1d5ec833694 +burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 1c78cd3118b3c9ca82f8cb77ffc1137619ea4e8e503c460f2dafb659d0dd766b +burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin eab9c19ef27b245e5ef0216ab1080c9dd89c96013b7dc978bf610288d5e82b00 ccip_encoding_utils: ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin 9971fc93c34442a0989570d3dab90a125de31e6e60754ad972807ce6ad4dfba0 ccip_home: ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin 02cb75b4274a5be7f4006cf2b72cc09e77eb6dba4c1a9c720af86668ff8ea1df ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin b368699ae7dbee7c21d049a641642837f18ce2cc8d4ece69509f205de673108e ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin aee49c9246d5903e68b175516b3cdfdec5df23e25d53d604cd382b6bc0bf34f7 -lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 1067f557abeb5570f1da7f050ea982ffad0f35dc064e668a8a0e6af128df490c +lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 04b40584830294fb603cc2a250af7d831d05a04650a8c2fc9e3af5a78c471be6 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 ec2d3a92348d8e7b8f0d359b62a45157b9d2c750c01fbcf991826c4392f6e218 mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 @@ -26,7 +26,7 @@ rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../ rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin 941118dfdc6bb042c339cfe8d8e0c7a0b486afb731a785d58a64994e7a13c459 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 397bc7be08c2848c0f4715f90b16206d6367f78ffb7cd48e2b1dfc0ccc5aea26 -token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin da86a1407f31134e7246bde63c80ce8c78ce7d7b44e267f3c1f6030441ff4252 +token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin 793d65f336929becdcf8bc3f2208a5b6de93774215fe2e863bef64df419cfdb0 usdc_reader_tester: ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.bin 672a07c9218fd6ad7c04dde583088b0f5ffc8d55a46f4be1714008dd3409438b -usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin b688126b13353f7aab7481f3f6b8f79cd2cace96be71eace70237d402823493a +usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin a9fef4db2c901302c0293b139eb77017b18da8543b7623e17f2932efbb8e3011 weth9: ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin 2970d79a0ca6dd6279cde130de45e56c8790ed695eae477fb5ba4c1bb75b720d diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 376f70192d2..257670dbaa1 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -503,8 +503,13 @@ func (w TokenPoolWrapper) ApplyChainUpdates(opts *bind.TransactOpts, update []to } func (w TokenPoolWrapper) SetChainRateLimiterConfig(opts *bind.TransactOpts, selector uint64, out token_pool.RateLimiterConfig, in token_pool.RateLimiterConfig) (*types.Transaction, error) { + if w.Latest != nil && w.Latest.PoolInterface != nil { - return w.Latest.PoolInterface.SetChainRateLimiterConfig(opts, selector, out, in) + selectors := []uint64{selector} + out := []token_pool.RateLimiterConfig{out} + in := []token_pool.RateLimiterConfig{in} + + return w.Latest.PoolInterface.SetChainRateLimiterConfigs(opts, selectors, out, in) } if w.V1_4_0 != nil && w.V1_4_0.PoolInterface != nil { return w.V1_4_0.PoolInterface.SetChainRateLimiterConfig(opts, selector,