From 9b0356071aa0e8924768a7fb0236736ac1af891a Mon Sep 17 00:00:00 2001 From: raghu0891 Date: Thu, 21 Nov 2024 16:30:49 +0530 Subject: [PATCH] Base 0 commit --- .changeset/README.md | 8 + .changeset/config.json | 11 + .envrc | 1 + .github/actions/build-test-image/action.yml | 51 + .github/workflows/amarna.yml | 27 + .github/workflows/changesets.yml | 46 + .github/workflows/contracts.yml | 24 + .github/workflows/golangci-lint.yml | 80 + .../workflows/integration-tests-publish.yml | 37 + .github/workflows/integration-tests-smoke.yml | 140 + .github/workflows/integration-tests-soak.yml | 121 + .github/workflows/integration_contracts.yml | 23 + .github/workflows/integration_gauntlet.yml | 26 + .github/workflows/lint.yml | 26 + .../workflows/monitoring-build-push-ecr.yml | 52 + .github/workflows/relayer.yml | 29 + .../release/starknet-gauntlet-cli.yml | 37 + .../workflows/release/starknet-relayer.yml | 31 + .gitignore | 164 + .golangci.yml | 83 + .helm-repositories.yaml | 30 + .prettierignore | 17 + .prettierrc.json | 21 + .tool-versions | 18 + CHANGELOG.md | 19 + CONTRIBUTING.md | 43 + LICENSE | 21 + Makefile | 267 + README.md | 3 + contracts/.gitignore | 3 + contracts/.helix/languages.toml | 5 + contracts/constraints.txt | 0 contracts/hardhat.config.ts | 71 + contracts/package.json | 33 + contracts/requirements.txt | 6 + .../cairo/access/IAccessController.cairo | 10 + .../SimpleReadAccessController/library.cairo | 63 + .../simple_read_access_controller.cairo | 39 + .../SimpleWriteAccessController/library.cairo | 158 + .../simple_write_access_controller.cairo | 29 + .../src/plugin/cairo/access/ownable.cairo | 117 + .../SequencerUptimeFeed/library.cairo | 269 + .../sequencer_uptime_feed.cairo | 99 + .../cairo/example/Aggregator_consumer.cairo | 32 + .../cairo/introspection/ITypeAndVersion.cairo | 7 + .../src/plugin/cairo/ocr2/IAggregator.cairo | 52 + .../src/plugin/cairo/ocr2/aggregator.cairo | 1232 +++ .../plugin/cairo/ocr2/aggregator_proxy.cairo | 225 + .../cairo/ocr2/mocks/MockAggregator.cairo | 94 + .../plugin/cairo/token/ERC677/IERC677.cairo | 13 + .../cairo/token/ERC677/IERC677Receiver.cairo | 12 + .../src/plugin/cairo/token/ERC677/README.md | 18 + .../plugin/cairo/token/ERC677/library.cairo | 38 + .../token/ERC677/mock/link_receiver.cairo | 105 + .../ERC677/mock/not_erc677_compatible.cairo | 8 + .../ERC677/mock/token677_receiver_mock.cairo | 92 + .../plugin/cairo/token/IMintableToken.cairo | 12 + .../token/starkgate/presets/link_token.cairo | 168 + contracts/src/plugin/cairo/utils.cairo | 18 + .../solidity/emergency/StarknetValidator.sol | 288 + .../solidity/mocks/MockStarknetMessaging.sol | 46 + contracts/test/access/behavior/ownable.ts | 114 + contracts/test/constants.ts | 2 + .../test/emergency/StarknetValidator.test.ts | 641 ++ .../emergency/sequencer_uptime_feed.test.ts | 171 + contracts/test/ocr2/aggregator.test.ts | 468 + contracts/test/ocr2/aggregator_proxy.test.ts | 110 + contracts/test/token/ERC677/ERC677.test.ts | 153 + .../test/token/ERC677/link-receiver.test.ts | 231 + .../test/token/starkgate/behavior/ERC20.ts | 275 + .../test/token/starkgate/link_token.test.ts | 30 + contracts/tsconfig.json | 18 + contracts/vendor/starkware-libs/README.md | 6 + .../starknet/solidity/IStarknetMessaging.sol | 54 + .../solidity/IStarknetMessagingEvents.sol | 51 + .../solidity/libraries/NamedStorage.sol | 93 + .../starknet/solidity/IStarknetMessaging.sol | 54 + .../solidity/IStarknetMessagingEvents.sol | 51 + .../starknet/solidity/StarknetMessaging.sol | 178 + .../std_contracts/ERC20/permitted.cairo | 39 + contracts/yarn.lock | 3700 ++++++++ docs/README.md | 16 + docs/assets/godepgraph_starknet_relayer.png | Bin 0 -> 76856 bytes docs/emergency-protocol/README.md | 142 + docs/gauntlet/README.md | 15 + docs/gauntlet/getting_started.md | 73 + docs/getting-started.md | 30 + docs/integration-tests/README.md | 241 + docs/integration-tests/testing.md | 5 + docs/kubernetes.md | 19 + .../contracts/aggregator-consumer/.gitignore | 2 + .../contracts/Aggregator_consumer.cairo | 32 + .../contracts/MockAggregator.cairo | 8 + .../Price_Consumer_With_Sequencer_Check.cairo | 74 + .../aggregator-consumer/getting_start.md | 25 + .../aggregator-consumer/hardhat.config.ts | 34 + .../aggregator-consumer/package.json | 28 + .../scripts/consumerValidator.ts | 127 + .../scripts/deploy_accounts.ts | 60 + .../scripts/deploy_contracts.ts | 93 + .../scripts/getLatestPrice.ts | 54 + .../scripts/readContinuously.ts | 47 + .../scripts/readDecimals.ts | 28 + .../scripts/readLatestRound.ts | 36 + .../scripts/updateLatestRound.ts | 89 + .../aggregator-consumer/scripts/utils.ts | 79 + .../test/mock/Aggregator_consumer.test.ts | 83 + .../test/mock/Examples_test.test.ts | 93 + .../aggregator-consumer/tsconfig.json | 15 + examples/contracts/proxy-consumer/.gitignore | 2 + examples/contracts/proxy-consumer/README.md | 36 + .../contracts/Proxy_consumer.cairo | 50 + .../contracts/aggregator_proxy_abi.json | 451 + .../proxy-consumer/hardhat.config.ts | 22 + .../contracts/proxy-consumer/package.json | 18 + .../proxy-consumer/scripts/deployConsumer.ts | 60 + .../proxy-consumer/scripts/readLatestRound.ts | 81 + .../scripts/readLatestRoundOffChain.ts | 39 + examples/spec/ocr2-bootstrap.spec.toml | 10 + examples/spec/ocr2-oracle-simple.spec.toml | 45 + examples/spec/ocr2-oracle.spec.toml | 79 + flake.lock | 43 + flake.nix | 16 + integration-tests/README.md | 7 + integration-tests/common/common.go | 256 + integration-tests/common/gauntlet_common.go | 142 + integration-tests/common/test_common.go | 357 + integration-tests/framework.yaml | 19 + integration-tests/go.mod | 381 + integration-tests/go.sum | 2093 +++++ .../infra_deployments/deployer_test.go | 100 + integration-tests/networks.yaml | 67 + integration-tests/package.json | 7 + integration-tests/scripts/buildTestImage | 41 + integration-tests/scripts/buildTests | 29 + integration-tests/scripts/entrypoint | 17 + integration-tests/smoke/ocr2_test.go | 64 + integration-tests/soak/ocr2_test.go | 58 + integration-tests/test.Dockerfile | 9 + .../test.Dockerfile.dockerignore | 24 + integration-tests/utils/common.go | 24 + jest.config.ts | 37 + monitoring/README.md | 91 + monitoring/cmd/monitoring/main.go | 80 + monitoring/go.mod | 71 + monitoring/go.sum | 353 + monitoring/ops/Dockerfile | 29 + monitoring/ops/docker-compose.yml | 49 + monitoring/pkg/monitoring/config_chain.go | 117 + monitoring/pkg/monitoring/config_feed.go | 110 + monitoring/pkg/monitoring/config_node.go | 40 + .../pkg/monitoring/exporter_prometheus.go | 103 + monitoring/pkg/monitoring/metrics.go | 91 + monitoring/pkg/monitoring/source_envelope.go | 180 + .../pkg/monitoring/source_envelope_test.go | 185 + monitoring/pkg/monitoring/source_proxy.go | 56 + .../pkg/monitoring/source_proxy_test.go | 53 + monitoring/pkg/monitoring/source_txresults.go | 63 + .../pkg/monitoring/source_txresults_test.go | 60 + monitoring/pkg/monitoring/testutils.go | 58 + nix.conf | 1 + ops/README.md | 11 + ops/charts/devnet/.helmignore | 21 + ops/charts/devnet/Chart.yaml | 7 + ops/charts/devnet/templates/NOTES.txt | 1 + ops/charts/devnet/templates/_helpers.tpl | 16 + ops/charts/devnet/templates/deployment.yaml | 72 + ops/charts/devnet/templates/service.yaml | 16 + ops/charts/devnet/values.yaml | 16 + ops/charts/hardhat/.helmignore | 21 + ops/charts/hardhat/Chart.yaml | 6 + ops/charts/hardhat/templates/NOTES.txt | 1 + ops/charts/hardhat/templates/_helpers.tpl | 16 + ops/charts/hardhat/templates/deployment.yaml | 45 + ops/charts/hardhat/templates/service.yaml | 16 + ops/charts/hardhat/values.yaml | 14 + ops/devnet/devnet.go | 126 + ops/devnet/environment.go | 107 + ops/gauntlet/gauntlet_starknet.go | 213 + ops/go.mod | 149 + ops/go.sum | 517 ++ ops/hardhat/environment.go | 108 + ops/localenv/README.md | 49 + ops/localenv/main.go | 123 + ops/plugin-starknet.yaml | 30 + ops/scripts/devnet-hardhat-down.sh | 28 + ops/scripts/devnet-hardhat.sh | 23 + ops/test_helpers.go | 112 + ops/utils/project_path.go | 16 + package.json | 61 + .../hardhat.config.ts | 29 + .../integration-eqlabs-multisig/package.json | 24 + .../test/Multisig.test.ts | 88 + .../integration-eqlabs-multisig/tsconfig.json | 6 + packages-ts/starknet-gauntlet-argent/LICENSE | 21 + .../starknet-gauntlet-argent/README.md | 31 + .../starknet-gauntlet-argent/package.json | 31 + .../src/commands/account/deploy.ts | 49 + .../src/commands/account/index.ts | 4 + .../src/commands/account/initialize.ts | 84 + .../src/commands/index.ts | 3 + .../starknet-gauntlet-argent/src/index.ts | 3 + .../src/lib/categories.ts | 5 + .../src/lib/contracts.ts | 14 + .../starknet-gauntlet-argent/tsconfig.json | 9 + packages-ts/starknet-gauntlet-cli/LICENSE | 21 + packages-ts/starknet-gauntlet-cli/README.md | 39 + .../networks/.env.goerli | 7 + .../starknet-gauntlet-cli/networks/.env.local | 1 + .../starknet-gauntlet-cli/package.json | 38 + .../starknet-gauntlet-cli/src/index.ts | 174 + .../starknet-gauntlet-cli/tsconfig.json | 9 + .../LICENSE | 21 + .../README.md | 93 + .../package.json | 32 + .../src/commands/index.ts | 9 + .../commands/sequencerUptimeFeed/deploy.ts | 60 + .../src/commands/sequencerUptimeFeed/index.ts | 7 + .../sequencerUptimeFeed/inspection/index.ts | 3 + .../inspection/inspection.ts | 57 + .../sequencerUptimeFeed/setL1Sender.ts | 49 + .../starknetValidator/acceptOwnership.ts | 34 + .../commands/starknetValidator/addAccess.ts | 47 + .../src/commands/starknetValidator/deploy.ts | 113 + .../src/commands/starknetValidator/index.ts | 7 + .../starknetValidator/transferOwnership.ts | 40 + .../commands/starknetValidator/validate.ts | 90 + .../src/index.ts | 1 + .../src/lib/categories.ts | 6 + .../src/lib/contracts.ts | 29 + .../test/commands/sequencerUptimeFeed.test.ts | 67 + .../tsconfig.json | 9 + packages-ts/starknet-gauntlet-example/LICENSE | 21 + .../starknet-gauntlet-example/README.md | 29 + .../contract_artifacts/abi/example.json | 4875 +++++++++++ .../starknet-gauntlet-example/example.cairo | 32 + .../starknet-gauntlet-example/package.json | 32 + .../src/commands/example/deploy.ts | 45 + .../src/commands/example/increaseBalance.ts | 21 + .../src/commands/example/index.ts | 5 + .../src/commands/example/inspection/index.ts | 3 + .../commands/example/inspection/inspect.ts | 42 + .../src/commands/index.ts | 7 + .../starknet-gauntlet-example/src/index.ts | 3 + .../src/lib/categories.ts | 5 + .../src/lib/contracts.ts | 14 + .../test/commands/example.test.ts | 102 + .../test/utils/index.ts | 29 + .../starknet-gauntlet-example/tsconfig.json | 9 + packages-ts/starknet-gauntlet-ledger/LICENSE | 21 + .../starknet-gauntlet-ledger/package.json | 32 + .../starknet-gauntlet-ledger/src/index.ts | 140 + .../test/ledger-path-regex.test.ts | 35 + .../starknet-gauntlet-ledger/tsconfig.json | 9 + .../starknet-gauntlet-multisig/LICENSE | 21 + .../starknet-gauntlet-multisig/README.md | 72 + .../starknet-gauntlet-multisig/package.json | 32 + .../src/commands/index.ts | 1 + .../src/commands/multisig/deploy.ts | 83 + .../src/commands/multisig/index.ts | 8 + .../src/commands/multisig/inspection/index.ts | 3 + .../multisig/inspection/inspection.ts | 44 + .../src/commands/multisig/setSigners.ts | 57 + .../src/commands/multisig/setThreshold.ts | 65 + .../starknet-gauntlet-multisig/src/index.ts | 4 + .../src/lib/categories.ts | 3 + .../src/lib/contracts.ts | 18 + .../src/lib/utils.ts | 13 + .../src/wrapper/index.ts | 288 + .../src/wrapper/types.ts | 21 + .../test/multisig/multisig.test.ts | 223 + .../starknet-gauntlet-multisig/tsconfig.json | 9 + packages-ts/starknet-gauntlet-ocr2/LICENSE | 21 + packages-ts/starknet-gauntlet-ocr2/README.md | 57 + .../starknet-gauntlet-ocr2/package.json | 33 + .../src/commands/accessController/deploy.ts | 36 + .../src/commands/accessController/index.ts | 3 + .../src/commands/example/deploy.ts | 49 + .../src/commands/example/index.ts | 5 + .../src/commands/example/inspect.ts | 75 + .../src/commands/index.ts | 27 + .../src/commands/ocr2/addAccess.ts | 62 + .../src/commands/ocr2/deploy.ts | 48 + .../src/commands/ocr2/disableAccessCheck.ts | 32 + .../src/commands/ocr2/index.ts | 9 + .../src/commands/ocr2/inspection/inspect.ts | 41 + .../src/commands/ocr2/setBilling.ts | 43 + .../src/commands/ocr2/setConfig.ts | 89 + .../src/commands/proxy/confirmAggregator.ts | 63 + .../src/commands/proxy/deploy.ts | 65 + .../src/commands/proxy/index.ts | 7 + .../src/commands/proxy/inspection/inspect.ts | 61 + .../src/commands/proxy/proposeAggregator.ts | 63 + .../starknet-gauntlet-ocr2/src/index.ts | 3 + .../src/lib/categories.ts | 5 + .../src/lib/contracts.ts | 46 + .../src/lib/encoding.ts | 98 + .../test/commands/access_controller.test.ts | 30 + .../test/commands/ocr2.test.ts | 199 + .../test/commands/proxy.test.ts | 125 + .../test/lib/encoding.test.ts | 25 + .../starknet-gauntlet-ocr2/tsconfig.json | 9 + packages-ts/starknet-gauntlet-oz/LICENSE | 21 + packages-ts/starknet-gauntlet-oz/README.md | 23 + packages-ts/starknet-gauntlet-oz/package.json | 32 + .../src/commands/account/deploy.ts | 91 + .../src/commands/account/index.ts | 2 + .../src/commands/index.ts | 3 + packages-ts/starknet-gauntlet-oz/src/index.ts | 3 + .../src/lib/categories.ts | 3 + .../starknet-gauntlet-oz/src/lib/contracts.ts | 32 + .../test/commands/account.test.ts | 44 + .../starknet-gauntlet-oz/tsconfig.json | 9 + packages-ts/starknet-gauntlet-token/LICENSE | 21 + packages-ts/starknet-gauntlet-token/README.md | 31 + .../starknet-gauntlet-token/package.json | 34 + .../src/commands/index.ts | 5 + .../src/commands/inspection/balanceOf.ts | 71 + .../src/commands/inspection/index.ts | 3 + .../src/commands/token/deploy.ts | 62 + .../src/commands/token/index.ts | 5 + .../src/commands/token/mint.ts | 72 + .../src/commands/token/transfer.ts | 69 + .../starknet-gauntlet-token/src/index.ts | 3 + .../src/lib/categories.ts | 5 + .../src/lib/contracts.ts | 37 + .../test/commands/token.test.ts | 135 + .../starknet-gauntlet-token/tsconfig.json | 9 + packages-ts/starknet-gauntlet/LICENSE | 21 + packages-ts/starknet-gauntlet/README.md | 1 + packages-ts/starknet-gauntlet/package.json | 32 + .../src/commands/base/command.ts | 28 + .../src/commands/base/executeCommand.ts | 237 + .../src/commands/base/index.ts | 3 + .../src/commands/base/inspectionCommand.ts | 156 + .../src/dependencies/index.ts | 24 + .../starknet-gauntlet/src/events/index.ts | 1 + .../src/events/subscription.ts | 30 + packages-ts/starknet-gauntlet/src/index.ts | 13 + .../starknet-gauntlet/src/provider/index.ts | 112 + .../src/transaction/index.ts | 10 + .../starknet-gauntlet/src/utils/address.ts | 10 + .../starknet-gauntlet/src/utils/index.ts | 1 + .../src/wallet/defaultWallet.ts | 24 + .../starknet-gauntlet/src/wallet/index.ts | 13 + .../test/__mocks__/example.json | 7501 ++++++++++++++++ .../test/commands/execute.test.ts | 115 + .../starknet-gauntlet/test/utils/index.ts | 83 + .../starknet-gauntlet/test/utils/network.ts | 76 + packages-ts/starknet-gauntlet/tsconfig.json | 9 + packages-ts/starknet/.gitignore | 3 + packages-ts/starknet/hardhat.config.ts | 26 + packages-ts/starknet/package.json | 29 + packages-ts/starknet/src/account.ts | 100 + packages-ts/starknet/src/index.ts | 2 + packages-ts/starknet/src/utils.ts | 68 + packages-ts/starknet/test/fundAccount.test.ts | 73 + packages-ts/starknet/tsconfig.json | 15 + relayer/go.mod | 51 + relayer/go.sum | 214 + relayer/package.json | 7 + relayer/pkg/plugin/chain/chain.go | 23 + relayer/pkg/plugin/config/config.go | 78 + relayer/pkg/plugin/db/db.go | 14 + relayer/pkg/plugin/keys/key.go | 104 + relayer/pkg/plugin/keys/keystore.go | 7 + relayer/pkg/plugin/keys/mocks/keystore.go | 50 + relayer/pkg/plugin/keys/ocr2key.go | 143 + relayer/pkg/plugin/keys/ocr2key_test.go | 178 + relayer/pkg/plugin/keys/utils.go | 60 + relayer/pkg/plugin/ocr2/client.go | 252 + relayer/pkg/plugin/ocr2/client_test.go | 124 + relayer/pkg/plugin/ocr2/config.go | 8 + relayer/pkg/plugin/ocr2/config_digester.go | 104 + .../pkg/plugin/ocr2/config_digester_test.go | 67 + relayer/pkg/plugin/ocr2/contract_cache.go | 159 + relayer/pkg/plugin/ocr2/contract_reader.go | 125 + .../pkg/plugin/ocr2/contract_transmitter.go | 113 + relayer/pkg/plugin/ocr2/events.go | 242 + relayer/pkg/plugin/ocr2/events_test.go | 154 + .../plugin/ocr2/medianreport/onchainconfig.go | 115 + .../ocr2/medianreport/onchainconfig_test.go | 91 + .../pkg/plugin/ocr2/medianreport/report.go | 159 + .../ocr2/medianreport/report_fuzz_test.go | 35 + .../plugin/ocr2/medianreport/report_test.go | 155 + relayer/pkg/plugin/ocr2/medianreport/utils.go | 15 + relayer/pkg/plugin/ocr2/mocks/OCR2Reader.go | 203 + relayer/pkg/plugin/ocr2/providers.go | 153 + ...bf537d4d81f389524539f402d13aa01f93a65ac7e9 | 2 + ...d5c9b9bea24ec8bb8ee322e03d12b98b6a90367d45 | 2 + ...49782fb2ea099a8dba26e80f2652b621cd5c180bb2 | 2 + ...8b22bf71aceb4f9ecd5849401dbc4f549fb9233e53 | 2 + .../pkg/plugin/ocr2/transmissions_cache.go | 152 + relayer/pkg/plugin/ocr2/types.go | 96 + relayer/pkg/plugin/ocr2/types_test.go | 40 + relayer/pkg/plugin/ocr2/utils.go | 27 + relayer/pkg/plugin/relay.go | 117 + relayer/pkg/plugin/txm/config.go | 12 + relayer/pkg/plugin/txm/mocks/config.go | 71 + relayer/pkg/plugin/txm/test_helpers.go | 90 + relayer/pkg/plugin/txm/txm.go | 231 + relayer/pkg/plugin/txm/txm_test.go | 108 + relayer/pkg/plugin/types.go | 8 + relayer/pkg/starknet/client.go | 297 + relayer/pkg/starknet/client_test.go | 69 + relayer/pkg/starknet/events.go | 12 + relayer/pkg/starknet/events_test.go | 35 + relayer/pkg/starknet/mocks/Reader.go | 193 + ...dc251e4b7cc673a85738e29a86310d186cd8e2ce1b | 2 + relayer/pkg/starknet/types.go | 11 + relayer/pkg/starknet/utils.go | 169 + relayer/pkg/starknet/utils_fuzz_test.go | 21 + relayer/pkg/starknet/utils_test.go | 142 + scripts/generate-codegraph.sh | 58 + shell.nix | 44 + tsconfig.base.json | 39 + tsconfig.json | 40 + yarn.lock | 7728 +++++++++++++++++ 418 files changed, 53253 insertions(+) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json create mode 100644 .envrc create mode 100644 .github/actions/build-test-image/action.yml create mode 100644 .github/workflows/amarna.yml create mode 100644 .github/workflows/changesets.yml create mode 100644 .github/workflows/contracts.yml create mode 100644 .github/workflows/golangci-lint.yml create mode 100644 .github/workflows/integration-tests-publish.yml create mode 100644 .github/workflows/integration-tests-smoke.yml create mode 100644 .github/workflows/integration-tests-soak.yml create mode 100644 .github/workflows/integration_contracts.yml create mode 100644 .github/workflows/integration_gauntlet.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/monitoring-build-push-ecr.yml create mode 100644 .github/workflows/relayer.yml create mode 100644 .github/workflows/release/starknet-gauntlet-cli.yml create mode 100644 .github/workflows/release/starknet-relayer.yml create mode 100644 .gitignore create mode 100644 .golangci.yml create mode 100644 .helm-repositories.yaml create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 .tool-versions create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 contracts/.gitignore create mode 100644 contracts/.helix/languages.toml create mode 100644 contracts/constraints.txt create mode 100644 contracts/hardhat.config.ts create mode 100644 contracts/package.json create mode 100644 contracts/requirements.txt create mode 100644 contracts/src/plugin/cairo/access/IAccessController.cairo create mode 100644 contracts/src/plugin/cairo/access/SimpleReadAccessController/library.cairo create mode 100644 contracts/src/plugin/cairo/access/SimpleReadAccessController/simple_read_access_controller.cairo create mode 100644 contracts/src/plugin/cairo/access/SimpleWriteAccessController/library.cairo create mode 100644 contracts/src/plugin/cairo/access/SimpleWriteAccessController/simple_write_access_controller.cairo create mode 100644 contracts/src/plugin/cairo/access/ownable.cairo create mode 100644 contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/library.cairo create mode 100644 contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/sequencer_uptime_feed.cairo create mode 100644 contracts/src/plugin/cairo/example/Aggregator_consumer.cairo create mode 100644 contracts/src/plugin/cairo/introspection/ITypeAndVersion.cairo create mode 100644 contracts/src/plugin/cairo/ocr2/IAggregator.cairo create mode 100644 contracts/src/plugin/cairo/ocr2/aggregator.cairo create mode 100644 contracts/src/plugin/cairo/ocr2/aggregator_proxy.cairo create mode 100644 contracts/src/plugin/cairo/ocr2/mocks/MockAggregator.cairo create mode 100644 contracts/src/plugin/cairo/token/ERC677/IERC677.cairo create mode 100644 contracts/src/plugin/cairo/token/ERC677/IERC677Receiver.cairo create mode 100644 contracts/src/plugin/cairo/token/ERC677/README.md create mode 100644 contracts/src/plugin/cairo/token/ERC677/library.cairo create mode 100644 contracts/src/plugin/cairo/token/ERC677/mock/link_receiver.cairo create mode 100644 contracts/src/plugin/cairo/token/ERC677/mock/not_erc677_compatible.cairo create mode 100644 contracts/src/plugin/cairo/token/ERC677/mock/token677_receiver_mock.cairo create mode 100644 contracts/src/plugin/cairo/token/IMintableToken.cairo create mode 100644 contracts/src/plugin/cairo/token/starkgate/presets/link_token.cairo create mode 100644 contracts/src/plugin/cairo/utils.cairo create mode 100644 contracts/src/plugin/solidity/emergency/StarknetValidator.sol create mode 100644 contracts/src/plugin/solidity/mocks/MockStarknetMessaging.sol create mode 100644 contracts/test/access/behavior/ownable.ts create mode 100644 contracts/test/constants.ts create mode 100644 contracts/test/emergency/StarknetValidator.test.ts create mode 100644 contracts/test/emergency/sequencer_uptime_feed.test.ts create mode 100644 contracts/test/ocr2/aggregator.test.ts create mode 100644 contracts/test/ocr2/aggregator_proxy.test.ts create mode 100644 contracts/test/token/ERC677/ERC677.test.ts create mode 100644 contracts/test/token/ERC677/link-receiver.test.ts create mode 100644 contracts/test/token/starkgate/behavior/ERC20.ts create mode 100644 contracts/test/token/starkgate/link_token.test.ts create mode 100644 contracts/tsconfig.json create mode 100644 contracts/vendor/starkware-libs/README.md create mode 100644 contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessaging.sol create mode 100644 contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol create mode 100644 contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/solidity/libraries/NamedStorage.sol create mode 100644 contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessaging.sol create mode 100644 contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol create mode 100644 contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/StarknetMessaging.sol create mode 100644 contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/std_contracts/ERC20/permitted.cairo create mode 100644 contracts/yarn.lock create mode 100644 docs/README.md create mode 100644 docs/assets/godepgraph_starknet_relayer.png create mode 100644 docs/emergency-protocol/README.md create mode 100644 docs/gauntlet/README.md create mode 100644 docs/gauntlet/getting_started.md create mode 100644 docs/getting-started.md create mode 100644 docs/integration-tests/README.md create mode 100644 docs/integration-tests/testing.md create mode 100644 docs/kubernetes.md create mode 100644 examples/contracts/aggregator-consumer/.gitignore create mode 100644 examples/contracts/aggregator-consumer/contracts/Aggregator_consumer.cairo create mode 100644 examples/contracts/aggregator-consumer/contracts/MockAggregator.cairo create mode 100644 examples/contracts/aggregator-consumer/contracts/Price_Consumer_With_Sequencer_Check.cairo create mode 100644 examples/contracts/aggregator-consumer/getting_start.md create mode 100644 examples/contracts/aggregator-consumer/hardhat.config.ts create mode 100644 examples/contracts/aggregator-consumer/package.json create mode 100644 examples/contracts/aggregator-consumer/scripts/consumerValidator.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/deploy_accounts.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/deploy_contracts.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/getLatestPrice.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/readContinuously.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/readDecimals.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/readLatestRound.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/updateLatestRound.ts create mode 100644 examples/contracts/aggregator-consumer/scripts/utils.ts create mode 100644 examples/contracts/aggregator-consumer/test/mock/Aggregator_consumer.test.ts create mode 100644 examples/contracts/aggregator-consumer/test/mock/Examples_test.test.ts create mode 100644 examples/contracts/aggregator-consumer/tsconfig.json create mode 100644 examples/contracts/proxy-consumer/.gitignore create mode 100644 examples/contracts/proxy-consumer/README.md create mode 100644 examples/contracts/proxy-consumer/contracts/Proxy_consumer.cairo create mode 100644 examples/contracts/proxy-consumer/contracts/aggregator_proxy_abi.json create mode 100644 examples/contracts/proxy-consumer/hardhat.config.ts create mode 100644 examples/contracts/proxy-consumer/package.json create mode 100644 examples/contracts/proxy-consumer/scripts/deployConsumer.ts create mode 100644 examples/contracts/proxy-consumer/scripts/readLatestRound.ts create mode 100644 examples/contracts/proxy-consumer/scripts/readLatestRoundOffChain.ts create mode 100644 examples/spec/ocr2-bootstrap.spec.toml create mode 100644 examples/spec/ocr2-oracle-simple.spec.toml create mode 100644 examples/spec/ocr2-oracle.spec.toml create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 integration-tests/README.md create mode 100644 integration-tests/common/common.go create mode 100644 integration-tests/common/gauntlet_common.go create mode 100644 integration-tests/common/test_common.go create mode 100644 integration-tests/framework.yaml create mode 100644 integration-tests/go.mod create mode 100644 integration-tests/go.sum create mode 100644 integration-tests/infra_deployments/deployer_test.go create mode 100644 integration-tests/networks.yaml create mode 100644 integration-tests/package.json create mode 100755 integration-tests/scripts/buildTestImage create mode 100755 integration-tests/scripts/buildTests create mode 100755 integration-tests/scripts/entrypoint create mode 100644 integration-tests/smoke/ocr2_test.go create mode 100644 integration-tests/soak/ocr2_test.go create mode 100644 integration-tests/test.Dockerfile create mode 100644 integration-tests/test.Dockerfile.dockerignore create mode 100644 integration-tests/utils/common.go create mode 100644 jest.config.ts create mode 100644 monitoring/README.md create mode 100644 monitoring/cmd/monitoring/main.go create mode 100644 monitoring/go.mod create mode 100644 monitoring/go.sum create mode 100644 monitoring/ops/Dockerfile create mode 100644 monitoring/ops/docker-compose.yml create mode 100644 monitoring/pkg/monitoring/config_chain.go create mode 100644 monitoring/pkg/monitoring/config_feed.go create mode 100644 monitoring/pkg/monitoring/config_node.go create mode 100644 monitoring/pkg/monitoring/exporter_prometheus.go create mode 100644 monitoring/pkg/monitoring/metrics.go create mode 100644 monitoring/pkg/monitoring/source_envelope.go create mode 100644 monitoring/pkg/monitoring/source_envelope_test.go create mode 100644 monitoring/pkg/monitoring/source_proxy.go create mode 100644 monitoring/pkg/monitoring/source_proxy_test.go create mode 100644 monitoring/pkg/monitoring/source_txresults.go create mode 100644 monitoring/pkg/monitoring/source_txresults_test.go create mode 100644 monitoring/pkg/monitoring/testutils.go create mode 100644 nix.conf create mode 100644 ops/README.md create mode 100644 ops/charts/devnet/.helmignore create mode 100644 ops/charts/devnet/Chart.yaml create mode 100644 ops/charts/devnet/templates/NOTES.txt create mode 100644 ops/charts/devnet/templates/_helpers.tpl create mode 100644 ops/charts/devnet/templates/deployment.yaml create mode 100644 ops/charts/devnet/templates/service.yaml create mode 100644 ops/charts/devnet/values.yaml create mode 100644 ops/charts/hardhat/.helmignore create mode 100644 ops/charts/hardhat/Chart.yaml create mode 100644 ops/charts/hardhat/templates/NOTES.txt create mode 100644 ops/charts/hardhat/templates/_helpers.tpl create mode 100644 ops/charts/hardhat/templates/deployment.yaml create mode 100644 ops/charts/hardhat/templates/service.yaml create mode 100644 ops/charts/hardhat/values.yaml create mode 100644 ops/devnet/devnet.go create mode 100644 ops/devnet/environment.go create mode 100644 ops/gauntlet/gauntlet_starknet.go create mode 100644 ops/go.mod create mode 100644 ops/go.sum create mode 100644 ops/hardhat/environment.go create mode 100644 ops/localenv/README.md create mode 100644 ops/localenv/main.go create mode 100644 ops/plugin-starknet.yaml create mode 100755 ops/scripts/devnet-hardhat-down.sh create mode 100755 ops/scripts/devnet-hardhat.sh create mode 100644 ops/test_helpers.go create mode 100644 ops/utils/project_path.go create mode 100644 package.json create mode 100644 packages-ts/integration-eqlabs-multisig/hardhat.config.ts create mode 100644 packages-ts/integration-eqlabs-multisig/package.json create mode 100644 packages-ts/integration-eqlabs-multisig/test/Multisig.test.ts create mode 100644 packages-ts/integration-eqlabs-multisig/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-argent/LICENSE create mode 100644 packages-ts/starknet-gauntlet-argent/README.md create mode 100644 packages-ts/starknet-gauntlet-argent/package.json create mode 100644 packages-ts/starknet-gauntlet-argent/src/commands/account/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-argent/src/commands/account/index.ts create mode 100644 packages-ts/starknet-gauntlet-argent/src/commands/account/initialize.ts create mode 100644 packages-ts/starknet-gauntlet-argent/src/commands/index.ts create mode 100644 packages-ts/starknet-gauntlet-argent/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-argent/src/lib/categories.ts create mode 100644 packages-ts/starknet-gauntlet-argent/src/lib/contracts.ts create mode 100644 packages-ts/starknet-gauntlet-argent/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-cli/LICENSE create mode 100644 packages-ts/starknet-gauntlet-cli/README.md create mode 100644 packages-ts/starknet-gauntlet-cli/networks/.env.goerli create mode 100644 packages-ts/starknet-gauntlet-cli/networks/.env.local create mode 100644 packages-ts/starknet-gauntlet-cli/package.json create mode 100644 packages-ts/starknet-gauntlet-cli/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-cli/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/LICENSE create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/README.md create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/package.json create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/index.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/index.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/index.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/inspection.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/setL1Sender.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/acceptOwnership.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/addAccess.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/index.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/transferOwnership.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/validate.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/lib/categories.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/src/lib/contracts.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/test/commands/sequencerUptimeFeed.test.ts create mode 100644 packages-ts/starknet-gauntlet-emergency-protocol/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-example/LICENSE create mode 100644 packages-ts/starknet-gauntlet-example/README.md create mode 100644 packages-ts/starknet-gauntlet-example/contract_artifacts/abi/example.json create mode 100644 packages-ts/starknet-gauntlet-example/example.cairo create mode 100644 packages-ts/starknet-gauntlet-example/package.json create mode 100644 packages-ts/starknet-gauntlet-example/src/commands/example/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/commands/example/increaseBalance.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/commands/example/index.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/commands/example/inspection/index.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/commands/example/inspection/inspect.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/commands/index.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/lib/categories.ts create mode 100644 packages-ts/starknet-gauntlet-example/src/lib/contracts.ts create mode 100644 packages-ts/starknet-gauntlet-example/test/commands/example.test.ts create mode 100644 packages-ts/starknet-gauntlet-example/test/utils/index.ts create mode 100644 packages-ts/starknet-gauntlet-example/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-ledger/LICENSE create mode 100644 packages-ts/starknet-gauntlet-ledger/package.json create mode 100644 packages-ts/starknet-gauntlet-ledger/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-ledger/test/ledger-path-regex.test.ts create mode 100644 packages-ts/starknet-gauntlet-ledger/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-multisig/LICENSE create mode 100644 packages-ts/starknet-gauntlet-multisig/README.md create mode 100644 packages-ts/starknet-gauntlet-multisig/package.json create mode 100644 packages-ts/starknet-gauntlet-multisig/src/commands/index.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/commands/multisig/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/commands/multisig/index.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/index.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/inspection.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setSigners.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setThreshold.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/lib/categories.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/lib/contracts.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/lib/utils.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/wrapper/index.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/src/wrapper/types.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/test/multisig/multisig.test.ts create mode 100644 packages-ts/starknet-gauntlet-multisig/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-ocr2/LICENSE create mode 100644 packages-ts/starknet-gauntlet-ocr2/README.md create mode 100644 packages-ts/starknet-gauntlet-ocr2/package.json create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/index.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/addAccess.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/disableAccessCheck.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/index.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/inspect.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setBilling.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/confirmAggregator.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/index.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/inspection/inspect.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/proposeAggregator.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/lib/categories.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/lib/contracts.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/test/commands/access_controller.test.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/test/commands/ocr2.test.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/test/commands/proxy.test.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/test/lib/encoding.test.ts create mode 100644 packages-ts/starknet-gauntlet-ocr2/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-oz/LICENSE create mode 100644 packages-ts/starknet-gauntlet-oz/README.md create mode 100644 packages-ts/starknet-gauntlet-oz/package.json create mode 100644 packages-ts/starknet-gauntlet-oz/src/commands/account/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-oz/src/commands/account/index.ts create mode 100644 packages-ts/starknet-gauntlet-oz/src/commands/index.ts create mode 100644 packages-ts/starknet-gauntlet-oz/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-oz/src/lib/categories.ts create mode 100644 packages-ts/starknet-gauntlet-oz/src/lib/contracts.ts create mode 100644 packages-ts/starknet-gauntlet-oz/test/commands/account.test.ts create mode 100644 packages-ts/starknet-gauntlet-oz/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet-token/LICENSE create mode 100644 packages-ts/starknet-gauntlet-token/README.md create mode 100644 packages-ts/starknet-gauntlet-token/package.json create mode 100644 packages-ts/starknet-gauntlet-token/src/commands/index.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/commands/inspection/balanceOf.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/commands/inspection/index.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/commands/token/deploy.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/commands/token/index.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/commands/token/mint.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/commands/token/transfer.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/index.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/lib/categories.ts create mode 100644 packages-ts/starknet-gauntlet-token/src/lib/contracts.ts create mode 100644 packages-ts/starknet-gauntlet-token/test/commands/token.test.ts create mode 100644 packages-ts/starknet-gauntlet-token/tsconfig.json create mode 100644 packages-ts/starknet-gauntlet/LICENSE create mode 100644 packages-ts/starknet-gauntlet/README.md create mode 100644 packages-ts/starknet-gauntlet/package.json create mode 100644 packages-ts/starknet-gauntlet/src/commands/base/command.ts create mode 100644 packages-ts/starknet-gauntlet/src/commands/base/executeCommand.ts create mode 100644 packages-ts/starknet-gauntlet/src/commands/base/index.ts create mode 100644 packages-ts/starknet-gauntlet/src/commands/base/inspectionCommand.ts create mode 100644 packages-ts/starknet-gauntlet/src/dependencies/index.ts create mode 100644 packages-ts/starknet-gauntlet/src/events/index.ts create mode 100644 packages-ts/starknet-gauntlet/src/events/subscription.ts create mode 100644 packages-ts/starknet-gauntlet/src/index.ts create mode 100644 packages-ts/starknet-gauntlet/src/provider/index.ts create mode 100644 packages-ts/starknet-gauntlet/src/transaction/index.ts create mode 100644 packages-ts/starknet-gauntlet/src/utils/address.ts create mode 100644 packages-ts/starknet-gauntlet/src/utils/index.ts create mode 100644 packages-ts/starknet-gauntlet/src/wallet/defaultWallet.ts create mode 100644 packages-ts/starknet-gauntlet/src/wallet/index.ts create mode 100644 packages-ts/starknet-gauntlet/test/__mocks__/example.json create mode 100644 packages-ts/starknet-gauntlet/test/commands/execute.test.ts create mode 100644 packages-ts/starknet-gauntlet/test/utils/index.ts create mode 100644 packages-ts/starknet-gauntlet/test/utils/network.ts create mode 100644 packages-ts/starknet-gauntlet/tsconfig.json create mode 100644 packages-ts/starknet/.gitignore create mode 100644 packages-ts/starknet/hardhat.config.ts create mode 100644 packages-ts/starknet/package.json create mode 100644 packages-ts/starknet/src/account.ts create mode 100644 packages-ts/starknet/src/index.ts create mode 100644 packages-ts/starknet/src/utils.ts create mode 100644 packages-ts/starknet/test/fundAccount.test.ts create mode 100644 packages-ts/starknet/tsconfig.json create mode 100644 relayer/go.mod create mode 100644 relayer/go.sum create mode 100644 relayer/package.json create mode 100644 relayer/pkg/plugin/chain/chain.go create mode 100644 relayer/pkg/plugin/config/config.go create mode 100644 relayer/pkg/plugin/db/db.go create mode 100644 relayer/pkg/plugin/keys/key.go create mode 100644 relayer/pkg/plugin/keys/keystore.go create mode 100644 relayer/pkg/plugin/keys/mocks/keystore.go create mode 100644 relayer/pkg/plugin/keys/ocr2key.go create mode 100644 relayer/pkg/plugin/keys/ocr2key_test.go create mode 100644 relayer/pkg/plugin/keys/utils.go create mode 100644 relayer/pkg/plugin/ocr2/client.go create mode 100644 relayer/pkg/plugin/ocr2/client_test.go create mode 100644 relayer/pkg/plugin/ocr2/config.go create mode 100644 relayer/pkg/plugin/ocr2/config_digester.go create mode 100644 relayer/pkg/plugin/ocr2/config_digester_test.go create mode 100644 relayer/pkg/plugin/ocr2/contract_cache.go create mode 100644 relayer/pkg/plugin/ocr2/contract_reader.go create mode 100644 relayer/pkg/plugin/ocr2/contract_transmitter.go create mode 100644 relayer/pkg/plugin/ocr2/events.go create mode 100644 relayer/pkg/plugin/ocr2/events_test.go create mode 100644 relayer/pkg/plugin/ocr2/medianreport/onchainconfig.go create mode 100644 relayer/pkg/plugin/ocr2/medianreport/onchainconfig_test.go create mode 100644 relayer/pkg/plugin/ocr2/medianreport/report.go create mode 100644 relayer/pkg/plugin/ocr2/medianreport/report_fuzz_test.go create mode 100644 relayer/pkg/plugin/ocr2/medianreport/report_test.go create mode 100644 relayer/pkg/plugin/ocr2/medianreport/utils.go create mode 100644 relayer/pkg/plugin/ocr2/mocks/OCR2Reader.go create mode 100644 relayer/pkg/plugin/ocr2/providers.go create mode 100644 relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzEncoding/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 create mode 100644 relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/a027c0abbee32f49cd1a35d5c9b9bea24ec8bb8ee322e03d12b98b6a90367d45 create mode 100644 relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/ef90fb60d9b326ffdcebdf49782fb2ea099a8dba26e80f2652b621cd5c180bb2 create mode 100644 relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/f285bc28d7b7e7006a25508b22bf71aceb4f9ecd5849401dbc4f549fb9233e53 create mode 100644 relayer/pkg/plugin/ocr2/transmissions_cache.go create mode 100644 relayer/pkg/plugin/ocr2/types.go create mode 100644 relayer/pkg/plugin/ocr2/types_test.go create mode 100644 relayer/pkg/plugin/ocr2/utils.go create mode 100644 relayer/pkg/plugin/relay.go create mode 100644 relayer/pkg/plugin/txm/config.go create mode 100644 relayer/pkg/plugin/txm/mocks/config.go create mode 100644 relayer/pkg/plugin/txm/test_helpers.go create mode 100644 relayer/pkg/plugin/txm/txm.go create mode 100644 relayer/pkg/plugin/txm/txm_test.go create mode 100644 relayer/pkg/plugin/types.go create mode 100644 relayer/pkg/starknet/client.go create mode 100644 relayer/pkg/starknet/client_test.go create mode 100644 relayer/pkg/starknet/events.go create mode 100644 relayer/pkg/starknet/events_test.go create mode 100644 relayer/pkg/starknet/mocks/Reader.go create mode 100644 relayer/pkg/starknet/testdata/fuzz/FuzzEncodeDecodeFelts/8dd7c6d4e51a9d0d2fd249dc251e4b7cc673a85738e29a86310d186cd8e2ce1b create mode 100644 relayer/pkg/starknet/types.go create mode 100644 relayer/pkg/starknet/utils.go create mode 100644 relayer/pkg/starknet/utils_fuzz_test.go create mode 100644 relayer/pkg/starknet/utils_test.go create mode 100755 scripts/generate-codegraph.sh create mode 100644 shell.nix create mode 100644 tsconfig.base.json create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..e5b6d8d --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..634bfce --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml new file mode 100644 index 0000000..7b25262 --- /dev/null +++ b/.github/actions/build-test-image/action.yml @@ -0,0 +1,51 @@ +name: Build Test Image +description: A composite action that allows building and publishing the test remote runner image + +inputs: + tag: + description: The tag to use by default and to use for checking image existance + default: ${{ github.sha }} + required: false + other_tags: + description: Other tags to push if needed + required: false + QA_AWS_ROLE_TO_ASSUME: + description: The AWS role to assume as the CD user, if any. Used in configuring the docker/login-action + required: true + QA_AWS_REGION: + description: The AWS region the ECR repository is located in, should only be needed for public ECR repositories, used in configuring docker/login-action + required: true + QA_AWS_ACCOUNT_NUMBER: + description: The AWS region the ECR repository is located in, should only be needed for public ECR repositories, used in configuring docker/login-action + required: true + +runs: + using: composite + steps: + - name: Check if image exists + id: check-image + uses: goplugin/plugin-github-actions/docker/image-exists@8489879838862929f43f7d7cd1b33903965cf507 # v2.1.6 + with: + repository: plugin-starknet-tests + tag: ${{ inputs.tag }} + AWS_REGION: ${{ inputs.QA_AWS_REGION }} + AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }} + - name: Build and Publish Test Runner + if: steps.check-image.outputs.exists == 'false' + uses: goplugin/plugin-github-actions/docker/build-push@8489879838862929f43f7d7cd1b33903965cf507 # v2.1.6 + with: + tags: | + ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/plugin-starknet-tests:${{ inputs.tag }} + ${{ inputs.other_tags }} + file: ./integration-tests/test.Dockerfile + build-args: | + SUITES="smoke soak" + AWS_REGION: ${{ inputs.QA_AWS_REGION }} + AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }} + - name: Print Image Built + env: + INPUTS_TAG: ${{ inputs.tag }} + shell: sh + run: | + echo "### plugin-starknet-tests image tag for this test run :ship:" >> $GITHUB_STEP_SUMMARY + echo "\`${INPUTS_TAG}\`" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/amarna.yml b/.github/workflows/amarna.yml new file mode 100644 index 0000000..13c11f0 --- /dev/null +++ b/.github/workflows/amarna.yml @@ -0,0 +1,27 @@ +name: Amarna Analysis +on: + push: + branches: + - develop + - main + pull_request: + +jobs: + analyze: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Run Amarna + uses: crytic/amarna-action@v0.1.1 + id: amarna + continue-on-error: true + with: + amarna-args: --disable-inline --exclude-rules=must-check-caller-address + sarif: results.sarif + target: 'contracts/src/plugin/cairo/' + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: ${{ steps.amarna.outputs.sarif }} + checkout_path: '/github/workspace' diff --git a/.github/workflows/changesets.yml b/.github/workflows/changesets.yml new file mode 100644 index 0000000..e8df7b7 --- /dev/null +++ b/.github/workflows/changesets.yml @@ -0,0 +1,46 @@ +name: Changesets + +on: + push: + branches: + - main + +jobs: + changesets: + name: Changesets + runs-on: ubuntu-latest + steps: + # Checkout this repository + - name: Checkout Repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + # Install nix + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + # Install dependencies using yarn + - name: Install Dependencies + run: nix develop -c yarn install --frozen-lockfile + # Create PR that will update versions or trigger publish + - name: Create Release Pull Request + uses: changesets/action@2a025e8ab1cfa4312c2868cb6aa3cd3b473b84bf # v1.3.0 + id: changesets + with: + publish: nix develop -c yarn release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + # Dispatch Relayer release + - name: Release relayer + run: gh workflow run .github/workflows/release/starknet-relayer.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Dispatch Gauntlet CLI build & release + - name: Build and release Gauntlet CLI + run: gh workflow run .github/workflows/release/starknet-gauntlet-cli.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/contracts.yml b/.github/workflows/contracts.yml new file mode 100644 index 0000000..7ba39e7 --- /dev/null +++ b/.github/workflows/contracts.yml @@ -0,0 +1,24 @@ +name: Contracts + +on: + push: + branches: + - develop + - main + pull_request: + +jobs: + contracts_run_tests: + name: Run Tests + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Test + run: nix develop -c make test-ts-contracts diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000..df48e23 --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,80 @@ +name: golangci_lint + +on: + push: + +jobs: + golangci-lint-version: + name: Get golangci-lint version to from nix + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Parse version + id: parse + run: | + long=$(nix develop -c golangci-lint version | grep "golangci-lint has version") + stringArray=($long) + version=$(echo "${stringArray[3]}") + echo "version found: ${version}" + echo "version=${version}" >>$GITHUB_OUTPUT + outputs: + version: ${{ steps.parse.outputs.version }} + + golang_lint_relayer: + name: Golang Lint Relayer + runs-on: ubuntu-latest + needs: [golangci-lint-version] + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Lint relayer + run: nix develop -c make lint-go-relayer + + golang_lint_ops: + name: Golang Lint Ops + runs-on: ubuntu-latest + needs: [golangci-lint-version] + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Lint ops + run: nix develop -c make lint-go-ops + + golang_lint_integration_tests: + name: Golang Lint Integration Tests + runs-on: ubuntu-latest + needs: [golangci-lint-version] + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Lint integration-tests + run: nix develop -c make lint-go-test + # Note: I could not figure out why the golangci-lint-action would not work even though it is technically running the same as above, error message is this: + # Running [/home/runner/golangci-lint-1.50.1-linux-amd64/golangci-lint run --out-format=github-actions --path-prefix=integration-tests --exclude=dot-imports] in [/home/runner/work/plugin-starknet/plugin-starknet/integration-tests] ... + # level=warning msg="[runner] Can't run linter goanalysis_metalinter: inspect: failed to load package client: could not load export data: no export data for \"github.com/goplugin/plugin-testing-framework/client\"" + # level=error msg="Running error: 1 error occurred:\n\t* can't run linter goanalysis_metalinter: inspect: failed to load package client: could not load export data: no export data for \"github.com/goplugin/plugin-testing-framework/client\"\n\n" + # - name: golangci-lint + # uses: golangci/golangci-lint-action@v3 + # env: + # CGO_ENABLED: 1 + # with: + # version: v${{ needs.golangci-lint-version.outputs.version }} + # working-directory: integration-tests + # args: --exclude=dot-imports diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml new file mode 100644 index 0000000..b4059a8 --- /dev/null +++ b/.github/workflows/integration-tests-publish.yml @@ -0,0 +1,37 @@ +name: Integration Tests Publish +# Publish the compiled integration tests + +on: + push: + branches: + - develop + +env: + ECR_TAG: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/plugin-starknet-tests:develop + +jobs: + publish-integration-test-image: + environment: integration + permissions: + id-token: write + contents: read + name: Publish Integration Test Image + runs-on: ubuntu-latest + steps: + - name: Collect Metrics + id: collect-gha-metrics + uses: goplugin/push-gha-metrics-action@v1 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: Publish Integration Test Image + continue-on-error: true + - name: Checkout the repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Build Image + uses: ./.github/actions/build-test-image + with: + other_tags: ${{ env.ECR_TAG }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} diff --git a/.github/workflows/integration-tests-smoke.yml b/.github/workflows/integration-tests-smoke.yml new file mode 100644 index 0000000..ed2d64d --- /dev/null +++ b/.github/workflows/integration-tests-smoke.yml @@ -0,0 +1,140 @@ +name: Integration Tests - Smoke + +on: + pull_request: + workflow_dispatch: + inputs: + cl_branch_ref: + description: Plugin repo branch to integrate with + required: true + default: develop + type: string + +# Only run 1 of this workflow at a time per PR +concurrency: + group: integration-tests-starknet-${{ github.ref }} + cancel-in-progress: true + +env: + PLUGIN_ENV_USER: ${{ github.actor }} + TEST_LOG_LEVEL: debug + CL_ECR: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/plugin + ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/plugin-starknet-tests:${{ github.sha }} + +jobs: + build_custom_plugin_image: + name: Build Custom CL Image + runs-on: ubuntu-latest + environment: integration + permissions: + id-token: write + contents: read + steps: + - name: Collect Metrics + if: always() + id: collect-gha-metrics + uses: goplugin/push-gha-metrics-action@808c183d1f5c26a4f3fd50b75d3cf7b58d9aa293 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: Build Custom CL Image + continue-on-error: true + - name: Check if image exists + id: check-image + uses: goplugin/plugin-github-actions/docker/image-exists@8489879838862929f43f7d7cd1b33903965cf507 # v2.1.6 + with: + repository: plugin + tag: starknet.${{ github.sha }} + AWS_REGION: ${{ secrets.QA_AWS_REGION }} + AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + - name: Build Image + if: steps.check-image.outputs.exists == 'false' + # note using a temporary commit for build-image that works around the go get issues, replace when go get issues are fixed please + uses: goplugin/plugin-github-actions/plugin-testing-framework/build-image@a2bf54158aa0a77a55f432347bc9ecf8ef642c2b # cosmos_one_off + with: + cl_repo: goplugin/pluginv3.0 + cl_ref: ${{ github.event.inputs.cl_branch_ref }} + # commit of the caller branch + dep_starknet_sha: ${{ github.event.pull_request.head.sha || github.sha }} + push_tag: ${{ env.CL_ECR }}:starknet.${{ github.sha }} + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_PRIVATE_GHA_PULL: ${{ secrets.QA_PRIVATE_GHA_PULL }} + - name: Print Plugin Image Built + run: | + echo "### plugin image tag used for this test run :link:" >> $GITHUB_STEP_SUMMARY + echo "\`starknet.${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + + build_test_image: + environment: integration + permissions: + id-token: write + contents: read + name: Build Test Image + runs-on: ubuntu20.04-32cores-128GB + steps: + - name: Collect Metrics + id: collect-gha-metrics + uses: goplugin/push-gha-metrics-action@v1 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: Build Test Image + continue-on-error: true + - name: Checkout the repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + ref: ${{ github.sha }} + - name: Build Image + uses: ./.github/actions/build-test-image + with: + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + + run_tests: + name: Run Smoke Tests + runs-on: ubuntu20.04-16cores-64GB + needs: [ build_custom_plugin_image, build_test_image ] + environment: integration + env: + TEST_SUITE: smoke + TEST_ARGS: -test.timeout 1h + PRIVATE_KEY: ${{ secrets.GOERLI_PRIVATE_KEY }} + ACCOUNT: ${{ secrets.GOERLI_ACCOUNT }} + TTL: 1h + NODE_COUNT: 5 + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + steps: + - name: Collect Metrics + if: always() + id: collect-gha-metrics + uses: goplugin/push-gha-metrics-action@808c183d1f5c26a4f3fd50b75d3cf7b58d9aa293 + with: + basic-auth: ${{ secrets.GRAFANA_CLOUD_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_CLOUD_HOST }} + this-job-name: Run Smoke Tests + continue-on-error: true + - name: Checkout the repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Run Tests + uses: goplugin/plugin-github-actions/plugin-testing-framework/run-tests@8489879838862929f43f7d7cd1b33903965cf507 # v2.1.6 + with: + test_command_to_run: nix develop -c make test-integration-smoke-ci + test_download_vendor_packages_command: cd integration-tests && nix develop -c go mod download + cl_repo: ${{ env.CL_ECR }} + cl_image_tag: starknet.${{ github.sha }} + token: ${{ secrets.GITHUB_TOKEN }} + go_mod_path: ./integration-tests/go.mod + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + artifacts_location: /home/runner/work/plugin-starknet/plugin-starknet/integration-tests/smoke/logs diff --git a/.github/workflows/integration-tests-soak.yml b/.github/workflows/integration-tests-soak.yml new file mode 100644 index 0000000..37cefb3 --- /dev/null +++ b/.github/workflows/integration-tests-soak.yml @@ -0,0 +1,121 @@ +name: Integration Tests - Soak + +on: + push: + branches: + - main + - develop + workflow_dispatch: + inputs: + cl_branch_ref: + description: Plugin repo branch to integrate with + required: true + default: develop + type: string + l2_rpc_url: + description: Override default RPC url which points to local devnet (Optional) + required: false + type: string + node_count: + description: Number of ocr nodes + required: true + default: 5 + type: string + ttl: + description: TTL for namespace + required: true + default: 72h + type: string + + + +# Only run 1 of this workflow at a time per PR +concurrency: + group: integration-tests-starknet-${{ github.ref }} + cancel-in-progress: true + +env: + ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/plugin-starknet-tests:${{ github.sha }} + +jobs: + build_custom_plugin_image: + name: Build Custom CL Image + runs-on: ubuntu-latest + environment: integration + permissions: + id-token: write + contents: read + steps: + - name: Check if image exists + id: check-image + uses: goplugin/plugin-github-actions/docker/image-exists@8489879838862929f43f7d7cd1b33903965cf507 # v2.1.6 + with: + repository: plugin + tag: starknet.${{ github.sha }} + AWS_REGION: ${{ secrets.QA_AWS_REGION }} + AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + - name: Build Image + if: steps.check-image.outputs.exists == 'false' + # note using a temporary commit for build-image that works around the go get issues, replace when go get issues are fixed please + uses: goplugin/plugin-github-actions/plugin-testing-framework/build-image@a2bf54158aa0a77a55f432347bc9ecf8ef642c2b # cosmos_one_off + with: + cl_repo: goplugin/pluginv3.0 + # By default we are integrating with CL develop + cl_ref: ${{ github.event.inputs.cl_branch_ref }} + # commit of the caller branch + dep_starknet_sha: ${{ github.event.pull_request.head.sha || github.sha }} + push_tag: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/plugin:starknet.${{ github.sha }} + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_PRIVATE_GHA_PULL: ${{ secrets.QA_PRIVATE_GHA_PULL }} + - name: Print Plugin Image Built + run: | + echo "### plugin image tag used for this test run :link:" >>$GITHUB_STEP_SUMMARY + echo "\`starknet.${{ github.sha }}\`" >>$GITHUB_STEP_SUMMARY + + run_tests: + name: Run Soak Tests + runs-on: ubuntu-latest + needs: [ build_custom_plugin_image ] + environment: integration + env: + PLUGIN_ENV_USER: ${{ github.actor }} + L2_RPC_URL: ${{ github.event.inputs.l2_rpc_url }} + NODE_COUNT: ${{ github.event.inputs.node_count }} + PRIVATE_KEY: ${{ secrets.GOERLI_PRIVATE_KEY }} + ACCOUNT: ${{ secrets.GOERLI_ACCOUNT }} + TTL: ${{ github.event.inputs.ttl }} + DETACH_RUNNER: true + TEST_SUITE: soak + TEST_ARGS: -test.timeout ${{ github.event.inputs.ttl }} + TEST_LOG_LEVEL: debug + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + steps: + - name: Checkout the repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Build Image + uses: ./.github/actions/build-test-image + with: + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + - name: Run Tests + uses: goplugin/plugin-github-actions/plugin-testing-framework/run-tests@ce87f8986ca18336cc5015df75916c2ec0a7c4b3 # v2.1.2 + with: + test_command_to_run: nix develop -c make test-integration-soak-ci + test_download_vendor_packages_command: cd integration-tests && nix develop -c go mod download + cl_repo: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/plugin + cl_image_tag: starknet.${{ github.sha }} + token: ${{ secrets.GITHUB_TOKEN }} + go_mod_path: ./integration-tests/go.mod + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} diff --git a/.github/workflows/integration_contracts.yml b/.github/workflows/integration_contracts.yml new file mode 100644 index 0000000..f2c3690 --- /dev/null +++ b/.github/workflows/integration_contracts.yml @@ -0,0 +1,23 @@ +name: Integration Contracts (Vendor, Examples) + +on: + push: + branches: + - develop + - main + pull_request: + +jobs: + integration_contracts_run_tests: + name: Run Tests + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Test + run: nix develop -c make test-integration-contracts diff --git a/.github/workflows/integration_gauntlet.yml b/.github/workflows/integration_gauntlet.yml new file mode 100644 index 0000000..4338e42 --- /dev/null +++ b/.github/workflows/integration_gauntlet.yml @@ -0,0 +1,26 @@ +name: Integration Gauntlet + +on: + push: + branches: + - develop + - main + pull_request: + +jobs: + integration_gauntlet_run_tests: + name: Run Tests + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Test + run: nix develop -c make test-integration-gauntlet + + - name: Test - Run Gauntlet CLI via Yarn + run: nix develop -c yarn gauntlet diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..018e273 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,26 @@ +name: Lint + +on: + push: + branches: + - develop + - main + pull_request: + +jobs: + lint_format_check: + name: Format Check + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Install + run: nix develop -c yarn install --frozen-lockfile + + - name: Check + run: nix develop -c make format-check diff --git a/.github/workflows/monitoring-build-push-ecr.yml b/.github/workflows/monitoring-build-push-ecr.yml new file mode 100644 index 0000000..fc10259 --- /dev/null +++ b/.github/workflows/monitoring-build-push-ecr.yml @@ -0,0 +1,52 @@ +name: "Build and push on-chain monitor image to ECR" + +on: + push: + branches: + - develop + paths: + - monitoring/** + +jobs: + build-and-publish-monitoring: + runs-on: ubuntu-latest + environment: publish + permissions: + id-token: write + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # v1.7.0 + with: + role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }} + role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Login to ECR + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0 + with: + registry: ${{ secrets.MONITORING_ECR_HOSTNAME }} + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@8c0edbc76e98fa90f69d9a2c020dcb50019dc325 # v2.2.1 + + - name: Generate docker metadata + id: docker_meta + uses: docker/metadata-action@57396166ad8aefe6098280995947635806a0e6ea # v4.1.1 + with: + flavor: | # prevent auto tagging with latest + latest=false + images: ${{ secrets.MONITORING_ECR_HOSTNAME }} + tags: type=sha,format=long + + - name: Build and push docker image + uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 # v3.2.0 + with: + push: true + context: monitoring + file: monitoring/ops/Dockerfile + tags: ${{ steps.docker_meta.outputs.tags }} + labels: ${{ steps.docker_meta.outputs.labels }} diff --git a/.github/workflows/relayer.yml b/.github/workflows/relayer.yml new file mode 100644 index 0000000..0411fcd --- /dev/null +++ b/.github/workflows/relayer.yml @@ -0,0 +1,29 @@ +name: Relayer + +on: + push: + branches: + - develop + - main + pull_request: + +jobs: + relayer_run_unit_tests: + name: Run Unit Tests + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Build + run: nix develop -c make build-go-relayer + + - name: Unit Test + run: nix develop -c make test-unit-go + + - name: Integration Test + run: nix develop -c make test-integration-go diff --git a/.github/workflows/release/starknet-gauntlet-cli.yml b/.github/workflows/release/starknet-gauntlet-cli.yml new file mode 100644 index 0000000..f558acd --- /dev/null +++ b/.github/workflows/release/starknet-gauntlet-cli.yml @@ -0,0 +1,37 @@ +name: Starknet Gauntlet CLI Release + +on: + workflow_dispatch: + +jobs: + starknet-gauntlet-cli-release: + name: Starknet Gauntlet CLI Release + runs-on: ubuntu-latest + steps: + # Checkout this repository + - name: Checkout Repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + # Install nix + - name: Install Nix + uses: cachix/install-nix-action@29bd9290ef037a3ecbdafe83cbd2185e9dd0fa0a # v20 + with: + nix_path: nixpkgs=channel:nixos-unstable + # Install dependencies using yarn + - name: Install Dependencies + run: nix develop -c yarn install --frozen-lockfile + # Build gauntlet binary + - name: Build Gauntlet + run: nix develop -c yarn bundle + # Store gauntlet-cli version + - name: Set Env Variables + run: echo "STARKNET_GAUNTLET_CLI=$(npm info @pluginv3.0/starknet-gauntlet-cli version)" >> $GITHUB_ENV + # Upload gauntlet binary to gauntlet-cli release + - name: Upload Gauntlet Binary + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: bin/plugin-starknet-* + file_glob: true + tag: | + @pluginv3.0/starknet-gauntlet-cli@${{ env.STARKNET_GAUNTLET_CLI }} + overwrite: false diff --git a/.github/workflows/release/starknet-relayer.yml b/.github/workflows/release/starknet-relayer.yml new file mode 100644 index 0000000..9607464 --- /dev/null +++ b/.github/workflows/release/starknet-relayer.yml @@ -0,0 +1,31 @@ +name: Starknet Relayer Release + +on: + workflow_dispatch: + +jobs: + starknet-relayer-release: + name: Release Starknet Relayer + runs-on: ubuntu-latest + steps: + # Checkout this repository + - name: Checkout Repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + # Store starknet version + - name: Set Env Variables + run: echo "STARKNET_RELAYER=$(npm info @pluginv3.0/starknet-relayer version)" >> $GITHUB_ENV + # Check if release tag exists + - name: Check release tag + uses: mukunku/tag-exists-action@5dfe2bf779fe5259360bb10b2041676713dcc8a3 # v1.1.0 + id: checkTag + with: + tag: relayer/v${{ env.STARKNET_RELAYER }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Release code under vX.X.X + - name: Release Code + if: steps.checkTag.outputs.exists == 'false' + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 + with: + tag_name: relayer/v${{ env.STARKNET_RELAYER }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fe4e630 --- /dev/null +++ b/.gitignore @@ -0,0 +1,164 @@ +.direnv +artifacts/ +accounts.json +node.json +package-lock.json +node_modules/ +flow-report.json +.env +.idea/ +report.json +bin +**/tsconfig.tsbuildinfo + +.DS_Store +.temp/ +coverage/ +coverage.json + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +./lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# vscode project settings +.vscode/ + +# go workspace settings +go.work +go.work.sum + +.env.test* +tmp-manifest-* + +# Test log files +integration-tests/logs +integration-tests/smoke/logs +integration-tests/soak/logs +remote.test +ztarrepo.tar.gz diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..6de791b --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,83 @@ +run: + timeout: 10m0s +linters: + enable: + - exhaustive + - exportloopref + - revive + # - goimports + - gosec + - misspell + # - rowserrcheck + - errorlint +linters-settings: + exhaustive: + default-signifies-exhaustive: true + goimports: + local-prefixes: github.com/goplugin/plugin-starknet + golint: + min-confidence: 1.0 + gosec: + excludes: + - G101 + - G104 + # - G204 + # - G304 + # - G404 + govet: + # report about shadowed variables + check-shadowing: true + errorlint: + # Allow formatting of errors without %w + errorf: false + revive: + confidence: 0.8 + rules: + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + - name: error-return + - name: error-strings + - name: error-naming + - name: if-return + - name: increment-decrement + # - name: var-naming + - name: var-declaration + - name: package-comments + - name: range + - name: receiver-naming + - name: time-naming + # - name: unexported-return + - name: indent-error-flow + - name: errorf + - name: empty-block + - name: superfluous-else + # - name: unused-parameter + - name: unreachable-code + - name: redefines-builtin-id + - name: waitgroup-by-value + - name: unconditional-recursion + - name: struct-tag + # - name: string-format + - name: string-of-int + # - name: range-val-address + - name: range-val-in-closure + - name: modifies-value-receiver + - name: modifies-parameter + - name: identical-branches + - name: get-return + # - name: flag-parameter + # - name: early-return + - name: defer + - name: constant-logical-expr + # - name: confusing-naming + # - name: confusing-results + - name: bool-literal-in-expr + - name: atomic +issues: + exclude-rules: + - path: test + text: "^G404:" + linters: + - gosec diff --git a/.helm-repositories.yaml b/.helm-repositories.yaml new file mode 100644 index 0000000..68ffe66 --- /dev/null +++ b/.helm-repositories.yaml @@ -0,0 +1,30 @@ +apiVersion: '' +generated: '0001-01-01T00:00:00Z' +repositories: + - caFile: '' + certFile: '' + insecure_skip_tls_verify: false + keyFile: '' + name: bitnami + pass_credentials_all: false + password: '' + url: https://charts.bitnami.com/bitnami + username: '' + - caFile: '' + certFile: '' + insecure_skip_tls_verify: false + keyFile: '' + name: plugin-qa + pass_credentials_all: false + password: '' + url: https://raw.githubusercontent.com/goplugin/qa-charts/gh-pages/ + username: '' + - caFile: '' + certFile: '' + insecure_skip_tls_verify: false + keyFile: '' + name: grafana + pass_credentials_all: false + password: '' + url: https://grafana.github.io/helm-charts + username: '' diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f104393 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,17 @@ +migrations +tests +ops +packages-rs +target +*.json +dist +*.yml +typechain-types +*.html + +# Vendor files (contracts) +vendor + +# Python virtual env +.venv +.direnv diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..e4769df --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,21 @@ +{ + "semi": false, + "singleQuote": true, + "printWidth": 100, + "endOfLine": "auto", + "tabWidth": 2, + "trailingComma": "all", + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 120, + "tabWidth": 2, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": false, + "explicitTypes": "always" + } + } + ] +} diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..8d6eb77 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,18 @@ +# Languages +nodejs 18.6.0 +yarn 1.22.19 +golang 1.20.1 +python 3.9.13 + +# Tools +mockery 2.13.0-beta.1 +golangci-lint 1.51.2 +actionlint 1.6.12 +shellcheck 0.8.0 + +# Kubernetes +k3d 5.4.4 +kubectl 1.25.5 +k9s 0.26.3 +helm 3.9.3 +helmenv 1.2.7 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0af93a2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,19 @@ +# Changelog Index + +This repository adheres to [Semantic Versioning](http://semver.org/). + +Plugin-Starknet contains a number of projects, all individually versioned and released. Please consult the following changelogs for more information: + +- [@pluginv3.0/starknet-relayer](/relayer/) +- [@pluginv3.0/starknet-gauntlet](/packages-ts/starknet-gauntlet/) +- [@pluginv3.0/starknet-gauntlet-cli](/packages-ts/starknet-gauntlet-cli/) +- [@pluginv3.0/starknet-gauntlet-ocr2](/packages-ts/starknet-gauntlet-ocr2/) +- [@pluginv3.0/starknet-gauntlet-oz](/packages-ts/starknet-gauntlet-oz/) +- [@pluginv3.0/starknet-gauntlet-argent](/packages-ts/starknet-gauntlet-argent/) +- [@pluginv3.0/starknet-gauntlet-token](/packages-ts/starknet-gauntlet-token/) +- [@pluginv3.0/starknet-contracts](/contracts/) +- [@pluginv3.0/starknet-integration-tests](/integration-tests/) + +If a project is pre-v1.0, minor version bumps may cause breaking changes. All breaking changes are noted in changelogs. + +Official project releases can be found here: https://github.com/goplugin/plugin-starknet/releases diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5fecc94 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,43 @@ +# Plugin Starknet monorepo contributing guide + +🎈 Thanks for your help improving the project! We are so happy to have you! + +## Workflow for Pull Requests + +🚨 Before making any non-trivial change, please first open an issue describing the change to solicit feedback and guidance. This will increase the likelihood of the PR getting merged. + +In general, the smaller the diff the easier it will be for us to review quickly. + +In order to contribute, fork the appropriate branch, for non-breaking changes to production that is `develop` and for the next release that is normally `release/X.X.X` branch. + +Additionally, if you are writing a new feature, please ensure you add appropriate test cases. + +Follow the [Getting Started](./docs/getting-started.md) guide to set up your local development environment. + +We recommend using the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format on commit messages. + +Unless your PR is ready for immediate review and merging, please mark it as 'draft' (or simply do not open a PR yet). + +**Bonus:** Add comments to the diff under the "Files Changed" tab on the PR page to clarify any sections where you think we might have questions about the approach taken. + +### Response time: + +We aim to provide a meaningful response to all PRs and issues from external contributors within 5 business days. + +### Changesets + +We use [changesets](https://github.com/atlassian/changesets) to manage releases of our various packages. +You _must_ include a `changeset` file in your PR when making a change that would require a new package release. + +Adding a `changeset` file is easy: + +1. Navigate to the root of the monorepo. +2. Run `yarn changeset`. You'll be prompted to select packages to include in the changeset. Use the arrow keys to move the cursor up and down, hit the `spacebar` to select a package, and hit `enter` to confirm your selection. Select _all_ packages that require a new release as a result of your PR. +3. Once you hit `enter` you'll be prompted to decide whether your selected packages need a `major`, `minor`, or `patch` release. We follow the [Semantic Versioning](https://semver.org/) scheme. Please avoid using `major` releases for any packages that are still in version `0.y.z`. +4. Commit your changeset and push it into your PR. The changeset bot will notice your changeset file and leave a little comment to this effect on GitHub. + +### Rebasing + +We use the `git rebase` command to keep our commit history tidy. +Rebasing is an easy way to make sure that each PR includes a series of clean commits with descriptive commit messages +See [this tutorial](https://docs.gitlab.com/ee/topics/git/git_rebase.html) for a detailed explanation of `git rebase` and how you should use it to maintain a clean commit history. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6609f76 --- /dev/null +++ b/Makefile @@ -0,0 +1,267 @@ +BIN_DIR = bin +export GOPATH ?= $(shell go env GOPATH) +export GO111MODULE ?= on + +LINUX=LINUX +OSX=OSX +WINDOWS=WIN32 +OSFLAG := +ifeq ($(OS),Windows_NT) + OSFLAG = $(WINDOWS) +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + OSFLAG = $(LINUX) + endif + ifeq ($(UNAME_S),Darwin) + OSFLAG = $(OSX) + endif +endif + +.PHONY: install +install: +ifeq ($(OSFLAG),$(WINDOWS)) + @echo "Windows system detected - no automated setup available." + @echo "Please install your developer enviroment manually (@see .tool-versions)." + @echo + exit 1 +endif +ifeq ($(OSFLAG),$(OSX)) + @echo "MacOS system detected - installing the required toolchain via asdf (@see .tool-versions)." + @echo + brew install asdf + asdf plugin add golang || true + asdf plugin add nodejs || true + asdf plugin add python || true + asdf plugin add mockery || true + asdf plugin add golangci-lint || true + asdf plugin add actionlint || true + asdf plugin add shellcheck || true + asdf plugin add k3d || true + asdf plugin add kubectl || true + asdf plugin add k9s || true + asdf plugin add helm || true + asdf plugin add helmenv https://github.com/goplugin/asdf-helmenv.git || true + @echo + asdf install +endif +ifeq ($(OSFLAG),$(LINUX)) + @echo "Linux system detected - please install and use NIX (@see shell.nix)." + @echo +ifneq ($(CI),true) + # install nix + sh <(curl -L https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install) --daemon --tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve --nix-extra-conf-file ./nix.conf +endif +endif + +.PHONY: nix-container +nix-container: + docker run -it --rm -v $(shell pwd):/repo -e NIX_USER_CONF_FILES=/repo/nix.conf --workdir /repo nixos/nix:latest /bin/sh + +.PHONY: nix-flake-update +nix-flake-update: + docker run -it --rm -v $(shell pwd):/repo -e NIX_USER_CONF_FILES=/repo/nix.conf --workdir /repo nixos/nix:latest /bin/sh -c "nix flake update" + +.PHONY: build +build: build-go build-ts + +.PHONY: build-go +build-go: build-go-relayer build-go-ops build-go-integration-tests + +.PHONY: build-go-relayer +build-go-relayer: + cd relayer/ && go build ./... + +.PHONY: build-go-ops +build-go-ops: + cd ops/ && go build ./... + +.PHONY: build-go-integration-tests +build-go-integration-tests: + cd integration-tests/ && go build ./... + +.PHONY: build-ts +build-ts: build-ts-workspace build-ts-contracts build-ts-examples + +.PHONY: build-ts-workspace +build-ts-workspace: + yarn install --frozen-lockfile + yarn build + +# TODO: use yarn workspaces features instead of managing separately like this +# https://yarnpkg.com/cli/workspaces/foreach +.PHONY: build-ts-contracts +build-ts-contracts: + cd contracts/ && \ + yarn install --frozen-lockfile && \ + yarn compile + +.PHONY: build-ts-examples +build-ts-examples: + cd examples/contracts/aggregator-consumer && \ + yarn install --frozen-lockfile && \ + yarn compile + +.PHONY: gowork +gowork: + go work init + go work use ./ops + go work use ./relayer + go work use ./integration-tests + +.PHONY: gowork_rm +gowork_rm: + rm go.work* + +.PHONY: format +format: format-go format-cairo format-ts + +.PHONY: format-check +format-check: format-cairo-check format-ts-check + +.PHONY: format-go +format-go: format-go-fmt format-go-mod-tidy + +.PHONY: format-go-fmt +format-go-fmt: + cd ./relayer && go fmt ./... + cd ./ops && go fmt ./... + cd ./integration-tests && go fmt ./... + +.PHONY: format-go-mod-tidy +format-go-mod-tidy: + cd ./relayer && go mod tidy + cd ./monitoring && go mod tidy + cd ./ops && go mod tidy + cd ./integration-tests && go mod tidy + +.PHONY: format-cairo +format-cairo: + find ./contracts/src -name "*.cairo" -type f \ + -exec cairo-format -i --one_item_per_line {} + + find ./examples -name "*.cairo" -type f \ + -exec cairo-format -i --one_item_per_line {} + + +.PHONY: format-cairo-check +format-cairo-check: + find ./contracts/src -name "*.cairo" -type f \ + -exec cairo-format -c --one_item_per_line {} + + find ./examples -name "*.cairo" -type f \ + -exec cairo-format -c --one_item_per_line {} + + +.PHONY: format-ts +format-ts: + yarn format + +.PHONY: format-ts-check +format-ts-check: + yarn format:check + +.PHONY: lint-go-ops +lint-go-ops: + cd ./ops && golangci-lint --color=always run + +.PHONY: lint-go-relayer +lint-go-relayer: + cd ./relayer && golangci-lint --color=always run + +.PHONY: lint-go-test +lint-go-test: + cd ./integration-tests && golangci-lint --color=always --exclude=dot-imports run + +.PHONY: test-go +test-go: test-unit-go test-integration-go + +.PHONY: test-unit +test-unit: test-unit-go + +.PHONY: test-unit-go +test-unit-go: + cd ./relayer && go test -v ./... + cd ./relayer && go test -v ./... -race -count=10 + +.PHONY: test-integration-go +# only runs tests with TestIntegration_* + //go:build integration +test-integration-go: + cd ./relayer && go test -v ./... -run TestIntegration -tags integration + +.PHONY: test-integration-prep +test-integration-prep: + python -m venv ~/cairo_venv && \ + . ~/cairo_venv/bin/activate + cd ./contracts && pip install -r requirements.txt + make build + +.PHONY: test-integration +test-integration: test-integration-smoke test-integration-contracts test-integration-gauntlet + +.PHONY: test-integration-smoke +test-integration-smoke: test-integration-prep + cd integration-tests/ && \ + go test --timeout=2h -v ./smoke + +# CI Already has already ran test-integration-prep +.PHONY: test-integration-smoke-ci +test-integration-smoke-ci: + cd integration-tests/ && \ + go test --timeout=2h -v -count=1 -json ./smoke 2>&1 | tee /tmp/gotest.log | gotestfmt + +.PHONY: test-integration-soak +test-integration-soak: test-integration-prep + cd integration-tests/ && \ + go test --timeout=1h -v ./soak + +# CI Already has already ran test-integration-prep +.PHONY: test-integration-soak-ci +test-integration-soak-ci: + cd integration-tests/ && \ + go test --timeout=1h -v -count=1 -json ./soak 2>&1 | tee /tmp/gotest.log | gotestfmt + +.PHONY: test-integration-contracts +# TODO: better network lifecycle setup - requires external network (L1 + L2) +test-integration-contracts: build-ts env-devnet-hardhat + cd examples/contracts/aggregator-consumer/ && \ + yarn test + cd packages-ts/integration-eqlabs-multisig/ && \ + yarn test + cd packages-ts/starknet/ && \ + yarn test + +.PHONY: test-integration-gauntlet +# TODO: better network lifecycle setup - tests setup/run their own network (L1 + conflict w/ above if not cleaned up) +test-integration-gauntlet: build-ts env-devnet-hardhat-down + cd packages-ts/starknet-gauntlet/ && \ + yarn test + cd packages-ts/starknet-gauntlet-argent/ && \ + yarn test + cd packages-ts/starknet-gauntlet-cli/ && \ + yarn test + cd packages-ts/starknet-gauntlet-example/ && \ + yarn test + cd packages-ts/starknet-gauntlet-multisig/ && \ + yarn test + cd packages-ts/starknet-gauntlet-ocr2/ && \ + yarn test + cd packages-ts/starknet-gauntlet-oz/ && \ + yarn test + cd packages-ts/starknet-gauntlet-token/ && \ + yarn test + cd packages-ts/starknet-gauntlet-emergency-protocol/ && \ + yarn test + +.PHONY: test-ts +test-ts: test-ts-contracts test-integration-contracts test-integration-gauntlet + +.PHONY: test-ts-contracts +test-ts-contracts: build-ts-contracts build-ts-workspace env-devnet-hardhat + cd contracts/ && \ + yarn test + +# TODO: this script needs to be replaced with a predefined K8s enviroment +.PHONY: env-devnet-hardhat +env-devnet-hardhat: + ./ops/scripts/devnet-hardhat.sh + +.PHONY: env-devnet-hardhat-down +env-devnet-hardhat-down: + ./ops/scripts/devnet-hardhat-down.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..2cbc32f --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Plugin Starknet + +For more information, see the [Plugin Starknet Documentation](./docs). diff --git a/contracts/.gitignore b/contracts/.gitignore new file mode 100644 index 0000000..3446f76 --- /dev/null +++ b/contracts/.gitignore @@ -0,0 +1,3 @@ +starknet-artifacts/ +cache/ +typechain-types/ diff --git a/contracts/.helix/languages.toml b/contracts/.helix/languages.toml new file mode 100644 index 0000000..70f2df9 --- /dev/null +++ b/contracts/.helix/languages.toml @@ -0,0 +1,5 @@ +[[language]] +name = "cairo" +language-server = { command = "node", args = ["node_modules/cairo-ls/out/server.js", "--stdio"] } +[language.config] +cairols = { venvCommand = ". .venv/bin/activate", sourceDir = "contracts" } diff --git a/contracts/constraints.txt b/contracts/constraints.txt new file mode 100644 index 0000000..e69de29 diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts new file mode 100644 index 0000000..339dcc6 --- /dev/null +++ b/contracts/hardhat.config.ts @@ -0,0 +1,71 @@ +import { HardhatUserConfig } from 'hardhat/types' +import '@shardlabs/starknet-hardhat-plugin' +import '@nomiclabs/hardhat-ethers' +import '@nomicfoundation/hardhat-chai-matchers' +import 'solidity-coverage' + +const COMPILER_SETTINGS = { + optimizer: { + enabled: true, + runs: 1000000, + }, + metadata: { + bytecodeHash: 'none', + }, +} + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +const config: HardhatUserConfig = { + solidity: { + compilers: [ + { + version: '0.6.12', + settings: COMPILER_SETTINGS, + }, + { + version: '0.8.15', + settings: COMPILER_SETTINGS, + }, + ], + }, + starknet: { + // dockerizedVersion: "0.10.0", // alternatively choose one of the two venv options below + // uses (my-venv) defined by `python -m venv path/to/my-venv` + // venv: "../.venv", + + // uses the currently active Python environment (hopefully with available Starknet commands!) + venv: 'active', + // network: "alpha", + network: 'devnet', + wallets: { + OpenZeppelin: { + accountName: 'OpenZeppelin', + modulePath: 'starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount', + accountPath: '~/.starknet_accounts', + }, + }, + }, + networks: { + devnet: { + url: 'http://127.0.0.1:5050', + }, + integratedDevnet: { + url: 'http://127.0.0.1:5050', + venv: 'active', + args: ['--lite-mode'], + // dockerizedVersion: "0.2.0" + }, + }, + mocha: { + timeout: 10000000, + }, + paths: { + sources: './src', + starknetSources: './src', + cairoPaths: ['./vendor/starkware-libs/starkgate-contracts/src'], + }, +} + +export default config diff --git a/contracts/package.json b/contracts/package.json new file mode 100644 index 0000000..5c340ea --- /dev/null +++ b/contracts/package.json @@ -0,0 +1,33 @@ +{ + "name": "@pluginv3.0/starknet-contracts", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "compile:cairo": "hardhat starknet-compile", + "compile:solidity": "hardhat compile", + "compile": "yarn compile:cairo && yarn compile:solidity", + "test": "hardhat --network localhost test" + }, + "author": "", + "license": "MIT", + "devDependencies": { + "@ethereum-waffle/mock-contract": "^4.0.4", + "@nomicfoundation/hardhat-chai-matchers": "^1.0.3", + "@nomiclabs/hardhat-ethers": "^2.0.5", + "@shardlabs/starknet-hardhat-plugin": "^0.8.0-alpha.0", + "@types/chai": "^4.3.3", + "@types/elliptic": "^6.4.14", + "@types/mocha": "^9.1.1", + "chai": "^4.3.6", + "ethers": "^5.6.8", + "hardhat": "^2.10.2", + "solidity-coverage": "^0.8.2" + }, + "dependencies": { + "@pluginv3.0/contracts": "^0.4.2", + "@pluginv3.0/starknet": "^1.0.0", + "@openzeppelin/contracts": "^4.7.3", + "axios": "^0.24.0" + } +} diff --git a/contracts/requirements.txt b/contracts/requirements.txt new file mode 100644 index 0000000..84895f1 --- /dev/null +++ b/contracts/requirements.txt @@ -0,0 +1,6 @@ +ecdsa +fastecdsa +sympy +cairo-lang>=0.11.0.1 +starknet-devnet>=0.5.0 +openzeppelin-cairo-contracts==0.5.0 diff --git a/contracts/src/plugin/cairo/access/IAccessController.cairo b/contracts/src/plugin/cairo/access/IAccessController.cairo new file mode 100644 index 0000000..b6ba969 --- /dev/null +++ b/contracts/src/plugin/cairo/access/IAccessController.cairo @@ -0,0 +1,10 @@ +%lang starknet + +@contract_interface +namespace IAccessController { + func has_access(user: felt, data_len: felt, data: felt*) -> (bool: felt) { + } + + func check_access(user: felt) { + } +} diff --git a/contracts/src/plugin/cairo/access/SimpleReadAccessController/library.cairo b/contracts/src/plugin/cairo/access/SimpleReadAccessController/library.cairo new file mode 100644 index 0000000..b324a45 --- /dev/null +++ b/contracts/src/plugin/cairo/access/SimpleReadAccessController/library.cairo @@ -0,0 +1,63 @@ +%lang starknet + +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.starknet.common.syscalls import get_tx_info +from starkware.cairo.common.bool import TRUE, FALSE + +from plugin.cairo.access.SimpleWriteAccessController.library import ( + SimpleWriteAccessController, + owner, + proposed_owner, + transfer_ownership, + accept_ownership, + add_access, + remove_access, + enable_access_check, + disable_access_check, +) + +namespace SimpleReadAccessController { + func initialize{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + owner_address: felt + ) { + SimpleWriteAccessController.initialize(owner_address); + return (); + } + + // Gives access to: + // - any externally owned account (note that offchain actors can always read + // any contract storage regardless of onchain access control measures, so this + // does not weaken the access control while improving usability) + // - accounts explicitly added to an access list + func has_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + user: felt, data_len: felt, data: felt* + ) -> (bool: felt) { + let (has_access) = SimpleWriteAccessController.has_access(user, data_len, data); + if (has_access == TRUE) { + return (TRUE,); + } + + // NOTICE: access is granted to direct calls, to enable off-chain reads. + if (user == 0) { + return (TRUE,); + } + + return (FALSE,); + } + + // TODO: remove when starkware adds get_class_hash_at + func check_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(user: felt) { + alloc_locals; + + let empty_data_len = 0; + let (empty_data) = alloc(); + + let (bool) = SimpleReadAccessController.has_access(user, empty_data_len, empty_data); + with_attr error_message("SimpleReadAccessController: address does not have access") { + assert bool = TRUE; + } + + return (); + } +} diff --git a/contracts/src/plugin/cairo/access/SimpleReadAccessController/simple_read_access_controller.cairo b/contracts/src/plugin/cairo/access/SimpleReadAccessController/simple_read_access_controller.cairo new file mode 100644 index 0000000..c30505a --- /dev/null +++ b/contracts/src/plugin/cairo/access/SimpleReadAccessController/simple_read_access_controller.cairo @@ -0,0 +1,39 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin + +from plugin.cairo.access.SimpleReadAccessController.library import SimpleReadAccessController +from plugin.cairo.access.SimpleWriteAccessController.library import ( + owner, + proposed_owner, + transfer_ownership, + accept_ownership, + add_access, + remove_access, + enable_access_check, + disable_access_check, +) + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + owner_address: felt +) { + SimpleReadAccessController.initialize(owner_address); + return (); +} + +// implements IAccessController +@view +func has_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + user: felt, data_len: felt, data: felt* +) -> (bool: felt) { + let (has_access) = SimpleReadAccessController.has_access(user, data_len, data); + return (has_access,); +} + +// implements IAccessController +@view +func check_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(user: felt) { + SimpleReadAccessController.check_access(user); + return (); +} diff --git a/contracts/src/plugin/cairo/access/SimpleWriteAccessController/library.cairo b/contracts/src/plugin/cairo/access/SimpleWriteAccessController/library.cairo new file mode 100644 index 0000000..0d09f83 --- /dev/null +++ b/contracts/src/plugin/cairo/access/SimpleWriteAccessController/library.cairo @@ -0,0 +1,158 @@ +%lang starknet + +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.bool import TRUE, FALSE +from starkware.cairo.common.cairo_builtins import HashBuiltin + +from plugin.cairo.access.ownable import Ownable + +@event +func AddedAccess(user: felt) { +} + +@event +func RemovedAccess(user: felt) { +} + +@event +func CheckAccessEnabled() { +} + +@event +func CheckAccessDisabled() { +} + +@storage_var +func SimpleWriteAccessController_check_enabled() -> (checkEnabled: felt) { +} + +@storage_var +func SimpleWriteAccessController_access_list(address: felt) -> (bool: felt) { +} + +// --- Ownership --- + +@view +func owner{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}() -> (owner: felt) { + let (owner) = Ownable.get_owner(); + return (owner=owner); +} + +@view +func proposed_owner{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}() -> ( + proposed_owner: felt +) { + let (proposed_owner) = Ownable.get_proposed_owner(); + return (proposed_owner=proposed_owner); +} + +@external +func transfer_ownership{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + new_owner: felt +) -> () { + return Ownable.transfer_ownership(new_owner); +} + +@external +func accept_ownership{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + return Ownable.accept_ownership(); +} + +// --- AC --- + +// Adds an address to the access list +@external +func add_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(user: felt) { + Ownable.assert_only_owner(); + let (has_access) = SimpleWriteAccessController_access_list.read(user); + if (has_access == FALSE) { + SimpleWriteAccessController_access_list.write(user, TRUE); + AddedAccess.emit(user); + return (); + } + + return (); +} + +// Removes an address from the access list +@external +func remove_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(user: felt) { + Ownable.assert_only_owner(); + let (has_access) = SimpleWriteAccessController_access_list.read(user); + if (has_access == TRUE) { + SimpleWriteAccessController_access_list.write(user, FALSE); + RemovedAccess.emit(user); + return (); + } + + return (); +} + +// Makes the access check enforced +@external +func enable_access_check{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + Ownable.assert_only_owner(); + let (check_enabled) = SimpleWriteAccessController_check_enabled.read(); + if (check_enabled == FALSE) { + SimpleWriteAccessController_check_enabled.write(TRUE); + CheckAccessEnabled.emit(); + return (); + } + + return (); +} + +// makes the access check unenforced +@external +func disable_access_check{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + Ownable.assert_only_owner(); + let (check_enabled) = SimpleWriteAccessController_check_enabled.read(); + if (check_enabled == TRUE) { + SimpleWriteAccessController_check_enabled.write(FALSE); + CheckAccessDisabled.emit(); + return (); + } + + return (); +} + +namespace SimpleWriteAccessController { + func initialize{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + owner_address: felt + ) { + Ownable.initializer(owner_address); + SimpleWriteAccessController_check_enabled.write(TRUE); + + return (); + } + + func has_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + user: felt, data_len: felt, data: felt* + ) -> (bool: felt) { + let (has_access) = SimpleWriteAccessController_access_list.read(user); + if (has_access == TRUE) { + return (TRUE,); + } + + let (check_enabled) = SimpleWriteAccessController_check_enabled.read(); + if (check_enabled == FALSE) { + return (TRUE,); + } + + return (FALSE,); + } + + func check_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(user: felt) { + alloc_locals; + + let empty_data_len = 0; + let (empty_data) = alloc(); + + let (bool) = SimpleWriteAccessController.has_access(user, empty_data_len, empty_data); + with_attr error_message("SimpleWriteAccessController: address does not have access") { + assert bool = TRUE; + } + + return (); + } +} diff --git a/contracts/src/plugin/cairo/access/SimpleWriteAccessController/simple_write_access_controller.cairo b/contracts/src/plugin/cairo/access/SimpleWriteAccessController/simple_write_access_controller.cairo new file mode 100644 index 0000000..6571cf0 --- /dev/null +++ b/contracts/src/plugin/cairo/access/SimpleWriteAccessController/simple_write_access_controller.cairo @@ -0,0 +1,29 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin + +from plugin.cairo.access.SimpleWriteAccessController.library import SimpleWriteAccessController + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + owner_address: felt +) { + SimpleWriteAccessController.initialize(owner_address); + return (); +} + +// implements IAccessController +@view +func has_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + user: felt, data_len: felt, data: felt* +) -> (bool: felt) { + let (has_access) = SimpleWriteAccessController.has_access(user, data_len, data); + return (has_access,); +} + +// implements IAccessController +@view +func check_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(user: felt) { + SimpleWriteAccessController.check_access(user); + return (); +} diff --git a/contracts/src/plugin/cairo/access/ownable.cairo b/contracts/src/plugin/cairo/access/ownable.cairo new file mode 100644 index 0000000..fcc3c21 --- /dev/null +++ b/contracts/src/plugin/cairo/access/ownable.cairo @@ -0,0 +1,117 @@ +// Equivalent to openzeppelin/Ownable except it's a two step process to transfer ownership. +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.starknet.common.syscalls import get_caller_address +from starkware.cairo.common.math import assert_not_zero + +// +// Events +// + +@event +func OwnershipTransferred(previousOwner: felt, newOwner: felt) { +} + +@event +func OwnershipTransferRequested(from_address: felt, to: felt) { +} + +// +// Storage +// + +@storage_var +func Ownable_owner() -> (owner: felt) { +} + +@storage_var +func Ownable_proposed_owner() -> (proposed_owner: felt) { +} + +namespace Ownable { + // + // Constructor + // + func initializer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(owner: felt) { + with_attr error_message("Ownable: cannot transfer to zero address") { + assert_not_zero(owner); + } + _accept_ownership_transfer(owner); + return (); + } + + func assert_only_owner{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (owner) = Ownable_owner.read(); + let (caller) = get_caller_address(); + // caller is the zero address should not be possible anymore with introduction of fees + with_attr error_message("Ownable: caller is the zero address") { + assert_not_zero(caller); + } + with_attr error_message("Ownable: caller is not the owner") { + assert owner = caller; + } + return (); + } + + func get_owner{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + owner: felt + ) { + let (owner) = Ownable_owner.read(); + return (owner=owner); + } + + func get_proposed_owner{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + proposed_owner: felt + ) { + let (proposed_owner) = Ownable_proposed_owner.read(); + return (proposed_owner=proposed_owner); + } + + func transfer_ownership{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + new_owner: felt + ) -> () { + with_attr error_message("Ownable: cannot transfer to zero address") { + assert_not_zero(new_owner); + } + assert_only_owner(); + Ownable_proposed_owner.write(new_owner); + let (previous_owner: felt) = Ownable_owner.read(); + OwnershipTransferRequested.emit(previous_owner, new_owner); + return (); + } + + func accept_ownership{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (proposed_owner) = Ownable_proposed_owner.read(); + let (caller) = get_caller_address(); + // caller cannot be zero address to avoid overwriting owner when proposed_owner is not set + with_attr error_message("Ownable: caller is the zero address") { + assert_not_zero(caller); + } + with_attr error_message("Ownable: caller is not the proposed owner") { + assert proposed_owner = caller; + } + _accept_ownership_transfer(proposed_owner); + return (); + } + + func renounce_ownership{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + assert_only_owner(); + _accept_ownership_transfer(0); + return (); + } + + // + // Internal + // + + func _accept_ownership_transfer{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr + }(new_owner: felt) { + let (previous_owner: felt) = Ownable_owner.read(); + Ownable_owner.write(new_owner); + Ownable_proposed_owner.write(0); + OwnershipTransferred.emit(previous_owner, new_owner); + return (); + } +} diff --git a/contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/library.cairo b/contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/library.cairo new file mode 100644 index 0000000..8df7c39 --- /dev/null +++ b/contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/library.cairo @@ -0,0 +1,269 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.starknet.common.syscalls import ( + get_block_timestamp, + get_caller_address, + get_block_number, +) +from starkware.cairo.common.math import assert_not_zero, assert_nn_le, assert_lt_felt +from starkware.cairo.common.math_cmp import is_le +from starkware.cairo.common.bool import TRUE + +from plugin.cairo.utils import assert_boolean +from plugin.cairo.ocr2.IAggregator import Round, AnswerUpdated, NewRound +from plugin.cairo.access.SimpleReadAccessController.library import SimpleReadAccessController +from plugin.cairo.access.SimpleWriteAccessController.library import ( + owner, + proposed_owner, + transfer_ownership, + accept_ownership, + add_access, + remove_access, + enable_access_check, + disable_access_check, +) +from plugin.cairo.access.ownable import Ownable + +const ETH_ADDRESS_BOUND = 2 ** 160; + +@event +func RoundUpdated(status: felt, updated_at: felt) { +} + +@event +func UpdateIgnored( + latest_status: felt, latest_timestamp: felt, incoming_status: felt, incoming_timestamp: felt +) { +} + +@event +func L1SenderTransferred(from_addr: felt, to_addr: felt) { +} + +@storage_var +func SequencerUptimeFeed_l1_sender() -> (address: felt) { +} + +@storage_var +func SequencerUptimeFeed_rounds(id: felt, field: felt) -> (res: felt) { +} + +@storage_var +func SequencerUptimeFeed_latest_round_id() -> (res: felt) { +} + +func require_l1_sender{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + address: felt +) { + let (l1_sender) = SequencerUptimeFeed_l1_sender.read(); + with_attr error_message("SequencerUptimeFeed: invalid sender") { + assert l1_sender = address; + } + + return (); +} + +func require_valid_round_id{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt +) { + let (latest_round_id) = SequencerUptimeFeed_latest_round_id.read(); + + with_attr error_message("SequencerUptimeFeed: invalid round_id") { + assert_not_zero(round_id); + assert_nn_le(round_id, latest_round_id); + } + + return (); +} + +func require_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (address) = get_caller_address(); + SimpleReadAccessController.check_access(address); + + return (); +} + +// TODO: make overridable in the future +@external +func set_l1_sender{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(address: felt) { + Ownable.assert_only_owner(); + + with_attr error_message("SequencerUptimeFeed: L1 sender address out of range") { + assert_lt_felt(address, ETH_ADDRESS_BOUND); + } + + with_attr error_message("SequencerUptimeFeed: L1 sender address can not be zero") { + assert_not_zero(address); + } + _set_l1_sender(address); + + return (); +} + +@view +func l1_sender{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + address: felt +) { + let (address) = SequencerUptimeFeed_l1_sender.read(); + return (address,); +} + +namespace SequencerUptimeFeed { + func initialize{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + initial_status: felt, owner_address: felt + ) { + with_attr error_message("SequencerUptimeFeed: value isn't a boolean") { + assert_boolean(initial_status); + } + + SimpleReadAccessController.initialize(owner_address); + + let round_id = 1; + let (timestamp) = get_block_timestamp(); + _record_round(round_id, initial_status, timestamp); + + return (); + } + + func update_status{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + from_address: felt, status: felt, timestamp: felt + ) { + alloc_locals; + require_l1_sender(from_address); + with_attr error_message("SequencerUptimeFeed: value isn't a boolean") { + assert_boolean(status); + } + + let (latest_round_id) = SequencerUptimeFeed_latest_round_id.read(); + let (latest_started_at) = SequencerUptimeFeed_rounds.read( + latest_round_id, Round.started_at + ); + let (local latest_status) = SequencerUptimeFeed_rounds.read(latest_round_id, Round.answer); + + let lt = is_le(timestamp, latest_started_at - 1); // timestamp < latest_started_at + if (lt == TRUE) { + UpdateIgnored.emit(latest_status, latest_started_at, status, timestamp); + return (); + } + + if (latest_status == status) { + _update_round(latest_round_id, status); + } else { + let round_id = latest_round_id + 1; + _record_round(round_id, status, timestamp); + } + + return (); + } + + func latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round + ) { + require_access(); + + let (latest_round_id) = SequencerUptimeFeed_latest_round_id.read(); + let (latest_round) = SequencerUptimeFeed.round_data(latest_round_id); + + return (latest_round,); + } + + func round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt + ) -> (res: Round) { + require_access(); + require_valid_round_id(round_id); + + let (round) = _get_round(round_id); + return (round,); + } + + func description{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + description: felt + ) { + return ('L2 Sequencer Uptime Status Feed',); + } + + func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt + ) { + return (0,); + } + + func type_and_version{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + meta: felt + ) { + const meta = 'SequencerUptimeFeed 1.0.0'; + return (meta,); + } +} + +func _set_round{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt, value: Round +) { + SequencerUptimeFeed_rounds.write(id=round_id, field=Round.answer, value=value.answer); + SequencerUptimeFeed_rounds.write(id=round_id, field=Round.block_num, value=value.block_num); + SequencerUptimeFeed_rounds.write(id=round_id, field=Round.started_at, value=value.started_at); + SequencerUptimeFeed_rounds.write(id=round_id, field=Round.updated_at, value=value.updated_at); + + return (); +} + +func _get_round{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt +) -> (round: Round) { + let (answer) = SequencerUptimeFeed_rounds.read(id=round_id, field=Round.answer); + let (block_num) = SequencerUptimeFeed_rounds.read(id=round_id, field=Round.block_num); + let (started_at) = SequencerUptimeFeed_rounds.read(id=round_id, field=Round.started_at); + let (updated_at) = SequencerUptimeFeed_rounds.read(id=round_id, field=Round.updated_at); + + return (Round(round_id, answer, block_num, started_at, updated_at),); +} + +func _set_l1_sender{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + address: felt +) { + let (old_address) = SequencerUptimeFeed_l1_sender.read(); + + if (old_address != address) { + SequencerUptimeFeed_l1_sender.write(address); + L1SenderTransferred.emit(old_address, address); + return (); + } + + return (); +} + +func _record_round{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt, status: felt, timestamp: felt +) { + SequencerUptimeFeed_latest_round_id.write(round_id); + + let (block_num) = get_block_number(); + let (updated_at) = get_block_timestamp(); + + let round = Round( + round_id=round_id, + answer=status, + block_num=block_num, + started_at=timestamp, + updated_at=updated_at, + ); + _set_round(round_id, round); + + let (sender) = get_caller_address(); + NewRound.emit(round_id=round_id, started_by=sender, started_at=timestamp); + AnswerUpdated.emit(status, round_id, timestamp); + + return (); +} + +func _update_round{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt, status: felt +) { + let (updated_at) = get_block_timestamp(); + SequencerUptimeFeed_rounds.write(round_id, Round.updated_at, updated_at); + + RoundUpdated.emit(status, updated_at); + return (); +} diff --git a/contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/sequencer_uptime_feed.cairo b/contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/sequencer_uptime_feed.cairo new file mode 100644 index 0000000..aca4389 --- /dev/null +++ b/contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/sequencer_uptime_feed.cairo @@ -0,0 +1,99 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin + +from plugin.cairo.access.SimpleReadAccessController.library import SimpleReadAccessController +from plugin.cairo.access.SimpleWriteAccessController.library import ( + owner, + proposed_owner, + transfer_ownership, + accept_ownership, + add_access, + remove_access, + enable_access_check, + disable_access_check, +) +from plugin.cairo.ocr2.IAggregator import Round +from plugin.cairo.emergency.SequencerUptimeFeed.library import ( + SequencerUptimeFeed, + set_l1_sender, + l1_sender, +) + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + initial_status: felt, owner_address: felt +) { + SequencerUptimeFeed.initialize(initial_status, owner_address); + return (); +} + +// implements IAggregator +@l1_handler +func update_status{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + from_address: felt, status: felt, timestamp: felt +) { + SequencerUptimeFeed.update_status(from_address, status, timestamp); + return (); +} + +// implements IAggregator +@view +func latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round +) { + let (latest_round) = SequencerUptimeFeed.latest_round_data(); + return (latest_round,); +} + +// implements IAggregator +@view +func round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt +) -> (res: Round) { + let (round) = SequencerUptimeFeed.round_data(round_id); + return (round,); +} + +// implements IAggregator +@view +func description{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + description: felt +) { + let (description) = SequencerUptimeFeed.description(); + return (description,); +} + +// implements IAggregator +@view +func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt +) { + let (decimals) = SequencerUptimeFeed.decimals(); + return (decimals,); +} + +// implements IAggregator +@view +func type_and_version{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + meta: felt +) { + let (meta) = SequencerUptimeFeed.type_and_version(); + return (meta,); +} + +// implements IAccessController +@view +func has_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + user: felt, data_len: felt, data: felt* +) -> (bool: felt) { + let (has_access) = SimpleReadAccessController.has_access(user, data_len, data); + return (has_access,); +} + +// implements IAccessController +@view +func check_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(user: felt) { + SimpleReadAccessController.check_access(user); + return (); +} diff --git a/contracts/src/plugin/cairo/example/Aggregator_consumer.cairo b/contracts/src/plugin/cairo/example/Aggregator_consumer.cairo new file mode 100644 index 0000000..aae9031 --- /dev/null +++ b/contracts/src/plugin/cairo/example/Aggregator_consumer.cairo @@ -0,0 +1,32 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from plugin.cairo.ocr2.IAggregator import IAggregator, Round + +@storage_var +func AggregatorConsumer_ocr_address() -> (address: felt) { +} + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(address: felt) { + AggregatorConsumer_ocr_address.write(address); + return (); +} + +@view +func readLatestRound{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round +) { + let (address) = AggregatorConsumer_ocr_address.read(); + let (round: Round) = IAggregator.latest_round_data(contract_address=address); + return (round,); +} + +@view +func readDecimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt +) { + let (address) = AggregatorConsumer_ocr_address.read(); + let (decimals) = IAggregator.decimals(contract_address=address); + return (decimals,); +} diff --git a/contracts/src/plugin/cairo/introspection/ITypeAndVersion.cairo b/contracts/src/plugin/cairo/introspection/ITypeAndVersion.cairo new file mode 100644 index 0000000..d64f26b --- /dev/null +++ b/contracts/src/plugin/cairo/introspection/ITypeAndVersion.cairo @@ -0,0 +1,7 @@ +%lang starknet + +@contract_interface +namespace ITypeAndVersion { + func type_and_version() -> (meta: felt) { + } +} diff --git a/contracts/src/plugin/cairo/ocr2/IAggregator.cairo b/contracts/src/plugin/cairo/ocr2/IAggregator.cairo new file mode 100644 index 0000000..34e7248 --- /dev/null +++ b/contracts/src/plugin/cairo/ocr2/IAggregator.cairo @@ -0,0 +1,52 @@ +%lang starknet + +struct Round { + round_id: felt, + answer: felt, + block_num: felt, + started_at: felt, + updated_at: felt, +} + +@event +func NewTransmission( + round_id: felt, + answer: felt, + transmitter: felt, + observation_timestamp: felt, + observers: felt, + observations_len: felt, + observations: felt*, + juels_per_fee_coin: felt, + gas_price: felt, + config_digest: felt, + epoch_and_round: felt, + reimbursement: felt, +) { +} + +@event +func AnswerUpdated(current: felt, round_id: felt, timestamp: felt) { +} + +@event +func NewRound(round_id: felt, started_by: felt, started_at: felt) { +} + +@contract_interface +namespace IAggregator { + func latest_round_data() -> (round: Round) { + } + + func round_data(round_id: felt) -> (round: Round) { + } + + func description() -> (description: felt) { + } + + func decimals() -> (decimals: felt) { + } + + func type_and_version() -> (meta: felt) { + } +} diff --git a/contracts/src/plugin/cairo/ocr2/aggregator.cairo b/contracts/src/plugin/cairo/ocr2/aggregator.cairo new file mode 100644 index 0000000..7a066b9 --- /dev/null +++ b/contracts/src/plugin/cairo/ocr2/aggregator.cairo @@ -0,0 +1,1232 @@ +// amarna: disable=arithmetic-div,arithmetic-sub,arithmetic-mul,arithmetic-add +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin, BitwiseBuiltin +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.registers import get_fp_and_pc +from starkware.cairo.common.hash_state import ( + hash_init, + hash_finalize, + hash_update, + hash_update_single, +) +from starkware.cairo.common.signature import verify_ecdsa_signature +from starkware.cairo.common.bitwise import bitwise_and +from starkware.cairo.common.bool import TRUE +from starkware.cairo.common.math import ( + abs_value, + assert_le_felt, + assert_lt, + assert_not_zero, + assert_not_equal, + assert_nn_le, + assert_nn, + assert_in_range, + unsigned_div_rem, +) +from starkware.cairo.common.math_cmp import is_nn +from starkware.cairo.common.pow import pow +from starkware.cairo.common.uint256 import ( + Uint256, + uint256_sub, + uint256_lt, + uint256_le, + uint256_check, +) + +from starkware.starknet.common.syscalls import ( + get_caller_address, + get_contract_address, + get_block_timestamp, + get_block_number, + get_tx_info, +) + +from openzeppelin.utils.constants.library import UINT8_MAX + +from openzeppelin.token.erc20.IERC20 import IERC20 + +from plugin.cairo.access.IAccessController import IAccessController + +from plugin.cairo.utils import felt_to_uint256, uint256_to_felt + +from plugin.cairo.access.ownable import Ownable + +from plugin.cairo.access.SimpleReadAccessController.library import SimpleReadAccessController + +from plugin.cairo.access.SimpleWriteAccessController.library import ( + owner, + proposed_owner, + transfer_ownership, + accept_ownership, + add_access, + remove_access, + enable_access_check, + disable_access_check, +) + +from plugin.cairo.ocr2.IAggregator import NewTransmission, Round + +// --- + +const MAX_ORACLES = 31; + +const GIGA = 10 ** 9; + +const UINT32_MAX = (2 ** 32) - 1; +const INT128_MAX = (2 ** (128 - 1)) - 1; + +// Maximum number of faulty oracles +@storage_var +func Aggregator_f() -> (f: felt) { +} + +@storage_var +func Aggregator_latest_epoch_and_round() -> (res: felt) { +} + +@storage_var +func Aggregator_latest_aggregator_round_id() -> (round_id: felt) { +} + +using Range = (min: felt, max: felt); + +@storage_var +func Aggregator_answer_range() -> (range: Range) { +} + +@storage_var +func Aggregator_decimals() -> (decimals: felt) { +} + +@storage_var +func Aggregator_description() -> (description: felt) { +} + +// + +@storage_var +func Aggregator_latest_config_block_number() -> (block: felt) { +} + +@storage_var +func Aggregator_config_count() -> (count: felt) { +} + +@storage_var +func Aggregator_latest_config_digest() -> (digest: felt) { +} + +@storage_var +func Aggregator_oracles_len() -> (len: felt) { +} + +// TODO: should we pack into (index, payment) = split_felt()? index is u8, payment is u128 +struct Oracle { + index: felt, + + // entire supply of PLI always fits into u96, so felt is safe to use + payment_juels: felt, +} + +@storage_var +func Aggregator_transmitters(pkey: felt) -> (index: Oracle) { +} + +@storage_var +func Aggregator_signers(pkey: felt) -> (index: felt) { +} + +@storage_var +func Aggregator_signers_list(index: felt) -> (pkey: felt) { +} + +@storage_var +func Aggregator_transmitters_list(index: felt) -> (pkey: felt) { +} + +@storage_var +func reward_from_aggregator_round_id_(index: felt) -> (round_id: felt) { +} + +// --- + +struct Transmission { + answer: felt, + block_num: felt, + observation_timestamp: felt, + transmission_timestamp: felt, +} + +@storage_var +func Aggregator_transmissions(round_id: felt) -> (transmission: Transmission) { +} + +// --- + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + owner: felt, + link: felt, + min_answer: felt, + max_answer: felt, + billing_access_controller: felt, + decimals: felt, + description: felt, +) { + Ownable.initializer(owner); + SimpleReadAccessController.initialize(owner); // This also calls Ownable.initializer + Aggregator_link_token.write(link); + Aggregator_billing_access_controller.write(billing_access_controller); + + assert_lt(min_answer, max_answer); + let range: Range = (min_answer, max_answer); + Aggregator_answer_range.write(range); + + with_attr error_message("Aggregator: decimals are negative or exceed 2^8") { + assert_nn_le(decimals, UINT8_MAX); + } + Aggregator_decimals.write(decimals); + Aggregator_description.write(description); + return (); +} + +// --- Validation --- + +// NOTE: Currently unimplemented: +// - Can't set a gas limit on the validator call +// - Can't catch errors in calls so validation could block submission + +// --- Configuration + +@event +func ConfigSet( + previous_config_block_number: felt, + latest_config_digest: felt, + config_count: felt, + oracles_len: felt, + oracles: OracleConfig*, + f: felt, + onchain_config_len: felt, + onchain_config: felt*, + offchain_config_version: felt, + offchain_config_len: felt, + offchain_config: felt*, +) { +} + +struct OracleConfig { + signer: felt, + transmitter: felt, +} + +struct OnchainConfig { + version: felt, + min_answer: felt, + max_answer: felt, +} + +@external +func set_config{ + syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*, range_check_ptr +}( + oracles_len: felt, + oracles: OracleConfig*, + f: felt, + onchain_config_len: felt, + onchain_config: felt*, + offchain_config_version: felt, + offchain_config_len: felt, + offchain_config: felt*, +) -> (digest: felt) { + alloc_locals; + Ownable.assert_only_owner(); + + assert_nn_le(oracles_len, MAX_ORACLES); // oracles_len <= MAX_ORACLES + assert_lt(3 * f, oracles_len); // 3 * f < oracles_len + assert_nn(f); // f is positive + + // Notice: onchain_config is always zero since we don't allow configuring it yet after deployment. + // The contract still computes the onchain_config while digesting the config using min/maxAnswer set on construction. + with_attr error_message("Aggregator: onchain_config must be empty") { + assert onchain_config_len = 0; + } + + let (answer_range: Range) = Aggregator_answer_range.read(); + local computed_onchain_config: OnchainConfig = OnchainConfig( + version=1, min_answer=answer_range.min, max_answer=answer_range.max + ); + // cast to felt* and use OnchainConfig.SIZE as len + let (__fp__, _) = get_fp_and_pc(); + let onchain_config = cast(&computed_onchain_config, felt*); + + // pay out existing oracles + pay_oracles(); + + // remove old signers/transmitters + let (len) = Aggregator_oracles_len.read(); + remove_oracles(len); + + let (latest_round_id) = Aggregator_latest_aggregator_round_id.read(); + + // add new oracles (also sets oracle_len_) + add_oracles(oracles, 0, oracles_len, latest_round_id); + + Aggregator_f.write(f); + let (block_num: felt) = get_block_number(); + let (prev_block_num) = Aggregator_latest_config_block_number.read(); + Aggregator_latest_config_block_number.write(block_num); + // update config count + let (config_count) = Aggregator_config_count.read(); + let config_count = config_count + 1; + Aggregator_config_count.write(config_count); + // calculate and store config digest + let (contract_address) = get_contract_address(); + let (tx_info) = get_tx_info(); + let (digest) = config_digest_from_data( + tx_info.chain_id, + contract_address, + config_count, + oracles_len, + oracles, + f, + OnchainConfig.SIZE, + onchain_config, + offchain_config_version, + offchain_config_len, + offchain_config, + ); + Aggregator_latest_config_digest.write(digest); + + // reset epoch & round + Aggregator_latest_epoch_and_round.write(0); + + ConfigSet.emit( + previous_config_block_number=prev_block_num, + latest_config_digest=digest, + config_count=config_count, + oracles_len=oracles_len, + oracles=oracles, + f=f, + onchain_config_len=OnchainConfig.SIZE, + onchain_config=onchain_config, + offchain_config_version=offchain_config_version, + offchain_config_len=offchain_config_len, + offchain_config=offchain_config, + ); + + return (digest,); +} + +func remove_oracles{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(n: felt) { + if (n == 0) { + Aggregator_oracles_len.write(0); + return (); + } + + // delete oracle from all maps + let (signer) = Aggregator_signers_list.read(n); + Aggregator_signers.write(signer, 0); + + let (transmitter) = Aggregator_transmitters_list.read(n); + Aggregator_transmitters.write(transmitter, Oracle(index=0, payment_juels=0)); + + return remove_oracles(n - 1); +} + +func add_oracles{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + oracles: OracleConfig*, index: felt, len: felt, latest_round_id: felt +) { + if (len == 0) { + Aggregator_oracles_len.write(index); + return (); + } + + // NOTE: index should start with 1 here because storage is 0-initialized. + // That way signers(pkey) => 0 indicates "not present" + let index = index + 1; + + // Check for duplicates + let (existing_signer) = Aggregator_signers.read(oracles.signer); + with_attr error_message("Aggregator: repeated signer") { + assert existing_signer = 0; + } + + let (existing_transmitter: Oracle) = Aggregator_transmitters.read(oracles.transmitter); + with_attr error_message("Aggregator: repeated transmitter") { + assert existing_transmitter.index = 0; + } + + Aggregator_signers.write(oracles.signer, index); + Aggregator_signers_list.write(index, oracles.signer); + + Aggregator_transmitters.write(oracles.transmitter, Oracle(index=index, payment_juels=0)); + Aggregator_transmitters_list.write(index, oracles.transmitter); + + reward_from_aggregator_round_id_.write(index, latest_round_id); + + return add_oracles(oracles + OracleConfig.SIZE, index, len - 1, latest_round_id); +} + +const DIGEST_MASK = 2 ** (252 - 12) - 1; +const PREFIX = 4 * 2 ** (252 - 12); + +func config_digest_from_data{pedersen_ptr: HashBuiltin*, bitwise_ptr: BitwiseBuiltin*}( + chain_id: felt, + contract_address: felt, + config_count: felt, + oracles_len: felt, + oracles: OracleConfig*, + f: felt, + onchain_config_len: felt, + onchain_config: felt*, + offchain_config_version: felt, + offchain_config_len: felt, + offchain_config: felt*, +) -> (hash: felt) { + let hash_ptr = pedersen_ptr; + with hash_ptr { + let (hash_state_ptr) = hash_init(); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, chain_id); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, contract_address); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, config_count); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, oracles_len); + let (hash_state_ptr) = hash_update( + hash_state_ptr, oracles, oracles_len * OracleConfig.SIZE + ); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, f); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, onchain_config_len); + let (hash_state_ptr) = hash_update(hash_state_ptr, onchain_config, onchain_config_len); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, offchain_config_version); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, offchain_config_len); + let (hash_state_ptr) = hash_update(hash_state_ptr, offchain_config, offchain_config_len); + + let (hash) = hash_finalize(hash_state_ptr); + + // clamp the first two bytes with the config digest prefix + let (masked) = bitwise_and(hash, DIGEST_MASK); + let hash = masked + PREFIX; + + let pedersen_ptr = hash_ptr; + return (hash=hash); + } +} + +@view +func latest_config_details{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + config_count: felt, block_number: felt, config_digest: felt +) { + let (config_count) = Aggregator_config_count.read(); + let (block_number) = Aggregator_latest_config_block_number.read(); + let (config_digest) = Aggregator_latest_config_digest.read(); + return (config_count=config_count, block_number=block_number, config_digest=config_digest); +} + +@view +func transmitters{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + transmitters_len: felt, transmitters: felt* +) { + alloc_locals; + + let (result: felt*) = alloc(); + let (len) = Aggregator_oracles_len.read(); + + transmitters_inner(len, 0, result); + + return (transmitters_len=len, transmitters=result); +} + +// unroll transmitter list into a continuous array +func transmitters_inner{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + len: felt, index: felt, result: felt* +) { + if (len == 0) { + return (); + } + + let index = index + 1; + + let (transmitter) = Aggregator_transmitters_list.read(index); + assert result[0] = transmitter; + + return transmitters_inner(len - 1, index, result + 1); +} + +// --- Transmission --- + +struct Signature { + r: felt, + s: felt, + public_key: felt, +} + +struct ReportContext { + config_digest: felt, + epoch_and_round: felt, + extra_hash: felt, +} + +@external +func transmit{ + syscall_ptr: felt*, + pedersen_ptr: HashBuiltin*, + ecdsa_ptr: SignatureBuiltin*, + bitwise_ptr: BitwiseBuiltin*, + range_check_ptr, +}( + report_context: ReportContext, + observation_timestamp: felt, + observers: felt, + observations_len: felt, + observations: felt*, + juels_per_fee_coin: felt, + gas_price: felt, + signatures_len: felt, + signatures: Signature*, +) { + alloc_locals; + + let (epoch_and_round) = Aggregator_latest_epoch_and_round.read(); + with_attr error_message("Aggregator: stale report") { + assert_lt(epoch_and_round, report_context.epoch_and_round); + } + + // validate transmitter + let (caller) = get_caller_address(); + let (oracle: Oracle) = Aggregator_transmitters.read(caller); + assert_not_zero(oracle.index); // 0 index = uninitialized + + // Validate config digest matches latest_config_digest + let (config_digest) = Aggregator_latest_config_digest.read(); + with_attr error_message("Aggregator: config digest mismatch") { + assert report_context.config_digest = config_digest; + } + + let (f) = Aggregator_f.read(); + with_attr error_message("Aggregator: wrong number of signatures f={f}") { + assert signatures_len = (f + 1); + } + + let (msg) = hash_report( + report_context, + observation_timestamp, + observers, + observations_len, + observations, + juels_per_fee_coin, + gas_price, + ); + verify_signatures(msg, signatures, signatures_len, signed_count=0); + + // report(): + + assert_nn_le(observations_len, MAX_ORACLES); // len <= MAX_ORACLES + assert_lt(f, observations_len); // f < len + + Aggregator_latest_epoch_and_round.write(report_context.epoch_and_round); + + let (median_idx: felt, _) = unsigned_div_rem(observations_len, 2); + let median = observations[median_idx]; + + let is_neg = is_nn(median); + + // Check abs(median) is in i128 range. + // NOTE: (assert_le_felt(-i128::MAX, median) doesn't work correctly so we have to use abs!) + let value = abs_value(median); + if (is_neg == 0) { + with_attr error_message("Aggregator: value not in int128 range: {median}") { + assert_le_felt(value, INT128_MAX + 1); + } + } else { + with_attr error_message("Aggregator: value not in int128 range: {median}") { + assert_le_felt(value, INT128_MAX); + } + } + + // Validate median in min-max range + let (answer_range: Range) = Aggregator_answer_range.read(); + assert_in_range(median, answer_range.min, answer_range.max); + + let (local prev_round_id) = Aggregator_latest_aggregator_round_id.read(); + // let (prev_round_id) = Aggregator_latest_aggregator_round_id.read() + let round_id = prev_round_id + 1; + Aggregator_latest_aggregator_round_id.write(round_id); + + let (timestamp: felt) = get_block_timestamp(); + let (block_num: felt) = get_block_number(); + + // write to storage + Aggregator_transmissions.write( + round_id, + Transmission( + answer=median, + block_num=block_num, + observation_timestamp=observation_timestamp, + transmission_timestamp=timestamp, + ), + ); + + // NOTE: Usually validating via validator would happen here, currently disabled + + let (billing: Billing) = Aggregator_billing.read(); + + let (reimbursement_juels) = calculate_reimbursement( + juels_per_fee_coin, signatures_len, gas_price, billing + ); + + // end report() + + NewTransmission.emit( + round_id=round_id, + answer=median, + transmitter=caller, + observation_timestamp=observation_timestamp, + observers=observers, + observations_len=observations_len, + observations=observations, + juels_per_fee_coin=juels_per_fee_coin, + gas_price=gas_price, + config_digest=report_context.config_digest, + epoch_and_round=report_context.epoch_and_round, + reimbursement=reimbursement_juels, + ); + + // pay transmitter + let payment = reimbursement_juels + (billing.transmission_payment_gjuels * GIGA); + // TODO: check overflow + + Aggregator_transmitters.write( + caller, Oracle(index=oracle.index, payment_juels=oracle.payment_juels + payment) + ); + + return (); +} + +func hash_report{pedersen_ptr: HashBuiltin*}( + report_context: ReportContext, + observation_timestamp: felt, + observers: felt, + observations_len: felt, + observations: felt*, + juels_per_fee_coin: felt, + gas_price: felt, +) -> (hash: felt) { + let hash_ptr = pedersen_ptr; + with hash_ptr { + let (hash_state_ptr) = hash_init(); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, report_context.config_digest); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, report_context.epoch_and_round); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, report_context.extra_hash); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, observation_timestamp); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, observers); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, observations_len); + let (hash_state_ptr) = hash_update(hash_state_ptr, observations, observations_len); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, juels_per_fee_coin); + let (hash_state_ptr) = hash_update_single(hash_state_ptr, gas_price); + + let (hash) = hash_finalize(hash_state_ptr); + let pedersen_ptr = hash_ptr; + return (hash=hash); + } +} + +func verify_signatures{ + syscall_ptr: felt*, + pedersen_ptr: HashBuiltin*, + ecdsa_ptr: SignatureBuiltin*, + bitwise_ptr: BitwiseBuiltin*, + range_check_ptr, +}(msg: felt, signatures: Signature*, signatures_len: felt, signed_count: felt) { + alloc_locals; + + // 'signed_count' is used for tracking duplicate signatures + if (signatures_len == 0) { + // Check all signatures are unique (we only saw each pubkey once) + // NOTE: This relies on protocol-level design constraints (MAX_ORACLES = 31, f = 10) which + // ensures 31 bytes is enough to store a count for each oracle. Whenever the MAX_ORACLES + // is updated the mask below should also be updated. + assert MAX_ORACLES = 31; + let (masked) = bitwise_and( + signed_count, 0x01010101010101010101010101010101010101010101010101010101010101 + ); + with_attr error_message("Aggregator: duplicate signer") { + assert signed_count = masked; + } + return (); + } + + let signature = signatures[0]; + + // Validate the signer key actually belongs to an oracle + let (index) = Aggregator_signers.read(signature.public_key); + with_attr error_message("Aggregator: invalid signer {signature.public_key}") { + assert_not_zero(index); // 0 index = uninitialized + } + + verify_ecdsa_signature( + message=msg, + public_key=signature.public_key, + signature_r=signature.r, + signature_s=signature.s, + ); + + // TODO: Using shifts here might be expensive due to pow()? + // evaluate using alloc() to allocate a signed_count[oracles_len] instead + + // signed_count + 1 << (8 * index) + let (shift) = pow(2, 8 * index); + let signed_count = signed_count + shift; + + return verify_signatures(msg, signatures + Signature.SIZE, signatures_len - 1, signed_count); +} + +@view +func latest_transmission_details{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + ) -> (config_digest: felt, epoch_and_round: felt, latest_answer: felt, latest_timestamp: felt) { + let (config_digest) = Aggregator_latest_config_digest.read(); + let (latest_round_id) = Aggregator_latest_aggregator_round_id.read(); + let (epoch_and_round) = Aggregator_latest_epoch_and_round.read(); + let (transmission: Transmission) = Aggregator_transmissions.read(latest_round_id); + + return ( + config_digest=config_digest, + epoch_and_round=epoch_and_round, + latest_answer=transmission.answer, + latest_timestamp=transmission.transmission_timestamp, + ); +} + +// --- RequestNewRound + +// --- Queries + +// Read access helper +func require_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (address) = get_caller_address(); + SimpleReadAccessController.check_access(address); + + return (); +} + +@view +func description{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + description: felt +) { + require_access(); + let (description) = Aggregator_description.read(); + return (description,); +} + +@view +func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt +) { + require_access(); + let (decimals) = Aggregator_decimals.read(); + return (decimals,); +} + +@view +func round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt +) -> (round: Round) { + require_access(); + // TODO: assert round_id fits in u32 + + let (transmission: Transmission) = Aggregator_transmissions.read(round_id); + + let round = Round( + round_id=round_id, + answer=transmission.answer, + block_num=transmission.block_num, + started_at=transmission.observation_timestamp, + updated_at=transmission.transmission_timestamp, + ); + return (round,); +} + +@view +func latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round +) { + require_access(); + let (latest_round_id) = Aggregator_latest_aggregator_round_id.read(); + let (transmission: Transmission) = Aggregator_transmissions.read(latest_round_id); + + let round = Round( + round_id=latest_round_id, + answer=transmission.answer, + block_num=transmission.block_num, + started_at=transmission.observation_timestamp, + updated_at=transmission.transmission_timestamp, + ); + return (round,); +} + +// --- Set PLI Token + +@storage_var +func Aggregator_link_token() -> (token: felt) { +} + +@event +func LinkTokenSet(old_link_token: felt, new_link_token: felt) { +} + +@external +func set_link_token{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + link_token: felt, recipient: felt +) { + alloc_locals; + Ownable.assert_only_owner(); + + let (old_token) = Aggregator_link_token.read(); + if (link_token == old_token) { + return (); + } + + let (contract_address) = get_contract_address(); + + // call balanceOf as a sanity check to confirm we're talking to a token + IERC20.balanceOf(contract_address=link_token, account=contract_address); + + pay_oracles(); + + // transfer remaining balance to recipient + let (amount: Uint256) = IERC20.balanceOf(contract_address=link_token, account=contract_address); + IERC20.transfer(contract_address=old_token, recipient=recipient, amount=amount); + + Aggregator_link_token.write(link_token); + + LinkTokenSet.emit(old_link_token=old_token, new_link_token=link_token); + + return (); +} + +@view +func link_token{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + link_token: felt +) { + let (link_token) = Aggregator_link_token.read(); + return (link_token,); +} + +// --- Billing Access Controller + +@storage_var +func Aggregator_billing_access_controller() -> (access_controller: felt) { +} + +@event +func BillingAccessControllerSet(old_controller: felt, new_controller: felt) { +} + +@external +func set_billing_access_controller{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + access_controller: felt +) { + Ownable.assert_only_owner(); + + let (old_controller) = Aggregator_billing_access_controller.read(); + if (access_controller != old_controller) { + Aggregator_billing_access_controller.write(access_controller); + + BillingAccessControllerSet.emit( + old_controller=old_controller, new_controller=access_controller + ); + + return (); + } + + return (); +} + +@view +func billing_access_controller{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + ) -> (access_controller: felt) { + let (access_controller) = Aggregator_billing_access_controller.read(); + return (access_controller,); +} + +// --- Billing Config + +struct Billing { + // TODO: use a single felt via (observation_payment, transmission_payment) = split_felt()? + observation_payment_gjuels: felt, + transmission_payment_gjuels: felt, + gas_base: felt, + gas_per_signature: felt, +} + +@storage_var +func Aggregator_billing() -> (config: Billing) { +} + +@view +func billing{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + config: Billing +) { + let (config: Billing) = Aggregator_billing.read(); + return (config,); +} + +@event +func BillingSet(config: Billing) { +} + +@external +func set_billing{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(config: Billing) { + has_billing_access(); + + // Pay out oracles using existing settings for rounds up to now + pay_oracles(); + + // check payment value ranges within u32 bounds + assert_nn_le(config.observation_payment_gjuels, UINT32_MAX); + assert_nn_le(config.transmission_payment_gjuels, UINT32_MAX); + assert_nn_le(config.gas_base, UINT32_MAX); + assert_nn_le(config.gas_per_signature, UINT32_MAX); + + Aggregator_billing.write(config); + + BillingSet.emit(config=config); + + return (); +} + +func has_billing_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (caller) = get_caller_address(); + let (owner) = Ownable.get_owner(); + + // owner always has access + if (caller == owner) { + return (); + } + + let (access_controller) = Aggregator_billing_access_controller.read(); + + IAccessController.check_access(contract_address=access_controller, user=caller); + return (); +} + +// --- Payments and Withdrawals + +@event +func OraclePaid(transmitter: felt, payee: felt, amount: Uint256, link_token: felt) { +} + +@external +func withdraw_payment{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + transmitter: felt +) { + alloc_locals; + let (caller) = get_caller_address(); + let (payee) = Aggregator_payees.read(transmitter); + with_attr error_message("Aggregator: only payee can withdraw") { + assert caller = payee; + } + + let (latest_round_id) = Aggregator_latest_aggregator_round_id.read(); + let (link_token) = Aggregator_link_token.read(); + pay_oracle(transmitter, latest_round_id, link_token); + return (); +} + +func _owed_payment{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + oracle: Oracle +) -> (amount: felt) { + if (oracle.index == 0) { + return (0,); + } + + let (billing: Billing) = Aggregator_billing.read(); + + let (latest_round_id) = Aggregator_latest_aggregator_round_id.read(); + let (from_round_id) = reward_from_aggregator_round_id_.read(oracle.index); + let rounds = latest_round_id - from_round_id; + + let amount = (rounds * billing.observation_payment_gjuels * GIGA) + oracle.payment_juels; + return (amount,); +} + +@external +func owed_payment{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + transmitter: felt +) -> (amount: felt) { + let (oracle: Oracle) = Aggregator_transmitters.read(transmitter); + let (amount: felt) = _owed_payment(oracle); + return (amount,); +} + +func pay_oracle{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + transmitter: felt, latest_round_id: felt, link_token: felt +) { + alloc_locals; + + let (oracle: Oracle) = Aggregator_transmitters.read(transmitter); + + if (oracle.index == 0) { + return (); + } + + let (amount_: felt) = _owed_payment(oracle); + assert_nn(amount_); + + // if zero, fastpath return to avoid empty transfers + if (amount_ == 0) { + return (); + } + + let (amount: Uint256) = felt_to_uint256(amount_); + let (payee) = Aggregator_payees.read(transmitter); + + IERC20.transfer(contract_address=link_token, recipient=payee, amount=amount); + + // Reset payment + reward_from_aggregator_round_id_.write(oracle.index, latest_round_id); + Aggregator_transmitters.write(transmitter, Oracle(index=oracle.index, payment_juels=0)); + + OraclePaid.emit(transmitter=transmitter, payee=payee, amount=amount, link_token=link_token); + + return (); +} + +func pay_oracles{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (len) = Aggregator_oracles_len.read(); + let (latest_round_id) = Aggregator_latest_aggregator_round_id.read(); + let (link_token) = Aggregator_link_token.read(); + pay_oracles_(len, latest_round_id, link_token); + return (); +} + +func pay_oracles_{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + index: felt, latest_round_id: felt, link_token: felt +) { + if (index == 0) { + return (); + } + + let (transmitter) = Aggregator_transmitters_list.read(index); + pay_oracle(transmitter, latest_round_id, link_token); + + return pay_oracles_(index - 1, latest_round_id, link_token); +} + +@external +func withdraw_funds{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + recipient: felt, amount: Uint256 +) { + alloc_locals; + has_billing_access(); + uint256_check(amount); + let (link_token) = Aggregator_link_token.read(); + let (contract_address) = get_contract_address(); + + let (link_due) = total_link_due(); + let (balance: Uint256) = IERC20.balanceOf( + contract_address=link_token, account=contract_address + ); + + let (link_due_uint256: Uint256) = felt_to_uint256(link_due); + let (res) = uint256_le(link_due_uint256, balance); + with_attr error_message("Aggregator: total amount due exceeds the balance") { + assert res = 1; + } + + let (available: Uint256) = uint256_sub(balance, link_due_uint256); + + let (less_available: felt) = uint256_lt(available, amount); + if (less_available == TRUE) { + // Transfer as much as there is available + IERC20.transfer(contract_address=link_token, recipient=recipient, amount=available); + } else { + IERC20.transfer(contract_address=link_token, recipient=recipient, amount=amount); + } + + return (); +} + +func total_link_due{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + due: felt +) { + let (len) = Aggregator_oracles_len.read(); + let (latest_round_id) = Aggregator_latest_aggregator_round_id.read(); + + let (amount) = total_link_due_(len, latest_round_id, 0, 0); + return (amount,); +} + +func total_link_due_{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + index: felt, latest_round_id: felt, total_rounds: felt, payments_juels: felt +) -> (due: felt) { + if (index == 0) { + let (billing: Billing) = Aggregator_billing.read(); + let amount = (total_rounds * billing.observation_payment_gjuels * GIGA) + payments_juels; + return (amount,); + } + + let (transmitter) = Aggregator_transmitters_list.read(index); + let (oracle: Oracle) = Aggregator_transmitters.read(transmitter); + assert_not_zero(oracle.index); // 0 == undefined + + let (from_round_id) = reward_from_aggregator_round_id_.read(oracle.index); + let rounds = latest_round_id - from_round_id; + + let total_rounds = total_rounds + rounds; + let payments_juels = payments_juels + oracle.payment_juels; + + return total_link_due_(index - 1, latest_round_id, total_rounds, payments_juels); +} + +// since the felt type in Cairo is not signed, whoever calls this function will have to interpret the result line 1070 as the correct negative value. +@view +func link_available_for_payment{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + ) -> (available: felt) { + alloc_locals; + let (link_token) = Aggregator_link_token.read(); + let (contract_address) = get_contract_address(); + + let (balance_: Uint256) = IERC20.balanceOf( + contract_address=link_token, account=contract_address + ); + // entire link supply fits into u96 so this should not fail + let (balance) = uint256_to_felt(balance_); + + let (due) = total_link_due(); + let amount = balance - due; + + return (available=amount); +} + +// --- Transmitter Payment + +const MARGIN = 115; + +func calculate_reimbursement{range_check_ptr}( + juels_per_fee_coin: felt, signature_count: felt, gas_price: felt, config: Billing +) -> (amount_juels: felt) { + // Based on estimateFee (f=1 14977, f=2 14989, f=3 15002 f=4 15014 f=5 15027, count = f+1) + // NOTE: seems a bit odd since each ecdsa is supposed to be 25.6 gas: https://docs.starknet.io/docs/Fees/fee-mechanism/ + // gas_base = 14951, gas_per_signature = 13 + let exact_gas = config.gas_base + (signature_count * config.gas_per_signature); + let (gas: felt, _) = unsigned_div_rem(exact_gas * MARGIN, 100); // scale to 115% for some margin + let amount = gas * gas_price; + let amount_juels = amount * juels_per_fee_coin; + return (amount_juels,); +} + +// --- Payee Management + +@storage_var +func Aggregator_payees(transmitter: felt) -> (payment_address: felt) { +} + +@storage_var +func Aggregator_proposed_payees(transmitter: felt) -> (payment_address: felt) { +} + +@event +func PayeeshipTransferRequested(transmitter: felt, current: felt, proposed: felt) { +} + +@event +func PayeeshipTransferred(transmitter: felt, previous: felt, current: felt) { +} + +struct PayeeConfig { + transmitter: felt, + payee: felt, +} + +@external +func set_payees{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + payees_len: felt, payees: PayeeConfig* +) { + Ownable.assert_only_owner(); + + set_payee(payees, payees_len); + + return (); +} + +// Returns 1 if value == 0. Returns 0 otherwise. +func is_zero(value) -> (res: felt) { + if (value == 0) { + return (res=1); + } + + return (res=0); +} + +func set_payee{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + payees: PayeeConfig*, len: felt +) { + if (len == 0) { + return (); + } + + let (current_payee) = Aggregator_payees.read(payees.transmitter); + + // a more convoluted way of saying + // require(current_payee == 0 || current_payee == payee, "payee already set") + let (is_unset) = is_zero(current_payee); + let (is_same) = is_zero(current_payee - payees.payee); + with_attr error_message("Aggregator: payee already set") { + assert (is_unset - 1) * (is_same - 1) = 0; + } + + Aggregator_payees.write(payees.transmitter, payees.payee); + + PayeeshipTransferred.emit( + transmitter=payees.transmitter, previous=current_payee, current=payees.payee + ); + + return set_payee(payees + PayeeConfig.SIZE, len - 1); +} + +@external +func transfer_payeeship{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + transmitter: felt, proposed: felt +) { + with_attr error_message("Aggregator: cannot transfer payeeship to zero address") { + assert_not_zero(proposed); + } + let (caller) = get_caller_address(); + let (payee) = Aggregator_payees.read(transmitter); + with_attr error_message("Aggregator: only current payee can update") { + assert caller = payee; + } + with_attr error_message("Aggregator: cannot transfer to self") { + assert_not_equal(caller, proposed); + } + + Aggregator_proposed_payees.write(transmitter, proposed); + + PayeeshipTransferRequested.emit(transmitter=transmitter, current=payee, proposed=proposed); + + return (); +} + +@external +func accept_payeeship{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + transmitter: felt +) { + let (proposed) = Aggregator_proposed_payees.read(transmitter); + let (caller) = get_caller_address(); + with_attr error_message("Aggregator: only proposed payee can accept") { + assert caller = proposed; + } + + let (previous) = Aggregator_payees.read(transmitter); + Aggregator_payees.write(transmitter, caller); + Aggregator_proposed_payees.write(transmitter, 0); + + PayeeshipTransferred.emit(transmitter=transmitter, previous=previous, current=caller); + + return (); +} + +@view +func type_and_version() -> (meta: felt) { + return ('ocr2/aggregator.cairo 1.0.0',); +} diff --git a/contracts/src/plugin/cairo/ocr2/aggregator_proxy.cairo b/contracts/src/plugin/cairo/ocr2/aggregator_proxy.cairo new file mode 100644 index 0000000..749539f --- /dev/null +++ b/contracts/src/plugin/cairo/ocr2/aggregator_proxy.cairo @@ -0,0 +1,225 @@ +// amarna: disable=arithmetic-div,arithmetic-sub,arithmetic-mul,arithmetic-add +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.math import split_felt, assert_not_zero +from starkware.starknet.common.syscalls import get_caller_address + +from plugin.cairo.ocr2.IAggregator import IAggregator, Round + +from plugin.cairo.access.SimpleReadAccessController.library import SimpleReadAccessController +from plugin.cairo.access.SimpleWriteAccessController.library import ( + owner, + proposed_owner, + transfer_ownership, + accept_ownership, + add_access, + remove_access, + enable_access_check, + disable_access_check, +) +from plugin.cairo.access.ownable import Ownable + +struct Phase { + id: felt, + aggregator: felt, +} + +@storage_var +func AggregatorProxy_current_phase() -> (phase: Phase) { +} + +@storage_var +func AggregatorProxy_proposed_aggregator() -> (address: felt) { +} + +@storage_var +func AggregatorProxy_phases(id: felt) -> (address: felt) { +} + +const SHIFT = 2 ** 128; +const MAX_ID = SHIFT - 1; + +@event +func AggregatorProposed(current: felt, proposed: felt) { +} + +@event +func AggregatorConfirmed(previous: felt, latest: felt) { +} + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + owner: felt, address: felt +) { + SimpleReadAccessController.initialize(owner); // This also calls Ownable.initializer + set_aggregator(address); + return (); +} + +func set_aggregator{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + address: felt +) { + let (current_phase: Phase) = AggregatorProxy_current_phase.read(); + let id = current_phase.id + 1; + AggregatorProxy_current_phase.write(Phase(id=id, aggregator=address)); + AggregatorProxy_phases.write(id, address); + return (); +} + +@external +func propose_aggregator{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + address: felt +) { + Ownable.assert_only_owner(); + with_attr error_message("AggregatorProxy: aggregator is zero address") { + assert_not_zero(address); + } + AggregatorProxy_proposed_aggregator.write(address); + + // emit event + let (phase: Phase) = AggregatorProxy_current_phase.read(); + AggregatorProposed.emit(current=phase.aggregator, proposed=address); + return (); +} + +@external +func confirm_aggregator{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + address: felt +) { + Ownable.assert_only_owner(); + with_attr error_message("AggregatorProxy: aggregator is zero address") { + assert_not_zero(address); + } + let (phase: Phase) = AggregatorProxy_current_phase.read(); + let previous = phase.aggregator; + + let (proposed_aggregator) = AggregatorProxy_proposed_aggregator.read(); + assert proposed_aggregator = address; + AggregatorProxy_proposed_aggregator.write(0); + set_aggregator(proposed_aggregator); + + // emit event + AggregatorConfirmed.emit(previous=previous, latest=address); + return (); +} + +// Read access helper +func require_access{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (address) = get_caller_address(); + SimpleReadAccessController.check_access(address); + + return (); +} + +@view +func latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round +) { + require_access(); + let (phase: Phase) = AggregatorProxy_current_phase.read(); + let (round: Round) = IAggregator.latest_round_data(contract_address=phase.aggregator); + + // Add phase_id to the high bits of round_id + let round_id = round.round_id + (phase.id * SHIFT); + return ( + Round( + round_id=round_id, + answer=round.answer, + block_num=round.block_num, + started_at=round.started_at, + updated_at=round.updated_at, + ), + ); +} + +@view +func round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt +) -> (round: Round) { + require_access(); + let (phase_id, round_id) = split_felt(round_id); + let (address) = AggregatorProxy_phases.read(phase_id); + assert_not_zero(address); + + let (round: Round) = IAggregator.round_data(contract_address=address, round_id=round_id); + // Add phase_id to the high bits of round_id + let round_id = round.round_id + (phase_id * SHIFT); + return ( + Round( + round_id=round_id, + answer=round.answer, + block_num=round.block_num, + started_at=round.started_at, + updated_at=round.updated_at, + ), + ); +} + +// These read from the proposed aggregator as a way to test the aggregator before making setting it live. + +@view +func proposed_latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + ) -> (round: Round) { + require_access(); + let (aggregator) = AggregatorProxy_proposed_aggregator.read(); + let (round: Round) = IAggregator.latest_round_data(contract_address=aggregator); + return (round,); +} + +@view +func proposed_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + round_id: felt +) -> (round: Round) { + require_access(); + let (aggregator) = AggregatorProxy_proposed_aggregator.read(); + let (round: Round) = IAggregator.round_data(contract_address=aggregator, round_id=round_id); + return (round,); +} + +@view +func aggregator{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + aggregator: felt +) { + require_access(); + let (phase: Phase) = AggregatorProxy_current_phase.read(); + return (phase.aggregator,); +} + +@view +func phase_id{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + phase_id: felt +) { + require_access(); + let (phase: Phase) = AggregatorProxy_current_phase.read(); + return (phase.id,); +} + +@view +func description{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + description: felt +) { + require_access(); + let (phase: Phase) = AggregatorProxy_current_phase.read(); + let (description) = IAggregator.description(contract_address=phase.aggregator); + return (description,); +} + +@view +func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt +) { + require_access(); + let (phase: Phase) = AggregatorProxy_current_phase.read(); + let (decimals) = IAggregator.decimals(contract_address=phase.aggregator); + return (decimals,); +} + +@view +func type_and_version{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + meta: felt +) { + let (phase: Phase) = AggregatorProxy_current_phase.read(); + let (meta) = IAggregator.type_and_version(contract_address=phase.aggregator); + return (meta,); +} diff --git a/contracts/src/plugin/cairo/ocr2/mocks/MockAggregator.cairo b/contracts/src/plugin/cairo/ocr2/mocks/MockAggregator.cairo new file mode 100644 index 0000000..adc4941 --- /dev/null +++ b/contracts/src/plugin/cairo/ocr2/mocks/MockAggregator.cairo @@ -0,0 +1,94 @@ +%lang starknet + +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import HashBuiltin +from plugin.cairo.ocr2.IAggregator import NewTransmission, Round + +struct Transmission { + answer: felt, + block_num: felt, + observation_timestamp: felt, + transmission_timestamp: felt, +} + +@storage_var +func MockAggregator_transmissions(round_id: felt) -> (transmission: Transmission) { +} + +@storage_var +func MockAggregator_latest_aggregator_round_id() -> (round_id: felt) { +} + +@storage_var +func MockAggregator_decimals() -> (decimals: felt) { +} + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(decimals: felt) { + MockAggregator_decimals.write(decimals); + return (); +} + +@external +func set_latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + answer: felt, block_num: felt, observation_timestamp: felt, transmission_timestamp: felt +) { + alloc_locals; + let (prev_round_id) = MockAggregator_latest_aggregator_round_id.read(); + let round_id = prev_round_id + 1; + MockAggregator_latest_aggregator_round_id.write(round_id); + MockAggregator_transmissions.write( + round_id, + Transmission( + answer=answer, + block_num=block_num, + observation_timestamp=observation_timestamp, + transmission_timestamp=transmission_timestamp, + ), + ); + + let (observations: felt*) = alloc(); + assert observations[0] = 2; + assert observations[1] = 3; + NewTransmission.emit( + round_id=round_id, + answer=answer, + transmitter=12, + observation_timestamp=observation_timestamp, + observers=3, + observations_len=2, + observations=observations, + juels_per_fee_coin=18, + gas_price=1, + config_digest=34, + epoch_and_round=20, + reimbursement=100, + ); + return (); +} + +@view +func latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round +) { + alloc_locals; + let (latest_round_id) = MockAggregator_latest_aggregator_round_id.read(); + let (transmission: Transmission) = MockAggregator_transmissions.read(latest_round_id); + + let round = Round( + round_id=latest_round_id, + answer=transmission.answer, + block_num=transmission.block_num, + started_at=transmission.observation_timestamp, + updated_at=transmission.transmission_timestamp, + ); + return (round,); +} + +@view +func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt +) { + let (decimals) = MockAggregator_decimals.read(); + return (decimals,); +} diff --git a/contracts/src/plugin/cairo/token/ERC677/IERC677.cairo b/contracts/src/plugin/cairo/token/ERC677/IERC677.cairo new file mode 100644 index 0000000..7854c87 --- /dev/null +++ b/contracts/src/plugin/cairo/token/ERC677/IERC677.cairo @@ -0,0 +1,13 @@ +%lang starknet + +from starkware.cairo.common.uint256 import Uint256 + +@event +func Transfer(from_: felt, to: felt, value: Uint256, data_len: felt, data: felt*) { +} + +@contract_interface +namespace IERC677 { + func transferAndCall(to: felt, value: Uint256, data_len: felt, data: felt*) -> (success: felt) { + } +} diff --git a/contracts/src/plugin/cairo/token/ERC677/IERC677Receiver.cairo b/contracts/src/plugin/cairo/token/ERC677/IERC677Receiver.cairo new file mode 100644 index 0000000..6db1039 --- /dev/null +++ b/contracts/src/plugin/cairo/token/ERC677/IERC677Receiver.cairo @@ -0,0 +1,12 @@ +%lang starknet + +from starkware.cairo.common.uint256 import Uint256 + +@contract_interface +namespace IERC677Receiver { + func onTokenTransfer(sender: felt, value: Uint256, data_len: felt, data: felt*) { + } + + func supportsInterface(interface_id: felt) -> (success: felt) { + } +} diff --git a/contracts/src/plugin/cairo/token/ERC677/README.md b/contracts/src/plugin/cairo/token/ERC677/README.md new file mode 100644 index 0000000..635f672 --- /dev/null +++ b/contracts/src/plugin/cairo/token/ERC677/README.md @@ -0,0 +1,18 @@ +# Plugin ERC677 + +## starkgate_token.cairo + +Similar to the starkgate ERC20 contract but with some added functionality from ERC677. + +### transferAndCall + +Transfers tokens to receiver, via ERC20's `transfer(address, address, uint256)` function. It then logs an event `Transfer(address,address,uint256,bytes)`. + +Once the transfer has succeeded and the event is logged, the token calls `onTokenTransfer(sender, value, data_len, data)` on the receiver with `data[0]` as the function's selector, and all the parameters required by the function that you want to call next. + +## Receiver contract + +### onTokenTransfer + +This function is added to contracts enabling them to react to receiving tokens within a single transaction. The `data[0]` parameter is the selector of the function that you want to call. +The data paramater contains all the parameters required by the function that you want to call through the selector. diff --git a/contracts/src/plugin/cairo/token/ERC677/library.cairo b/contracts/src/plugin/cairo/token/ERC677/library.cairo new file mode 100644 index 0000000..e1b865c --- /dev/null +++ b/contracts/src/plugin/cairo/token/ERC677/library.cairo @@ -0,0 +1,38 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.uint256 import Uint256, uint256_check +from starkware.starknet.common.syscalls import get_caller_address +from starkware.cairo.common.bool import TRUE +from openzeppelin.token.erc20.library import ERC20 +from plugin.cairo.token.ERC677.IERC677Receiver import IERC677Receiver +from plugin.cairo.token.ERC677.IERC677 import Transfer + +const IERC677_RECEIVER_ID = 0x4f3dcd; + +// https://github.com/ethereum/EIPs/issues/677 +namespace ERC677 { + // All non-account contracts that want to receive the `transferAndCall` need to implement ERC165 + ERC677, or revert. + // All account contracts need to implement ERC165 (to be detected as an account, or revert), and optionally ERC677 + // if they want to be triggered, if not they'll still receive funds but not the trigger. + func transfer_and_call{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + to: felt, value: Uint256, data_len: felt, data: felt* + ) -> (success: felt) { + alloc_locals; + + uint256_check(value); + let (sender) = get_caller_address(); + + // ERC20.transfer will check that both addresses are not zero + ERC20.transfer(to, value); + Transfer.emit(sender, to, value, data_len, data); + + // TODO: should we always just return TRUE, for all cases? + let (bool) = IERC677Receiver.supportsInterface(to, IERC677_RECEIVER_ID); + if (bool == TRUE) { + IERC677Receiver.onTokenTransfer(to, sender, value, data_len, data); + return (TRUE,); + } + return (TRUE,); + } +} diff --git a/contracts/src/plugin/cairo/token/ERC677/mock/link_receiver.cairo b/contracts/src/plugin/cairo/token/ERC677/mock/link_receiver.cairo new file mode 100644 index 0000000..f724f70 --- /dev/null +++ b/contracts/src/plugin/cairo/token/ERC677/mock/link_receiver.cairo @@ -0,0 +1,105 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.bool import TRUE +from starkware.cairo.common.uint256 import Uint256, uint256_check +from starkware.starknet.common.syscalls import get_contract_address, library_call +from starkware.cairo.common.math import assert_not_zero + +from openzeppelin.introspection.erc165.library import ERC165 +from openzeppelin.token.erc20.IERC20 import IERC20 + +const IERC677_RECEIVER_ID = 0x4f3dcd; + +@storage_var +func linkReceiver_fallback_called_() -> (bool: felt) { +} + +@storage_var +func linkReceiver_call_data_called_() -> (bool: felt) { +} + +@storage_var +func linkReceiver_tokens_received_() -> (value: Uint256) { +} + +@storage_var +func linkReceiver_implementation_hash_() -> (class_hash: felt) { +} + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + class_hash: felt +) { + ERC165.register_interface(IERC677_RECEIVER_ID); + linkReceiver_implementation_hash_.write(class_hash); + return (); +} + +@external +func onTokenTransfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + sender: felt, value: Uint256, data_len: felt, data: felt* +) { + uint256_check(value); + with_attr error_message( + "LinkReceiver: data_len must not be null. It needs at least one selector") { + assert_not_zero(data_len); + } + linkReceiver_fallback_called_.write(TRUE); + let (class_hash) = linkReceiver_implementation_hash_.read(); + let selector = data[0]; + let data = data + 1; + library_call(class_hash, selector, data_len - 1, data); + return (); +} + +@external +func callbackWithoutWithdrawl{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + linkReceiver_call_data_called_.write(TRUE); + return (); +} + +@external +func callbackWithWithdrawl{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + value_high: felt, value_low: felt, sender: felt, token_addr: felt +) { + let value: Uint256 = Uint256(low=value_low, high=value_high); + linkReceiver_call_data_called_.write(TRUE); + let (contract_address) = get_contract_address(); + IERC20.transferFrom(token_addr, sender, contract_address, value); + + linkReceiver_tokens_received_.write(value); + return (); +} + +@view +func supportsInterface{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + interface_id: felt +) -> (success: felt) { + let (success) = ERC165.supports_interface(interface_id); + return (success,); +} + +@view +func getFallback{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + bool: felt +) { + let (bool) = linkReceiver_fallback_called_.read(); + return (bool,); +} + +@view +func getCallData{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + bool: felt +) { + let (bool) = linkReceiver_call_data_called_.read(); + return (bool,); +} + +@view +func getTokens{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + value: Uint256 +) { + let (value) = linkReceiver_tokens_received_.read(); + return (value,); +} diff --git a/contracts/src/plugin/cairo/token/ERC677/mock/not_erc677_compatible.cairo b/contracts/src/plugin/cairo/token/ERC677/mock/not_erc677_compatible.cairo new file mode 100644 index 0000000..88c3528 --- /dev/null +++ b/contracts/src/plugin/cairo/token/ERC677/mock/not_erc677_compatible.cairo @@ -0,0 +1,8 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + return (); +} diff --git a/contracts/src/plugin/cairo/token/ERC677/mock/token677_receiver_mock.cairo b/contracts/src/plugin/cairo/token/ERC677/mock/token677_receiver_mock.cairo new file mode 100644 index 0000000..74c304a --- /dev/null +++ b/contracts/src/plugin/cairo/token/ERC677/mock/token677_receiver_mock.cairo @@ -0,0 +1,92 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.bool import TRUE, FALSE +from starkware.cairo.common.uint256 import Uint256, uint256_check +from openzeppelin.introspection.erc165.library import ERC165 + +const IERC677_RECEIVER_ID = 0x4f3dcd; + +@storage_var +func token677ReceiverMock_token_sender_() -> (address: felt) { +} + +@storage_var +func token677ReceiverMock_sent_value_() -> (value: Uint256) { +} + +@storage_var +func token677ReceiverMock_token_data_(index: felt) -> (data: felt) { +} + +@storage_var +func token677ReceiverMock_token_data_len_() -> (data_len: felt) { +} + +@storage_var +func token677ReceiverMock_called_fallback_() -> (bool: felt) { +} + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + ERC165.register_interface(IERC677_RECEIVER_ID); + token677ReceiverMock_called_fallback_.write(FALSE); + return (); +} + +@external +func onTokenTransfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + sender: felt, value: Uint256, data_len: felt, data: felt* +) { + uint256_check(value); + token677ReceiverMock_called_fallback_.write(TRUE); + token677ReceiverMock_token_sender_.write(sender); + token677ReceiverMock_sent_value_.write(value); + token677ReceiverMock_token_data_len_.write(data_len); + fillDataStorage(0, data_len, data); + return (); +} + +func fillDataStorage{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + index: felt, data_len: felt, data: felt* +) { + if (data_len == 0) { + return (); + } + + let index = index + 1; + token677ReceiverMock_token_data_.write(index, [data]); + return fillDataStorage(index=index, data_len=data_len - 1, data=data + 1); +} + +@view +func supportsInterface{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + interface_id: felt +) -> (success: felt) { + let (success) = ERC165.supports_interface(interface_id); + return (success,); +} + +@view +func getCalledFallback{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + bool: felt +) { + let (bool) = token677ReceiverMock_called_fallback_.read(); + return (bool,); +} + +@view +func getSentValue{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + value: Uint256 +) { + let (value) = token677ReceiverMock_sent_value_.read(); + return (value,); +} + +@view +func getTokenSender{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + address: felt +) { + let (address) = token677ReceiverMock_token_sender_.read(); + return (address,); +} diff --git a/contracts/src/plugin/cairo/token/IMintableToken.cairo b/contracts/src/plugin/cairo/token/IMintableToken.cairo new file mode 100644 index 0000000..a8bad6b --- /dev/null +++ b/contracts/src/plugin/cairo/token/IMintableToken.cairo @@ -0,0 +1,12 @@ +%lang starknet + +from starkware.cairo.common.uint256 import Uint256 + +@contract_interface +namespace IMintableToken { + func permissionedMint(account: felt, amount: Uint256) { + } + + func permissionedBurn(account: felt, amount: Uint256) { + } +} diff --git a/contracts/src/plugin/cairo/token/starkgate/presets/link_token.cairo b/contracts/src/plugin/cairo/token/starkgate/presets/link_token.cairo new file mode 100644 index 0000000..3d9f449 --- /dev/null +++ b/contracts/src/plugin/cairo/token/starkgate/presets/link_token.cairo @@ -0,0 +1,168 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.common.bool import TRUE + +from openzeppelin.token.erc20.library import ERC20 + +from starkware.starknet.std_contracts.ERC20.permitted import ( + permitted_initializer, + permitted_minter_only, +) + +from plugin.cairo.token.ERC677.library import ERC677 + +const NAME = 'Plugin Token'; +const SYMBOL = 'PLI'; +const DECIMALS = 18; + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(owner: felt) { + ERC20.initializer(NAME, SYMBOL, DECIMALS); + permitted_initializer(owner); + return (); +} + +// +// Getters +// + +@view +func type_and_version() -> (meta: felt) { + return ('LinkToken 0.0.1',); +} + +@view +func name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (name: felt) { + let (name) = ERC20.name(); + return (name,); +} + +@view +func symbol{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (symbol: felt) { + let (symbol) = ERC20.symbol(); + return (symbol,); +} + +@view +func totalSupply{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + totalSupply: Uint256 +) { + let (totalSupply: Uint256) = ERC20.total_supply(); + return (totalSupply,); +} + +@view +func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt +) { + let (decimals) = ERC20.decimals(); + return (decimals,); +} + +@view +func balanceOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(account: felt) -> ( + balance: Uint256 +) { + let (balance: Uint256) = ERC20.balance_of(account); + return (balance,); +} + +@view +func allowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + owner: felt, spender: felt +) -> (remaining: Uint256) { + let (remaining: Uint256) = ERC20.allowance(owner, spender); + return (remaining,); +} + +// +// Externals +// + +@external +func transfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + recipient: felt, amount: Uint256 +) -> (success: felt) { + ERC20.transfer(recipient, amount); + return (TRUE,); +} + +@external +func transferFrom{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + sender: felt, recipient: felt, amount: Uint256 +) -> (success: felt) { + ERC20.transfer_from(sender, recipient, amount); + return (TRUE,); +} + +@external +func approve{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + spender: felt, amount: Uint256 +) -> (success: felt) { + ERC20.approve(spender, amount); + return (TRUE,); +} + +@external +func increaseAllowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + spender: felt, added_value: Uint256 +) -> (success: felt) { + ERC20.increase_allowance(spender, added_value); + return (TRUE,); +} + +@external +func decreaseAllowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + spender: felt, subtracted_value: Uint256 +) -> (success: felt) { + ERC20.decrease_allowance(spender, subtracted_value); + return (TRUE,); +} + +// +// Externals - ERC677 +// + +@external +func transferAndCall{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + to: felt, value: Uint256, data_len: felt, data: felt* +) -> (success: felt) { + ERC677.transfer_and_call(to, value, data_len, data); + return (TRUE,); +} + +// +// Externals - StarkGate IMintableToken interface +// + +@external +func permissionedMint{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + account: felt, amount: Uint256 +) { + alloc_locals; + with_attr error_message("LinkToken: no permission") { + permitted_minter_only(); + } + local syscall_ptr: felt* = syscall_ptr; + + ERC20._mint(recipient=account, amount=amount); + + return (); +} + +@external +func permissionedBurn{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + account: felt, amount: Uint256 +) { + alloc_locals; + with_attr error_message("LinkToken: no permission") { + permitted_minter_only(); + } + local syscall_ptr: felt* = syscall_ptr; + + ERC20._burn(account=account, amount=amount); + + return (); +} diff --git a/contracts/src/plugin/cairo/utils.cairo b/contracts/src/plugin/cairo/utils.cairo new file mode 100644 index 0000000..cacd3d2 --- /dev/null +++ b/contracts/src/plugin/cairo/utils.cairo @@ -0,0 +1,18 @@ +from starkware.cairo.common.math import assert_in_range, assert_lt_felt +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.common.math import split_felt + +func assert_boolean{range_check_ptr}(value: felt) { + // Asserts that value is in the range [0, 2). + return assert_in_range(value, 0, 2); +} + +func felt_to_uint256{range_check_ptr}(x) -> (uint_x: Uint256) { + let (high, low) = split_felt(x); + return (Uint256(low=low, high=high),); +} + +func uint256_to_felt{range_check_ptr}(value: Uint256) -> (value: felt) { + assert_lt_felt(value.high, 2 ** 123); + return (value.high * (2 ** 128) + value.low,); +} diff --git a/contracts/src/plugin/solidity/emergency/StarknetValidator.sol b/contracts/src/plugin/solidity/emergency/StarknetValidator.sol new file mode 100644 index 0000000..bfe5592 --- /dev/null +++ b/contracts/src/plugin/solidity/emergency/StarknetValidator.sol @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@pluginv3.0/contracts/src/v0.8/interfaces/AggregatorValidatorInterface.sol"; +import "@pluginv3.0/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol"; +import "@pluginv3.0/contracts/src/v0.8/interfaces/AccessControllerInterface.sol"; +import "@pluginv3.0/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; +import "@pluginv3.0/contracts/src/v0.8/SimpleWriteAccessController.sol"; +import "@pluginv3.0/contracts/src/v0.8/dev/vendor/openzeppelin-solidity/v4.3.1/contracts/utils/Address.sol"; +import "../../../../vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessaging.sol"; + +/// @title StarknetValidator - makes cross chain calls to update the Sequencer Uptime Feed on L2 +contract StarknetValidator is TypeAndVersionInterface, AggregatorValidatorInterface, SimpleWriteAccessController { + // Config for L1 -> L2 message cost approximation + struct GasConfig { + uint256 gasEstimate; + address gasPriceL1Feed; + } + + int256 private constant ANSWER_SEQ_OFFLINE = 1; + + uint256 public immutable SELECTOR_STARK_UPDATE_STATUS = _selectorStarknet("update_status"); + uint256 public immutable L2_UPTIME_FEED_ADDR; + + IStarknetMessaging public immutable STARKNET_CROSS_DOMAIN_MESSENGER; + + AggregatorV3Interface private s_source; + AccessControllerInterface private s_configAC; + GasConfig private s_gasConfig; + + /// @notice Starknet messaging contract address - the address is 0. + error InvalidStarknetMessagingAddress(); + /// @notice Starknet uptime feed address - the address is 0. + error InvalidL2FeedAddress(); + /// @notice Error thrown when the source aggregator address is 0 + error InvalidSourceAggregatorAddress(); + /// @notice Error thrown when the l1 gas price feed address is 0 + error InvalidGasPriceL1FeedAddress(); + /// @notice Error thrown when caller is not the owner and does not have access + error AccessForbidden(); + + /// @notice This event is emitted when the gas config is set. + event GasConfigSet(uint256 gasEstimate, address indexed gasPriceL1Feed); + /// @notice emitted when a new gas access-control contract is set + event ConfigACSet(address indexed previous, address indexed current); + /// @notice emitted when a new source aggregator contract is set + event SourceAggregatorSet(address indexed previous, address indexed current); + /// @notice emitted when withdrawFunds or withdrawFundsTo is call + event FundsWithdrawn(address indexed recipient, uint256 amount); + + /** + * @param starknetMessaging the address of the Starknet Messaging contract + * @param configAC the address of the AccessController contract managing config access + * @param gasPriceL1Feed address of the L1 gas price feed (used to approximate bridge L1 -> L2 message cost) + * @param source the source aggregator that we'll read data from (on retries) + * @param l2Feed the address of the target L2 contract (Sequencer Uptime Feed) + * @param gasEstimate the initial gas estimate for sending a message from L1 -> L2 + */ + constructor( + address starknetMessaging, + address configAC, + address gasPriceL1Feed, + address source, + uint256 l2Feed, + uint256 gasEstimate + ) { + if (starknetMessaging == address(0)) { + revert InvalidStarknetMessagingAddress(); + } + + if (l2Feed == 0) { + revert InvalidL2FeedAddress(); + } + + STARKNET_CROSS_DOMAIN_MESSENGER = IStarknetMessaging(starknetMessaging); + L2_UPTIME_FEED_ADDR = l2Feed; + + _setSourceAggregator(source); + _setConfigAC(configAC); + _setGasConfig(gasEstimate, gasPriceL1Feed); + } + + /// @notice converts a bool to uint256. + function toUInt256(bool x) internal pure returns (uint256 r) { + assembly { + r := x + } + } + + /** + * @notice versions: + * + * - StarknetValidator 0.1.0: initial release + * @inheritdoc TypeAndVersionInterface + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "StarknetValidator 0.1.0"; + } + + /// @notice Returns the gas configuration for sending cross chain messages. + function getGasConfig() external view returns (GasConfig memory) { + return s_gasConfig; + } + + /// @return address AccessControllerInterface contract address + function getConfigAC() external view returns (address) { + return address(s_configAC); + } + + /// @return address Aggregator contract address + function getSourceAggregator() external view returns (address) { + return address(s_source); + } + + /** + * @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. + * @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. + * @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. + * @return bool true if transaction succeeds. + */ + function validate( + uint256 /* previousRoundId */, + int256 /* previousAnswer */, + uint256 /* currentRoundId */, + int256 currentAnswer + ) external override checkAccess returns (bool) { + return _sendUpdateMessageToL2(currentAnswer); + } + + /** + * @notice retries to send the latest answer as update message to L2 + * @dev only with access, useful in cases where a previous x-domain message was handeled unsuccessfully. + */ + function retry() external checkAccess returns (bool) { + (, int256 latestAnswer, , , ) = AggregatorV3Interface(s_source).latestRoundData(); + return _sendUpdateMessageToL2(latestAnswer); + } + + /** + * @notice sends the 'update_status(answer, timestamp)' message + * via the L1 -> L2 bridge to the L2 feed contract + * @param answer The latest Sequencer status. 0 if the Sequencer is up and + * 1 if it is down. + */ + function _sendUpdateMessageToL2(int256 answer) internal returns (bool) { + // Bridge fees are paid on L1 + uint256 fee = _approximateFee(); + + // Fill payload with `status` and `timestamp` + uint256[] memory payload = new uint256[](2); + bool status = answer == ANSWER_SEQ_OFFLINE; + payload[0] = toUInt256(status); + payload[1] = block.timestamp; + + // Make the Starknet x-domain call. + // NOTICE: we ignore the output of this call (msgHash, nonce). + // We also don't raise any events as the 'LogMessageToL2' event will be emitted from the messaging contract. + STARKNET_CROSS_DOMAIN_MESSENGER.sendMessageToL2{value: fee}( + L2_UPTIME_FEED_ADDR, + SELECTOR_STARK_UPDATE_STATUS, + payload + ); + return true; + } + + /// @notice L1 oracle is asked for a fast L1 gas price, and the price multiplied by the configured gas estimate + function _approximateFee() internal view returns (uint256) { + (, int256 fastGasPriceInWei, , , ) = AggregatorV3Interface(s_gasConfig.gasPriceL1Feed).latestRoundData(); + return uint256(fastGasPriceInWei) * s_gasConfig.gasEstimate; + } + + /** + * @notice The selector is the starknet_keccak hash of the function name + * @dev Starknet keccak is defined as the first 250 bits of the Keccak256 hash. + * This is just Keccak256 augmented in order to fit into a field element. + * @param fn string function name + */ + function _selectorStarknet(string memory fn) internal pure returns (uint256) { + bytes32 digest = keccak256(abi.encodePacked(fn)); + return uint256(digest) % 2 ** 250; // get last 250 bits + } + + /** + * @notice Sets the gas configuration for sending cross chain messages + * @param gasEstimate The estimated units of gas to execute the transaction on L2. + * This value should include any buffer to include. + * @param gasPriceL1Feed The address of the fast gas L1 feed on L1. + */ + function setGasConfig(uint256 gasEstimate, address gasPriceL1Feed) external onlyOwnerOrConfigAccess { + _setGasConfig(gasEstimate, gasPriceL1Feed); + } + + /** + * @notice Sets the gas configuration for sending cross chain messages + * @param gasEstimate The estimated units of gas to execute the transaction on L2. + * This value should include any buffer to include. + * @param gasPriceL1Feed The address of the fast gas L1 feed on L1. + */ + function _setGasConfig(uint256 gasEstimate, address gasPriceL1Feed) internal { + if (gasPriceL1Feed == address(0)) { + revert InvalidGasPriceL1FeedAddress(); + } + s_gasConfig = GasConfig(gasEstimate, gasPriceL1Feed); + emit GasConfigSet(gasEstimate, gasPriceL1Feed); + } + + /** + * @notice sets config AccessControllerInterface contract + * @dev only owner can call this + * @param accessController new AccessControllerInterface contract address + */ + function setConfigAC(address accessController) external onlyOwner { + _setConfigAC(accessController); + } + + /** + * @notice Internal method that stores the configuration access controller + * @param accessController The address of the Access Controller for this contract + */ + function _setConfigAC(address accessController) internal { + address previousAccessController = address(s_configAC); + if (accessController != previousAccessController) { + // NOTICE: we don't give access to the new source aggregator + // It is not always the case that the source aggregator is also the sender for the 'validate' invocation + // as we usually deploy an additional proxy in between (owner can give access): + // https://github.com/goplugin/pluginv3.0/blob/develop/contracts/src/v0.8/ValidatorProxy.sol + s_configAC = AccessControllerInterface(accessController); + emit ConfigACSet(previousAccessController, accessController); + } + } + + /** + * @notice sets the source aggregator AggregatorInterface contract + * @dev only owner can call this + * @param source the source aggregator that we'll read data from (on retries) + */ + function setSourceAggregator(address source) external onlyOwner { + _setSourceAggregator(source); + } + + /// @notice Internal method that sets the source aggregator AggregatorInterface contract + function _setSourceAggregator(address source) internal { + if (source == address(0)) { + revert InvalidSourceAggregatorAddress(); + } + address previousSource = address(s_source); + if (source != previousSource) { + s_source = AggregatorV3Interface(source); + emit SourceAggregatorSet(previousSource, source); + } + } + + /// @dev reverts if the caller does not have access to change the configuration + modifier onlyOwnerOrConfigAccess() { + if (msg.sender != owner() && (address(s_configAC) != address(0) && !s_configAC.hasAccess(msg.sender, msg.data))) { + revert AccessForbidden(); + } + _; + } + + /** + * @notice makes this contract payable + * @dev funds are used to pay the bridge for x-domain messages to L2 + */ + receive() external payable {} + + /** + * @notice withdraws all funds available in this contract to the msg.sender + * @dev only owner can call this + */ + function withdrawFunds() external onlyOwner { + address payable recipient = payable(msg.sender); + uint256 amount = address(this).balance; + Address.sendValue(recipient, amount); + emit FundsWithdrawn(recipient, amount); + } + + /** + * @notice withdraws all funds available in this contract to the address specified + * @dev only owner can call this + * @param recipient address where to send the funds + */ + function withdrawFundsTo(address payable recipient) external onlyOwner { + uint256 amount = address(this).balance; + Address.sendValue(recipient, amount); + emit FundsWithdrawn(recipient, amount); + } +} diff --git a/contracts/src/plugin/solidity/mocks/MockStarknetMessaging.sol b/contracts/src/plugin/solidity/mocks/MockStarknetMessaging.sol new file mode 100644 index 0000000..319cf13 --- /dev/null +++ b/contracts/src/plugin/solidity/mocks/MockStarknetMessaging.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import '../../../../vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/StarknetMessaging.sol'; + +/** + * @title MockStarknetMessaging make cross chain call. + For Devnet L1 <> L2 communication testing, we have to replace IStarknetCore with the MockStarknetMessaging.sol contract + */ +contract MockStarknetMessaging is StarknetMessaging { + constructor(uint256 MessageCancellationDelay) public { + messageCancellationDelay(MessageCancellationDelay); + } + + /** + Mocks a message from L2 to L1. + */ + function mockSendMessageFromL2( + uint256 fromAddress, + uint256 toAddress, + uint256[] calldata payload + ) external { + bytes32 msgHash = keccak256( + abi.encodePacked(fromAddress, toAddress, payload.length, payload) + ); + l2ToL1Messages()[msgHash] += 1; + } + + /** + Mocks consumption of a message from L1 to L2. + */ + function mockConsumeMessageToL2( + uint256 fromAddress, + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) external { + bytes32 msgHash = keccak256( + abi.encodePacked(fromAddress, toAddress, nonce, selector, payload.length, payload) + ); + + require(l1ToL2Messages()[msgHash] > 0, "INVALID_MESSAGE_TO_CONSUME"); + l1ToL2Messages()[msgHash] = 0; + } +} diff --git a/contracts/test/access/behavior/ownable.ts b/contracts/test/access/behavior/ownable.ts new file mode 100644 index 0000000..0c7d16c --- /dev/null +++ b/contracts/test/access/behavior/ownable.ts @@ -0,0 +1,114 @@ +import { expect } from 'chai' +import { starknet } from 'hardhat' +import { StarknetContract, Account } from 'hardhat/types/runtime' + +export type BeforeFn = () => Promise +export type TestData = { + ownable: StarknetContract + alice: Account + bob: Account +} + +// NOTICE: Leading zeros are trimmed for an encoded felt (number). +// To decode, the raw felt needs to be start padded up to max felt size (252 bits or < 32 bytes). +const hexPadStart = (data: number | bigint, len: number) => { + return `0x${data.toString(16).padStart(len, '0')}` +} + +const ADDRESS_LEN = 32 * 2 // 32 bytes (hex) + +const addresses = (t: TestData) => ({ + bob: t.bob.starknetContract.address, + alice: t.alice.starknetContract.address, +}) + +const expectOwner = async (c: StarknetContract, expected: string) => { + const { owner: raw } = await c.call('owner') + + const owner = hexPadStart(raw, ADDRESS_LEN) + expect(owner).to.deep.equal(expected) +} + +const expectProposedOwner = async (c: StarknetContract, expected: string) => { + const { proposed_owner: raw } = await c.call('proposed_owner') + + const proposedOwner = hexPadStart(raw, ADDRESS_LEN) + expect(proposedOwner).to.deep.equal(expected) +} + +// idempotent - end with original owner +export const shouldBehaveLikeOwnableContract = (beforeFn: BeforeFn) => { + describe('ownable behavior', function () { + let t: TestData + + before(async () => { + t = await beforeFn() + }) + + // TODO: test 'owner', 'proposed_owner', 'transfer_ownership', 'accept_ownership' in depth + + it(`should have 'owner' set`, async () => { + const { alice } = addresses(t) + + // initial owner is alice + await expectOwner(t.ownable, alice) + }) + + it(`should be able to 'transfer_ownership'`, async () => { + const { alice, bob } = addresses(t) + + await t.alice.invoke(t.ownable, 'transfer_ownership', { + new_owner: bob, + }) + + // owner is still alice + await expectOwner(t.ownable, alice) + await expectProposedOwner(t.ownable, bob) + }) + + it(`should be able to 'accept_ownership'`, async () => { + const { bob } = addresses(t) + + await t.bob.invoke(t.ownable, 'accept_ownership') + + // owner is now bob + await expectOwner(t.ownable, bob) + await expectProposedOwner(t.ownable, hexPadStart(0, ADDRESS_LEN)) // 0x0 + }) + + it(`should be able to 'transfer_ownership' back`, async () => { + const { alice, bob } = addresses(t) + + await t.bob.invoke(t.ownable, 'transfer_ownership', { + new_owner: alice, + }) + + // owner is still bob + await expectOwner(t.ownable, bob) + await expectProposedOwner(t.ownable, alice) + }) + + it(`should be able to 'accept_ownership' again`, async () => { + const { alice } = addresses(t) + + await t.alice.invoke(t.ownable, 'accept_ownership') + + // owner is now alice + await expectOwner(t.ownable, alice) + await expectProposedOwner(t.ownable, hexPadStart(0, ADDRESS_LEN)) // 0x0 + }) + + it(`should fail with account without fees`, async () => { + const accountNoFees = await starknet.OpenZeppelinAccount.createAccount() + + await t.alice.invoke(t.ownable, 'transfer_ownership', { + new_owner: accountNoFees.address, + }) + + try { + await accountNoFees.invoke(t.ownable, 'accept_ownership', { maxFee: 1e18 }) + expect.fail() + } catch (err: any) {} + }) + }) +} diff --git a/contracts/test/constants.ts b/contracts/test/constants.ts new file mode 100644 index 0000000..ea0bd93 --- /dev/null +++ b/contracts/test/constants.ts @@ -0,0 +1,2 @@ +/** 15 min */ +export const TIMEOUT = 900_000 diff --git a/contracts/test/emergency/StarknetValidator.test.ts b/contracts/test/emergency/StarknetValidator.test.ts new file mode 100644 index 0000000..c33ce9f --- /dev/null +++ b/contracts/test/emergency/StarknetValidator.test.ts @@ -0,0 +1,641 @@ +import { ethers, starknet, network } from 'hardhat' +import { Contract, ContractFactory } from 'ethers' +import { hash } from 'starknet' +import { + Account, + StarknetContractFactory, + StarknetContract, + HttpNetworkConfig, +} from 'hardhat/types' +import { expect } from 'chai' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { abi as aggregatorAbi } from '../../artifacts/@pluginv3.0/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol/AggregatorV3Interface.json' +import { abi as accessControllerAbi } from '../../artifacts/@pluginv3.0/contracts/src/v0.8/interfaces/AccessControllerInterface.sol/AccessControllerInterface.json' +import { abi as starknetMessagingAbi } from '../../artifacts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessaging.sol/IStarknetMessaging.json' +import { deployMockContract, MockContract } from '@ethereum-waffle/mock-contract' +import { account, addCompilationToNetwork } from '@pluginv3.0/starknet' + +describe('StarknetValidator', () => { + /** Fake L2 target */ + const networkUrl: string = (network.config as HttpNetworkConfig).url + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + let defaultAccount: Account + let deployer: SignerWithAddress + let eoaValidator: SignerWithAddress + let alice: SignerWithAddress + + let starknetValidatorFactory: ContractFactory + let starknetValidator: Contract + let mockStarknetMessagingFactory: ContractFactory + let mockStarknetMessaging: Contract + let mockGasPriceFeed: MockContract + let mockAccessController: MockContract + let mockAggregator: MockContract + + let l2ContractFactory: StarknetContractFactory + let l2Contract: StarknetContract + + before(async () => { + await addCompilationToNetwork( + 'src/plugin/solidity/emergency/StarknetValidator.sol:StarknetValidator', + ) + + // Deploy L2 account + defaultAccount = await starknet.OpenZeppelinAccount.createAccount() + + // Fund L2 account + await funder.fund([{ account: defaultAccount.address, amount: 1e21 }]) + await defaultAccount.deployAccount() + + // Fetch predefined L1 EOA accounts + const accounts = await ethers.getSigners() + deployer = accounts[0] + eoaValidator = accounts[1] + alice = accounts[2] + + // Deploy L2 feed contract + l2ContractFactory = await starknet.getContractFactory('sequencer_uptime_feed') + await defaultAccount.declare(l2ContractFactory) + + l2Contract = await defaultAccount.deploy(l2ContractFactory, { + initial_status: 0, + owner_address: defaultAccount.starknetContract.address, + }) + + // Deploy the MockStarknetMessaging contract used to simulate L1 - L2 comms + mockStarknetMessagingFactory = await ethers.getContractFactory( + 'MockStarknetMessaging', + deployer, + ) + const messageCancellationDelay = 5 * 60 // seconds + mockStarknetMessaging = await mockStarknetMessagingFactory.deploy(messageCancellationDelay) + await mockStarknetMessaging.deployed() + + // Deploy the mock feed + mockGasPriceFeed = await deployMockContract(deployer, aggregatorAbi) + await mockGasPriceFeed.mock.latestRoundData.returns( + '73786976294838220258' /** roundId */, + '96800000000' /** answer */, + '163826896' /** startedAt */, + '1638268960' /** updatedAt */, + '73786976294838220258' /** answeredInRound */, + ) + + // Deploy the mock access controller + mockAccessController = await deployMockContract(deployer, accessControllerAbi) + + // Deploy the mock aggregator + mockAggregator = await deployMockContract(deployer, aggregatorAbi) + await mockAggregator.mock.latestRoundData.returns( + '73786976294838220258' /** roundId */, + 1 /** answer */, + '163826896' /** startedAt */, + '1638268960' /** updatedAt */, + '73786976294838220258' /** answeredInRound */, + ) + }) + + beforeEach(async () => { + // Deploy the L1 StarknetValidator + starknetValidatorFactory = await ethers.getContractFactory('StarknetValidator', deployer) + starknetValidator = await starknetValidatorFactory.deploy( + mockStarknetMessaging.address, + mockAccessController.address, + mockGasPriceFeed.address, + mockAggregator.address, + l2Contract.address, + 0, + ) + + // Point the L2 feed contract to receive from the L1 StarknetValidator contract + await defaultAccount.invoke(l2Contract, 'set_l1_sender', { address: starknetValidator.address }) + }) + + describe('#constructor', () => { + it('reverts when the StarknetMessaging address is zero', async () => { + await expect( + starknetValidatorFactory.deploy( + ethers.constants.AddressZero, + mockAccessController.address, + mockGasPriceFeed.address, + mockAggregator.address, + l2Contract.address, + 0, + ), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidStarknetMessagingAddress') + }) + + it('reverts when the L2 feed is zero', async () => { + await expect( + starknetValidatorFactory.deploy( + mockStarknetMessaging.address, + mockAccessController.address, + mockGasPriceFeed.address, + mockAggregator.address, + 0, + 0, + ), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidL2FeedAddress') + }) + + it('reverts when the Aggregator address is zero', async () => { + await expect( + starknetValidatorFactory.deploy( + mockStarknetMessaging.address, + mockAccessController.address, + mockGasPriceFeed.address, + ethers.constants.AddressZero, + l2Contract.address, + 0, + ), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidSourceAggregatorAddress') + }) + + it('reverts when the L1 Gas Price feed address is zero', async () => { + await expect( + starknetValidatorFactory.deploy( + mockStarknetMessaging.address, + mockAccessController.address, + ethers.constants.AddressZero, + mockAggregator.address, + l2Contract.address, + 0, + ), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidGasPriceL1FeedAddress') + }) + + it('is initialized with the correct gas config', async () => { + const gasConfig = await starknetValidator.getGasConfig() + expect(gasConfig.gasEstimate).to.equal(0) // Initialized with 0 in before function + expect(gasConfig.gasPriceL1Feed).to.hexEqual(mockGasPriceFeed.address) + }) + + it('is initialized with the correct access controller address', async () => { + const acAddr = await starknetValidator.getConfigAC() + expect(acAddr).to.hexEqual(mockAccessController.address) + }) + + it('is initialized with the correct source aggregator address', async () => { + const aggregatorAddr = await starknetValidator.getSourceAggregator() + expect(aggregatorAddr).to.hexEqual(mockAggregator.address) + }) + + it('should get the selector from the name successfully', async () => { + const actual = hash.getSelectorFromName('update_status') + const expected = 1585322027166395525705364165097050997465692350398750944680096081848180365267n + expect(BigInt(actual)).to.equal(expected) + + const computedActual = await starknetValidator.SELECTOR_STARK_UPDATE_STATUS() + expect(computedActual).to.equal(expected) + }) + }) + + describe('#retry', () => { + describe('when called by account with no access', () => { + it('reverts', async () => { + await expect(starknetValidator.connect(alice).retry()).to.be.revertedWith('No access') + }) + }) + + describe('when called by account with access', () => { + it('transaction succeeds', async () => { + const waffleMockStarknetMessaging = await deployMockContract(deployer, starknetMessagingAbi) + await waffleMockStarknetMessaging.mock.sendMessageToL2.returns( + ethers.utils.formatBytes32String('0'), + 0, + ) + await mockAggregator.mock.latestRoundData.returns( + '0' /** roundId */, + 1 /** answer */, + '0' /** startedAt */, + '0' /** updatedAt */, + '0' /** answeredInRound */, + ) + await mockGasPriceFeed.mock.latestRoundData.returns( + '0' /** roundId */, + 1 /** answer */, + '0' /** startedAt */, + '0' /** updatedAt */, + '0' /** answeredInRound */, + ) + + const starknetValidator = await starknetValidatorFactory.deploy( + waffleMockStarknetMessaging.address, + mockAccessController.address, + mockGasPriceFeed.address, + mockAggregator.address, + l2Contract.address, + 0, + ) + + await starknetValidator.addAccess(deployer.address) + + await starknetValidator.retry() + }) + }) + }) + + describe('#setConfigAC', () => { + describe('when called by non owner', () => { + it('reverts', async () => { + await expect( + starknetValidator.connect(alice).setConfigAC(ethers.constants.AddressZero), + ).to.be.revertedWith('Only callable by owner') + }) + }) + + describe('when called by owner', () => { + it('emits an event', async () => { + const newACAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await expect(starknetValidator.setConfigAC(newACAddr)) + .to.emit(starknetValidator, 'ConfigACSet') + .withArgs(mockAccessController.address, newACAddr) + }) + + it('sets the access controller address', async () => { + const newACAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await starknetValidator.connect(deployer).setConfigAC(newACAddr) + expect(await starknetValidator.getConfigAC()).to.equal(newACAddr) + }) + + it('no-op if new address equals previous address', async () => { + const tx = await starknetValidator.setConfigAC(mockAccessController.address) + const receipt = await tx.wait() + expect(receipt.events).is.empty + expect(await starknetValidator.getConfigAC()).to.equal(mockAccessController.address) + }) + }) + }) + + describe('#setSourceAggregator', () => { + describe('when called by non owner', () => { + it('reverts', async () => { + await expect( + starknetValidator.connect(alice).setSourceAggregator(ethers.constants.AddressZero), + ).to.be.revertedWith('Only callable by owner') + }) + }) + + describe('when source address is the zero address', () => { + it('reverts', async () => { + await expect( + starknetValidator.connect(deployer).setSourceAggregator(ethers.constants.AddressZero), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidSourceAggregatorAddress') + }) + }) + + describe('when called by owner', () => { + it('emits an event', async () => { + const newSourceAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await expect(starknetValidator.setSourceAggregator(newSourceAddr)) + .to.emit(starknetValidator, 'SourceAggregatorSet') + .withArgs(mockAggregator.address, newSourceAddr) + }) + + it('sets the source aggregator address', async () => { + expect(await starknetValidator.getSourceAggregator()).to.hexEqual(mockAggregator.address) + }) + + it('does nothing if new address equal to previous', async () => { + const tx = await starknetValidator + .connect(deployer) + .setSourceAggregator(mockAggregator.address) + const receipt = await tx.wait() + expect(receipt.events).to.be.empty + + expect(await starknetValidator.getSourceAggregator()).to.hexEqual(mockAggregator.address) + }) + }) + }) + + describe('#setGasConfig', () => { + describe('when called by non owner without access', () => { + beforeEach(async () => { + await mockAccessController.mock.hasAccess.returns(false) + }) + + it('reverts', async () => { + await expect( + starknetValidator.connect(alice).setGasConfig(0, mockGasPriceFeed.address), + ).to.be.revertedWithCustomError(starknetValidator, 'AccessForbidden') + }) + }) + + describe('when called by owner', () => { + it('correctly sets the gas config', async () => { + const newGasEstimate = 25000 + const newFeedAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await starknetValidator.connect(deployer).setGasConfig(newGasEstimate, newFeedAddr) + const gasConfig = await starknetValidator.getGasConfig() + expect(gasConfig.gasEstimate).to.equal(newGasEstimate) + expect(gasConfig.gasPriceL1Feed).to.hexEqual(newFeedAddr) + }) + + it('emits an event', async () => { + const newGasEstimate = 25000 + const newFeedAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await expect(starknetValidator.connect(deployer).setGasConfig(newGasEstimate, newFeedAddr)) + .to.emit(starknetValidator, 'GasConfigSet') + .withArgs(newGasEstimate, newFeedAddr) + }) + + describe('when l1 gas price feed address is the zero address', () => { + it('reverts', async () => { + await expect( + starknetValidator.connect(deployer).setGasConfig(25000, ethers.constants.AddressZero), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidGasPriceL1FeedAddress') + }) + }) + }) + + describe('when access controller address is set', () => { + describe('when called by an address with access', () => { + beforeEach(async () => { + await mockAccessController.mock.hasAccess.returns(true) + }) + + it('correctly sets the gas config', async () => { + const newGasEstimate = 25000 + const newFeedAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await starknetValidator.connect(eoaValidator).setGasConfig(newGasEstimate, newFeedAddr) + const gasConfig = await starknetValidator.getGasConfig() + expect(gasConfig.gasEstimate).to.equal(newGasEstimate) + expect(gasConfig.gasPriceL1Feed).to.hexEqual(newFeedAddr) + }) + + it('emits an event', async () => { + const newGasEstimate = 25000 + const newFeedAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await expect( + starknetValidator.connect(eoaValidator).setGasConfig(newGasEstimate, newFeedAddr), + ) + .to.emit(starknetValidator, 'GasConfigSet') + .withArgs(newGasEstimate, newFeedAddr) + }) + + describe('when l1 gas price feed address is the zero address', () => { + it('reverts', async () => { + await expect( + starknetValidator + .connect(eoaValidator) + .setGasConfig(25000, ethers.constants.AddressZero), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidGasPriceL1FeedAddress') + }) + }) + }) + }) + + describe('when access controller address is not set', () => { + beforeEach(async () => { + await starknetValidator.connect(deployer).setConfigAC(ethers.constants.AddressZero) + }) + + describe('when called by an address without access', () => { + beforeEach(async () => { + await mockAccessController.mock.hasAccess.returns(false) + }) + + it('correctly sets the gas config', async () => { + const newGasEstimate = 25000 + const newFeedAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await starknetValidator.connect(eoaValidator).setGasConfig(newGasEstimate, newFeedAddr) + const gasConfig = await starknetValidator.getGasConfig() + expect(gasConfig.gasEstimate).to.equal(newGasEstimate) + expect(gasConfig.gasPriceL1Feed).to.hexEqual(newFeedAddr) + }) + + it('emits an event', async () => { + const newGasEstimate = 25000 + const newFeedAddr = '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4' + await expect( + starknetValidator.connect(eoaValidator).setGasConfig(newGasEstimate, newFeedAddr), + ) + .to.emit(starknetValidator, 'GasConfigSet') + .withArgs(newGasEstimate, newFeedAddr) + }) + + describe('when l1 gas price feed address is the zero address', () => { + it('reverts', async () => { + await expect( + starknetValidator + .connect(eoaValidator) + .setGasConfig(25000, ethers.constants.AddressZero), + ).to.be.revertedWithCustomError(starknetValidator, 'InvalidGasPriceL1FeedAddress') + }) + }) + }) + }) + }) + + describe('#validate', () => { + beforeEach(async () => { + await expect( + deployer.sendTransaction({ to: starknetValidator.address, value: 100n }) + ).to.changeEtherBalance(starknetValidator, 100n) + }) + + it('reverts if `StarknetValidator.validate` called by account with no access', async () => { + const c = starknetValidator.connect(eoaValidator) + await expect(c.validate(0, 0, 1, 1)).to.be.revertedWith('No access') + }) + + it('should not revert if `sequencer_uptime_feed.latest_round_data` called by an Account with no explicit access (Accounts are allowed read access)', async () => { + const { round } = await l2Contract.call('latest_round_data') + expect(round.answer).to.equal(0n) + }) + + it('should deploy the messaging contract', async () => { + const { address, l1_provider } = await starknet.devnet.loadL1MessagingContract(networkUrl) + expect(address).not.to.be.undefined + expect(l1_provider).to.equal(networkUrl) + }) + + it('should load the already deployed contract if the address is provided', async () => { + const { address: loadedFrom } = await starknet.devnet.loadL1MessagingContract( + networkUrl, + mockStarknetMessaging.address, + ) + + expect(mockStarknetMessaging.address).to.hexEqual(loadedFrom) + }) + + it('should send a message to the L2 contract', async () => { + // Load the mock messaging contract + await starknet.devnet.loadL1MessagingContract(networkUrl, mockStarknetMessaging.address) + + // Return gas price of 1 + await mockGasPriceFeed.mock.latestRoundData.returns( + '0' /** roundId */, + 1 /** answer */, + '0' /** startedAt */, + '0' /** updatedAt */, + '0' /** answeredInRound */, + ) + + + + // Simulate L1 transmit + validate + await starknetValidator.addAccess(eoaValidator.address) + // by default the gas config is 0, we need to change it or we will submit a 0 fee + const newGasEstimate = 1 + await starknetValidator + .connect(deployer) + .setGasConfig(newGasEstimate, mockGasPriceFeed.address) + await starknetValidator.connect(eoaValidator).validate(0, 0, 1, 1) // gasPrice (1) * newGasEstimate (1) + + // Simulate the L1 - L2 comms + const resp = await starknet.devnet.flush() + const msgFromL1 = resp.consumed_messages.from_l1 + expect(msgFromL1).to.have.a.lengthOf(1) + expect(resp.consumed_messages.from_l2).to.be.empty + + expect(msgFromL1[0].args.from_address).to.hexEqual(starknetValidator.address) + expect(msgFromL1[0].args.to_address).to.hexEqual(l2Contract.address) + expect(msgFromL1[0].address).to.hexEqual(mockStarknetMessaging.address) + + // Assert L2 effects + const res = await l2Contract.call('latest_round_data') + expect(res.round.answer).to.equal(1n) + }) + + it('should always send a **boolean** message to L2 contract', async () => { + // Load the mock messaging contract + await starknet.devnet.loadL1MessagingContract(networkUrl, mockStarknetMessaging.address) + + // Return gas price of 1 + await mockGasPriceFeed.mock.latestRoundData.returns( + '0' /** roundId */, + 1 /** answer */, + '0' /** startedAt */, + '0' /** updatedAt */, + '0' /** answeredInRound */, + ) + + // Simulate L1 transmit + validate + await starknetValidator.addAccess(eoaValidator.address) + // by default the gas config is 0, we need to change it or we will submit a 0 fee + const newGasEstimate = 1 + await starknetValidator + .connect(deployer) + .setGasConfig(newGasEstimate, mockGasPriceFeed.address) + await starknetValidator.connect(eoaValidator).validate(0, 0, 1, 127) // incorrect value + + // Simulate the L1 - L2 comms + const resp = await starknet.devnet.flush() + const msgFromL1 = resp.consumed_messages.from_l1 + expect(msgFromL1).to.have.a.lengthOf(1) + expect(resp.consumed_messages.from_l2).to.be.empty + + expect(msgFromL1[0].args.from_address).to.hexEqual(starknetValidator.address) + expect(msgFromL1[0].args.to_address).to.hexEqual(l2Contract.address) + expect(msgFromL1[0].address).to.hexEqual(mockStarknetMessaging.address) + + // Assert L2 effects + const res = await l2Contract.call('latest_round_data') + expect(res.round.answer).to.equal(0n) // status unchanged - incorrect value treated as false + }) + + it('should send multiple messages', async () => { + // Load the mock messaging contract + await starknet.devnet.loadL1MessagingContract(networkUrl, mockStarknetMessaging.address) + + // Return gas price of 1 + await mockGasPriceFeed.mock.latestRoundData.returns( + '0' /** roundId */, + 1 /** answer */, + '0' /** startedAt */, + '0' /** updatedAt */, + '0' /** answeredInRound */, + ) + + // Simulate L1 transmit + validate + await starknetValidator.addAccess(eoaValidator.address) + const c = starknetValidator.connect(eoaValidator) + // by default the gas config is 0, we need to change it or we will submit a 0 fee + const newGasEstimate = 1 + await starknetValidator + .connect(deployer) + .setGasConfig(newGasEstimate, mockGasPriceFeed.address) + await c.validate(0, 0, 1, 1) + await c.validate(0, 0, 1, 1) + await c.validate(0, 0, 1, 127) // incorrect value + await c.validate(0, 0, 1, 0) // final status + + // Simulate the L1 - L2 comms + const resp = await starknet.devnet.flush() + const msgFromL1 = resp.consumed_messages.from_l1 + expect(msgFromL1).to.have.a.lengthOf(4) + expect(resp.consumed_messages.from_l2).to.be.empty + + expect(msgFromL1[0].args.from_address).to.hexEqual(starknetValidator.address) + expect(msgFromL1[0].args.to_address).to.hexEqual(l2Contract.address) + expect(msgFromL1[0].address).to.hexEqual(mockStarknetMessaging.address) + + // Assert L2 effects + const res = await l2Contract.call('latest_round_data') + expect(res.round.answer).to.equal(0n) // final status 0 + }) + }) + + describe('#withdrawFunds', () => { + beforeEach(async () => { + await expect(() => + deployer.sendTransaction({ to: starknetValidator.address, value: 10 }) + ).to.changeEtherBalance(starknetValidator, 10n) + }) + + describe('when called by non owner', () => { + it('reverts', async () => { + await expect(starknetValidator.connect(alice).withdrawFunds()).to.be.revertedWith( + 'Only callable by owner', + ) + }) + }) + + describe('when called by owner', () => { + it('emits an event', async () => { + await expect(starknetValidator.connect(deployer).withdrawFunds()) + .to.emit(starknetValidator, 'FundsWithdrawn') + .withArgs(deployer.address, 10) + }) + + it('withdraws all funds to deployer', async () => { + await starknetValidator.connect(deployer).withdrawFunds() + const balance = await ethers.provider.getBalance(starknetValidator.address) + expect(balance).to.equal(0n) + }) + }) + }) + + describe('#withdrawFundsTo', () => { + beforeEach(async () => { + await expect(() => + deployer.sendTransaction({ to: starknetValidator.address, value: 10 }) + ).to.changeEtherBalance(starknetValidator, 10) + }) + + describe('when called by non owner', () => { + it('reverts', async () => { + await expect( + starknetValidator.connect(alice).withdrawFundsTo(alice.address), + ).to.be.revertedWith('Only callable by owner') + }) + }) + + describe('when called by owner', () => { + it('emits an event', async () => { + await expect(starknetValidator.connect(deployer).withdrawFundsTo(eoaValidator.address)) + .to.emit(starknetValidator, 'FundsWithdrawn') + .withArgs(eoaValidator.address, 10) + }) + + it('withdraws all funds to deployer', async () => { + await starknetValidator.connect(deployer).withdrawFunds() + const balance = await ethers.provider.getBalance(starknetValidator.address) + expect(balance).to.equal(0n) + }) + }) + }) +}) diff --git a/contracts/test/emergency/sequencer_uptime_feed.test.ts b/contracts/test/emergency/sequencer_uptime_feed.test.ts new file mode 100644 index 0000000..60ab169 --- /dev/null +++ b/contracts/test/emergency/sequencer_uptime_feed.test.ts @@ -0,0 +1,171 @@ +import { expect } from 'chai' +import { starknet } from 'hardhat' +import { StarknetContract, Account } from 'hardhat/types/runtime' +import { num } from 'starknet' +import { shouldBehaveLikeOwnableContract } from '../access/behavior/ownable' +import { account, expectInvokeError } from '@pluginv3.0/starknet' + +describe('SequencerUptimeFeed', function () { + this.timeout(300_000) + + let owner: Account + let nonOwner: Account + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + // should be beforeeach, but that'd be horribly slow. Just remember that the tests are not idempotent + before(async function () { + owner = await starknet.OpenZeppelinAccount.createAccount() + nonOwner = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([ + { account: owner.address, amount: 1e21 }, + { account: nonOwner.address, amount: 1e21 }, + ]) + await owner.deployAccount() + await nonOwner.deployAccount() + }) + + shouldBehaveLikeOwnableContract(async () => { + const alice = owner + const bob = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: bob.address, amount: 1e21 }]) + + await bob.deployAccount() + + const feedFactory = await starknet.getContractFactory('sequencer_uptime_feed') + await alice.declare(feedFactory) + + const feed = await alice.deploy(feedFactory, { + initial_status: 0, + owner_address: num.toBigInt(alice.starknetContract.address), + }) + + return { ownable: feed, alice, bob } + }) + + describe('Test access control via inherited `SimpleReadAccessController`', function () { + const user = 101 + let uptimeFeedContract: StarknetContract + + before(async function () { + const uptimeFeedFactory = await starknet.getContractFactory('sequencer_uptime_feed') + await owner.declare(uptimeFeedFactory) + + uptimeFeedContract = await owner.deploy(uptimeFeedFactory, { + initial_status: 0, + owner_address: num.toBigInt(owner.starknetContract.address), + }) + }) + + it('should block non-owners from making admin changes', async function () { + await owner.invoke(uptimeFeedContract, 'add_access', { user }) + + await expectInvokeError( + nonOwner.invoke(uptimeFeedContract, 'add_access', { user }), + 'Ownable: caller is not the owner', + ) + }) + + it('should report access information correctly', async function () { + { + const res = await uptimeFeedContract.call('has_access', { user: user, data: [] }) + expect(res.bool).to.equal(1n) + } + + { + const res = await uptimeFeedContract.call('has_access', { user: user + 1, data: [] }) + expect(res.bool).to.equal(0n) + } + }) + + it('should error on `check_access` without access', async function () { + await uptimeFeedContract.call('check_access', { user: user }) + + await expectInvokeError( + owner.invoke(uptimeFeedContract, 'check_access', { user: user + 1 }), + 'SimpleReadAccessController: address does not have access', + ) + }) + + it('should disable access check', async function () { + await owner.invoke(uptimeFeedContract, 'disable_access_check', {}) + + const res = await uptimeFeedContract.call('has_access', { user: user + 1, data: [] }) + expect(res.bool).to.equal(1n) + }) + + it('should enable access check', async function () { + await owner.invoke(uptimeFeedContract, 'enable_access_check', {}) + + const res = await uptimeFeedContract.call('has_access', { user: user + 1, data: [] }) + expect(res.bool).to.equal(0n) + }) + + it('should remove user access', async function () { + const res = await uptimeFeedContract.call('has_access', { user: user, data: [] }) + expect(res.bool).to.equal(1n) + + await owner.invoke(uptimeFeedContract, 'remove_access', { user: user }) + + const new_res = await uptimeFeedContract.call('has_access', { user: user, data: [] }) + expect(new_res.bool).to.equal(0n) + }) + }) + + describe('Test IAggregator interface using a Proxy', function () { + let uptimeFeedContract: StarknetContract + let proxyContract: StarknetContract + + before(async function () { + const uptimeFeedFactory = await starknet.getContractFactory('sequencer_uptime_feed') + await owner.declare(uptimeFeedFactory) + uptimeFeedContract = await owner.deploy(uptimeFeedFactory, { + initial_status: 0, + owner_address: num.toBigInt(owner.starknetContract.address), + }) + + const proxyFactory = await starknet.getContractFactory('aggregator_proxy') + await owner.declare(proxyFactory) + proxyContract = await owner.deploy(proxyFactory, { + owner: num.toBigInt(owner.starknetContract.address), + address: num.toBigInt(uptimeFeedContract.address), + }) + + // proxy contract needs to have access to uptimeFeedContract + await owner.invoke(uptimeFeedContract, 'add_access', { user: proxyContract.address }) + }) + + it('should block access when using an account without access', async function () { + const accWithoutAccess = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: accWithoutAccess.address, amount: 1e21 }]) + await accWithoutAccess.deployAccount() + await expectInvokeError( + accWithoutAccess.invoke(proxyContract, 'latest_round_data'), + 'SimpleReadAccessController: address does not have access', + ) + }) + + it('should respond via an aggregator_proxy contract', async function () { + { + const res = await proxyContract.call('latest_round_data') + expect(res.round.answer).to.equal(0n) + } + + { + const res = await proxyContract.call('description') + expect(res.description).to.equal( + 134626335741441605527772921271890603575702899782138692259993464692975953252n, + ) + } + + { + const res = await proxyContract.call('decimals') + expect(res.decimals).to.equal(0n) + } + + // TODO: enable access check and assert correct behaviour + }) + }) +}) diff --git a/contracts/test/ocr2/aggregator.test.ts b/contracts/test/ocr2/aggregator.test.ts new file mode 100644 index 0000000..f88480b --- /dev/null +++ b/contracts/test/ocr2/aggregator.test.ts @@ -0,0 +1,468 @@ +import { assert, expect } from 'chai' +import BN from 'bn.js' +import { starknet } from 'hardhat' +import { ec, hash, num, uint256 } from 'starknet' +import { Account, StarknetContract, StarknetContractFactory } from 'hardhat/types/runtime' +import { shouldBehaveLikeOwnableContract } from '../access/behavior/ownable' +import { TIMEOUT } from '../constants' +import { account, expectInvokeErrorMsg } from '@pluginv3.0/starknet' + +interface Oracle { + signer: Uint8Array + transmitter: Account +} + +const CHUNK_SIZE = 31 + +// Observers - max 31 oracles or 31 bytes +const OBSERVERS_MAX = 31 +const OBSERVERS_HEX = '0x00010203000000000000000000000000000000000000000000000000000000' +const INT128_MIN = BigInt(-2) ** BigInt(128 - 1) +const INT128_MAX = BigInt(2) ** BigInt(128 - 1) - BigInt(1) + +function encodeBytes(data: Uint8Array): string[] { + let felts = [] + + // prefix with len + let len = data.byteLength + felts.push(num.toBigInt(len).toString()) + + // chunk every 31 bytes + for (let i = 0; i < data.length; i += CHUNK_SIZE) { + const chunk = data.slice(i, i + CHUNK_SIZE) + // cast to int + felts.push(new BN(chunk, 'be').toString()) + } + return felts +} + +function decodeBytes(felts: BN[]): Uint8Array { + let data = [] + + // TODO: validate len > 1 + + // TODO: validate it fits into 54 bits + let length = felts.shift()?.toNumber()! + + for (const felt of felts) { + let chunk = felt.toArray('be', Math.min(CHUNK_SIZE, length)) + data.push(...chunk) + + length -= chunk.length + } + + return new Uint8Array(data) +} + +describe('aggregator.cairo', function () { + this.timeout(TIMEOUT) + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + let aggregatorFactory: StarknetContractFactory + + let owner: Account + let token: StarknetContract + let aggregator: StarknetContract + + let minAnswer = 2 + let maxAnswer = 1000000000 + + let f = 1 + let n = 3 * f + 1 + let oracles: Oracle[] = [] + let config_digest: number + + let answer: string + + before(async () => { + // assumes contract.cairo and events.cairo has been compiled + aggregatorFactory = await starknet.getContractFactory('ocr2/aggregator') + + // can also be declared as + // account = (await starknet.deployAccount("OpenZeppelin")) as OpenZeppelinAccount + // if imported from hardhat/types/runtime" + owner = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: owner.address, amount: 1e21 }]) + await owner.deployAccount() + + const tokenFactory = await starknet.getContractFactory('link_token') + await owner.declare(tokenFactory) + token = await owner.deploy(tokenFactory, { owner: owner.starknetContract.address }) + + await owner.invoke(token, 'permissionedMint', { + account: owner.starknetContract.address, + amount: uint256.bnToUint256(100_000_000_000), + }) + + await owner.declare(aggregatorFactory) + + aggregator = await owner.deploy(aggregatorFactory, { + owner: BigInt(owner.starknetContract.address), + link: BigInt(token.address), + min_answer: minAnswer, // TODO: toFelt() to correctly wrap negative ints + max_answer: maxAnswer, // TODO: toFelt() to correctly wrap negative ints + billing_access_controller: 0, // TODO: billing AC + decimals: 8, + description: starknet.shortStringToBigInt('FOO/BAR'), + }) + + console.log(`Deployed 'aggregator.cairo': ${aggregator.address}`) + + let futures = [] + let generateOracle = async () => { + let transmitter = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: transmitter.address, amount: 1e21 }]) + await transmitter.deployAccount() + + return { + signer: ec.starkCurve.utils.randomPrivateKey(), + transmitter, + // payee + } + } + for (let i = 0; i < n; i++) { + futures.push(generateOracle()) + } + oracles = await Promise.all(futures) + + let onchain_config: number[] = [] + let offchain_config_version = 2 + let offchain_config = new Uint8Array([1]) + let offchain_config_encoded = encodeBytes(offchain_config) + console.log('Encoded offchain_config: %O', encodeBytes(offchain_config)) + + let config = { + oracles: oracles.map((oracle) => { + return { + signer: ec.starkCurve.getStarkKey(oracle.signer), + transmitter: oracle.transmitter.starknetContract.address, + } + }), + f, + onchain_config, + offchain_config_version, + offchain_config: offchain_config_encoded, + } + await owner.invoke(aggregator, 'set_config', config) + console.log('Config: %O', config) + + let result = await aggregator.call('latest_config_details') + config_digest = result.config_digest + console.log(`Config digest: 0x${config_digest.toString(16)}`) + + // Immitate the fetch done by relay to confirm latest_config_details_works + let block = await starknet.getBlock({ blockNumber: result.block_number }) + let events = block.transaction_receipts[0].events + + assert.isNotEmpty(events) + assert.equal(events.length, 2) + console.log("Log raw 'ConfigSet' event: %O", events[0]) + + const decodedEvents = aggregator.decodeEvents(events) + assert.isNotEmpty(decodedEvents) + assert.equal(decodedEvents.length, 1) + console.log("Log decoded 'ConfigSet' event: %O", decodedEvents[0]) + + let e = decodedEvents[0] + assert.equal(e.name, 'ConfigSet') + }) + + shouldBehaveLikeOwnableContract(async () => { + const alice = owner + const bob = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: bob.address, amount: 1e21 }]) + await bob.deployAccount() + + return { ownable: aggregator, alice, bob } + }) + + describe('OCR aggregator behavior', function () { + let transmit = async (epoch_and_round: number, answer: num.BigNumberish): Promise => { + let extra_hash = 1 + let observation_timestamp = 1 + let juels_per_fee_coin = 1 + let gas_price = 1 + + let observers_buf = Buffer.alloc(31) + let observations = [] + + for (const [index, _] of oracles.entries()) { + observers_buf[index] = index + observations.push(answer) + } + + // convert to a single value that will be decoded by toBN + let observers = `0x${observers_buf.toString('hex')}` + assert.equal(observers, OBSERVERS_HEX) + + const reportData = [ + // report_context + config_digest, + epoch_and_round, + extra_hash, + // raw_report + observation_timestamp, + observers, + observations.length, + ...observations, + juels_per_fee_coin, + gas_price, + ] + let reportDigest = hash.computeHashOnElements(reportData) + console.log('Report data: %O', reportData) + console.log(`Report digest: ${reportDigest}`) + + console.log('Report signatures - START') + let signatures = [] + for (let { signer } of oracles.slice(0, f + 1)) { + let signature = ec.starkCurve.sign(reportDigest, signer) + let r = signature.r + let s = signature.s + const pubKey = num.toHex(ec.starkCurve.getStarkKey(signer)) + signatures.push({ r, s, public_key: pubKey }) + console.log({ pubKey, privKey: signer, r, s }) + } + console.log('Report signatures - END\n') + + const transmitter = oracles[0].transmitter + return await transmitter.invoke(aggregator, 'transmit', { + report_context: { + config_digest, + epoch_and_round, + extra_hash, + }, + observation_timestamp, + observers, + observations, + juels_per_fee_coin, + gas_price, + signatures, + }) + } + + it("should 'set_billing' successfully", async () => { + await owner.invoke(aggregator, 'set_billing', { + config: { + observation_payment_gjuels: 1, + transmission_payment_gjuels: 5, + gas_base: 1, + gas_per_signature: 1, + }, + }) + }) + + it("should emit 'NewTransmission' event on transmit", async () => { + const txHash = await transmit(1, 99) + const receipt = await starknet.getTransactionReceipt(txHash) + + assert.isNotEmpty(receipt.events) + console.log("Log raw 'NewTransmission' event: %O", receipt.events[0]) + + const decodedEvents = aggregator.decodeEvents(receipt.events) + assert.isNotEmpty(decodedEvents) + console.log("Log decoded 'NewTransmission' event: %O", decodedEvents[0]) + + const e = decodedEvents[0] + const transmitter = oracles[0].transmitter.address + + assert.equal(e.name, 'NewTransmission') + assert.equal(e.data.round_id, 1n) + assert.equal(e.data.observation_timestamp, 1n) + assert.equal(e.data.epoch_and_round, 1n) + // assert.equal(e.data.reimbursement, 0n) + + const len = 32 * 2 // 32 bytes (hex) + + // NOTICE: Leading zeros are trimmed for an encoded felt (number). + // To decode, the raw felt needs to be start padded up to max felt size (252 bits or < 32 bytes). + const hexPadStart = (data: number | bigint, len: number) => { + return `0x${data.toString(16).padStart(len, '0')}` + } + + expect(hexPadStart(e.data.transmitter, len)).to.hexEqual(transmitter) + + const lenObservers = OBSERVERS_MAX * 2 // 31 bytes (hex) + assert.equal(hexPadStart(e.data.observers, lenObservers), OBSERVERS_HEX) + assert.equal(e.data.observations_len, 4n) + + assert.equal(hexPadStart(e.data.config_digest, len), hexPadStart(config_digest, len)) + }) + + it('should transmit correctly', async () => { + await transmit(2, 99) + + let { round } = await aggregator.call('latest_round_data') + assert.equal(round.round_id, 2) + assert.equal(round.answer, 99) + + // await transmit(3, -10) // TODO: toFelt() to correctly wrap negative ints + // ;({ round } = await aggregator.call('latest_round_data')) + // assert.equal(round.round_id, 3) + // assert.equal(round.answer, -10) + + try { + await transmit(4, 1) + expect.fail() + } catch (err: any) { + // Round should be unchanged + let { round: new_round } = await aggregator.call('latest_round_data') + assert.deepEqual(round, new_round) + } + }) + + it('should transmit with max_int_128bit correctly', async () => { + answer = BigInt(INT128_MAX).toString(10) + try { + await transmit(4, answer) // TODO: toFelt() + expect.fail() + } catch (error: any) { + const matches = error?.message.match(/Error message: (.+?)\n/g) + if (!matches) { + console.log('answer is in int128 range but not in min-max range') + } + } + + try { + const tooBig = INT128_MAX + 1n + answer = BigInt(tooBig).toString(10) + await transmit(4, answer) + expect.fail() + } catch (err: any) { + expectInvokeErrorMsg( + err?.message, + `Error message: Aggregator: value not in int128 range: ${answer}\n`, + ) + } + }) + + // it('should transmit with min_int_128bit correctly', async () => { + // answer = BigInt(INT128_MIN).toString(10) + // try { + // await transmit(4, answer) // TODO: toFelt() + // } catch (err: any) { + // const matches = err?.message.match(/Error message: (.+?)\n/g) + // if (!matches) { + // console.log('answer is in int128 range but not in min-max range') + // } + // } + // + // try { + // const tooBig = INT128_MIN - 1n + // answer = BigInt(tooBig).toString(10) + // await transmit(4, answer) // TODO: toFelt() + // expect.fail() + // } catch (err: any) { + // expectInvokeErrorMsg( + // err?.message, + // `Error message: Aggregator: value not in int128 range: ${answer}\n`, + // ) + // } + // }) + + it('payee management', async () => { + let payees = oracles.map((oracle) => ({ + transmitter: oracle.transmitter.starknetContract.address, + payee: oracle.transmitter.starknetContract.address, // reusing transmitter acocunts as payees for simplicity + })) + // call set_payees, should succeed because all payees are zero + await owner.invoke(aggregator, 'set_payees', { payees }) + // call set_payees, should succeed because values are unchanged + await owner.invoke(aggregator, 'set_payees', { payees }) + + let oracle = oracles[0].transmitter + let transmitter = oracle.starknetContract.address + let payee = transmitter + + let proposed_oracle = oracles[1].transmitter + let proposed_transmitter = proposed_oracle.starknetContract.address + let proposed_payee = proposed_transmitter + + // can't transfer to self + try { + await oracle.invoke(aggregator, 'transfer_payeeship', { + transmitter, + proposed: payee, + }) + expect.fail() + } catch (err: any) { + // TODO: expect(err.message).to.contain(""); + } + + // only payee can transfer + try { + await proposed_oracle.invoke(aggregator, 'transfer_payeeship', { + transmitter, + proposed: proposed_payee, + }) + expect.fail() + } catch (err: any) {} + + // successful transfer + await oracle.invoke(aggregator, 'transfer_payeeship', { + transmitter, + proposed: proposed_payee, + }) + + // only proposed payee can accept + try { + await oracle.invoke(aggregator, 'accept_payeeship', { transmitter }) + expect.fail() + } catch (err: any) {} + + // successful accept + await proposed_oracle.invoke(aggregator, 'accept_payeeship', { + transmitter, + }) + }) + + it('payments and withdrawals', async () => { + let oracle = oracles[0] + // NOTE: previous test changed oracle0's payee to oracle1 + let payee = oracles[1].transmitter + aggregator.call + let { amount: owed } = await aggregator.call('owed_payment', { + transmitter: oracle.transmitter.starknetContract.address, + }) + // several rounds happened so we are owed payment + assert.ok(owed > 0) + + // no funds on contract, so no PLI available for payment + let { available } = await aggregator.call('link_available_for_payment') + assert.ok(available < 0) // should be negative: we owe payments + + // deposit PLI to contract + await owner.invoke(token, 'transfer', { + recipient: aggregator.address, + amount: uint256.bnToUint256(100_000_000_000), + }) + + // we have enough funds available now + available = (await aggregator.call('link_available_for_payment')).available + assert.ok(available > 0) + + // attempt to withdraw the payment + await payee.invoke(aggregator, 'withdraw_payment', { + transmitter: oracle.transmitter.starknetContract.address, + }) + + // balance as transferred to payee + let { balance } = await token.call('balanceOf', { + account: payee.starknetContract.address, + }) + + assert.ok(num.toBigInt(owed) === uint256.uint256ToBN(balance)) + + // owed payment is now zero + { + let { amount: owed } = await aggregator.call('owed_payment', { + transmitter: oracle.transmitter.starknetContract.address, + }) + assert.ok(owed == 0) + } + }) + }) +}) diff --git a/contracts/test/ocr2/aggregator_proxy.test.ts b/contracts/test/ocr2/aggregator_proxy.test.ts new file mode 100644 index 0000000..32af3db --- /dev/null +++ b/contracts/test/ocr2/aggregator_proxy.test.ts @@ -0,0 +1,110 @@ +import { assert } from 'chai' +import { starknet } from 'hardhat' +import { num } from 'starknet' +import { Account, StarknetContract, StarknetContractFactory } from 'hardhat/types/runtime' +import { TIMEOUT } from '../constants' +import { shouldBehaveLikeOwnableContract } from '../access/behavior/ownable' +import { account } from '@pluginv3.0/starknet' + +describe('aggregator_proxy.cairo', function () { + this.timeout(TIMEOUT) + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + let aggregatorContractFactory: StarknetContractFactory + let proxyContractFactory: StarknetContractFactory + + let owner: Account + let aggregator: StarknetContract + let proxy: StarknetContract + + before(async function () { + // assumes contract.cairo and events.cairo has been compiled + aggregatorContractFactory = await starknet.getContractFactory('ocr2/mocks/MockAggregator') + proxyContractFactory = await starknet.getContractFactory('ocr2/aggregator_proxy') + + owner = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: owner.address, amount: 1e21 }]) + await owner.deployAccount() + + await owner.declare(aggregatorContractFactory) + aggregator = await owner.deploy(aggregatorContractFactory, { decimals: 8 }) + + await owner.declare(proxyContractFactory) + + proxy = await owner.deploy(proxyContractFactory, { + owner: owner.address, + address: aggregator.address, + }) + + console.log(proxy.address) + }) + + shouldBehaveLikeOwnableContract(async () => { + const alice = owner + const bob = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: bob.address, amount: 1e21 }]) + await bob.deployAccount() + return { ownable: proxy, alice, bob } + }) + + describe('proxy behaviour', function () { + it('works', async () => { + // insert round into the mock + await owner.invoke(aggregator, 'set_latest_round_data', { + answer: 10, + block_num: 1, + observation_timestamp: 9, + transmission_timestamp: 8, + }) + + // query latest round + let { round } = await proxy.call('latest_round_data') + // TODO: split_felt the round_id and check phase=1 round=1 + assert.equal(round.answer, '10') + assert.equal(round.block_num, '1') + assert.equal(round.started_at, '9') + assert.equal(round.updated_at, '8') + + // insert a second ocr2 aggregator + let new_aggregator = await owner.deploy(aggregatorContractFactory, { decimals: 8 }) + + // insert round into the mock + await owner.invoke(new_aggregator, 'set_latest_round_data', { + answer: 12, + block_num: 2, + observation_timestamp: 10, + transmission_timestamp: 11, + }) + + // propose it to the proxy + await owner.invoke(proxy, 'propose_aggregator', { + address: new_aggregator.address, + }) + + // query latest round, it should still point to the old aggregator + round = (await proxy.call('latest_round_data')).round + assert.equal(round.answer, '10') + + // but the proposed round should be newer + round = (await proxy.call('proposed_latest_round_data')).round + assert.equal(round.answer, '12') + + // confirm the new aggregator + await owner.invoke(proxy, 'confirm_aggregator', { + address: new_aggregator.address, + }) + + const phase_aggregator = await proxy.call('aggregator', {}) + assert.equal(phase_aggregator.aggregator, num.toBigInt(new_aggregator.address)) + + const phase_id = await proxy.call('phase_id', {}) + assert.equal(phase_id.phase_id, 2n) + + // query latest round, it should now point to the new aggregator + round = (await proxy.call('latest_round_data')).round + assert.equal(round.answer, '12') + }) + }) +}) diff --git a/contracts/test/token/ERC677/ERC677.test.ts b/contracts/test/token/ERC677/ERC677.test.ts new file mode 100644 index 0000000..0dd64f3 --- /dev/null +++ b/contracts/test/token/ERC677/ERC677.test.ts @@ -0,0 +1,153 @@ +import { expect } from 'chai' +import { starknet } from 'hardhat' +import { uint256, num } from 'starknet' +import { Account, StarknetContract, StarknetContractFactory } from 'hardhat/types/runtime' +import { TIMEOUT } from '../../constants' +import { account } from '@pluginv3.0/starknet' + +describe('ERC677', function () { + this.timeout(TIMEOUT) + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + let receiverFactory: StarknetContractFactory + let tokenFactory: StarknetContractFactory + let receiver: StarknetContract + let sender: Account + let token: StarknetContract + let data: (number | bigint)[] + + beforeEach(async () => { + sender = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: sender.address, amount: 1e21 }]) + await sender.deployAccount() + + receiverFactory = await starknet.getContractFactory('token677_receiver_mock') + tokenFactory = await starknet.getContractFactory('link_token') + + await sender.declare(receiverFactory) + receiver = await sender.deploy(receiverFactory, {}) + + await sender.declare(tokenFactory) + token = await sender.deploy(tokenFactory, { owner: sender.starknetContract.address }) + + await sender.invoke(token, 'permissionedMint', { + account: sender.starknetContract.address, + amount: uint256.bnToUint256(1000), + }) + + await sender.invoke(token, 'transfer', { + recipient: sender.starknetContract.address, + amount: uint256.bnToUint256(100), + }) + const { value: value } = await receiver.call('getSentValue') + expect(uint256.uint256ToBN(value)).to.deep.equal(num.toBigInt(0)) + }) + + describe('#transferAndCall(address, uint, bytes)', () => { + beforeEach(() => { + data = [100n, 0n, 12] + }) + + it('transfers the tokens', async () => { + let { balance: balance } = await token.call('balanceOf', { + account: receiver.address, + }) + + expect(uint256.uint256ToBN(balance)).to.deep.equal(num.toBigInt(0)) + + await sender.invoke(token, 'transferAndCall', { + to: receiver.address, + value: uint256.bnToUint256(100), + data: data, + }) + + let { balance: balance1 } = await token.call('balanceOf', { + account: receiver.address, + }) + expect(uint256.uint256ToBN(balance1)).to.deep.equal(num.toBigInt(100)) + }) + + it('calls the token fallback function on transfer', async () => { + await sender.invoke(token, 'transferAndCall', { + to: receiver.address, + value: uint256.bnToUint256(100), + data: data, + }) + + const { bool: bool } = await receiver.call('getCalledFallback', {}) + expect(bool).to.deep.equal(1n) + + const { address: address } = await receiver.call('getTokenSender', {}) + expect(address).to.equal(BigInt(sender.starknetContract.address)) + + const { value: sentValue } = await receiver.call('getSentValue') + expect(uint256.uint256ToBN(sentValue)).to.deep.equal(num.toBigInt(100)) + }) + + it('transfer succeeds with response', async () => { + const response = await sender.invoke(token, 'transferAndCall', { + to: receiver.address, + value: uint256.bnToUint256(100), + data: data, + }) + expect(response).to.exist + }) + + it('throws when the transfer fails', async () => { + try { + await sender.invoke(token, 'transfer', { + recipient: receiver.address, + amount: uint256.bnToUint256(10000), + }) + expect.fail() + } catch (error: any) {} + }) + }) + + describe('when sending to a contract that is not ERC677 compatible', () => { + let nonERC677: StarknetContract + + beforeEach(async () => { + const nonERC677Factory = await starknet.getContractFactory('not_erc677_compatible') + + await sender.declare(nonERC677Factory) + nonERC677 = await sender.deploy(nonERC677Factory, {}) + + data = [1000n, 0n, 12n] + }) + + it('throws an error', async () => { + try { + await sender.invoke(token, 'transferAndCall', { + to: nonERC677.address, + value: uint256.bnToUint256(1000), + data: data, + }) + expect.fail() + } catch (error: any) { + let { balance: balance1 } = await token.call('balanceOf', { + account: nonERC677.address, + }) + expect(uint256.uint256ToBN(balance1)).to.deep.equal(num.toBigInt(0)) + } + }) + + it('throws an error when sending to 0 address', async () => { + try { + await sender.invoke(token, 'transferAndCall', { + to: 0, + value: uint256.bnToUint256(1000), + data: data, + }) + expect.fail() + } catch (error: any) { + let { balance: balance1 } = await token.call('balanceOf', { + account: 0, + }) + expect(uint256.uint256ToBN(balance1)).to.deep.equal(num.toBigInt(0)) + } + }) + }) +}) diff --git a/contracts/test/token/ERC677/link-receiver.test.ts b/contracts/test/token/ERC677/link-receiver.test.ts new file mode 100644 index 0000000..d14bc07 --- /dev/null +++ b/contracts/test/token/ERC677/link-receiver.test.ts @@ -0,0 +1,231 @@ +import { expect } from 'chai' +import { starknet } from 'hardhat' +import { uint256, hash, num } from 'starknet' +import { Account, StarknetContract, StarknetContractFactory } from 'hardhat/types/runtime' +import { TIMEOUT } from '../../constants' +import { account } from '@pluginv3.0/starknet' + +describe('LinkToken', function () { + this.timeout(TIMEOUT) + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + let receiverFactory: StarknetContractFactory + let linkReceiverFactory: StarknetContractFactory + let tokenFactory: StarknetContractFactory + let receiver: StarknetContract + let recipient: StarknetContract + let sender: Account + let owner: Account + let token: StarknetContract + + beforeEach(async () => { + sender = await starknet.OpenZeppelinAccount.createAccount() + owner = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([ + { account: sender.address, amount: 1e21 }, + { account: owner.address, amount: 1e21 }, + ]) + await sender.deployAccount() + await owner.deployAccount() + + receiverFactory = await starknet.getContractFactory('token677_receiver_mock') + tokenFactory = await starknet.getContractFactory('link_token') + + await owner.declare(receiverFactory) + await sender.declare(tokenFactory) + + receiver = await sender.deploy(receiverFactory, {}) + token = await owner.deploy(tokenFactory, { owner: owner.starknetContract.address }) + + await owner.invoke(token, 'permissionedMint', { + account: owner.starknetContract.address, + amount: uint256.bnToUint256(1000000000000000), + }) + }) + + it('assigns all of the balance to the owner', async () => { + let { balance: balance } = await token.call('balanceOf', { + account: owner.starknetContract.address, + }) + expect(uint256.uint256ToBN(balance).toString()).to.equal('1000000000000000') + }) + + describe('#transfer(address,uint256)', () => { + beforeEach(async () => { + await owner.invoke(token, 'transfer', { + recipient: sender.starknetContract.address, + amount: uint256.bnToUint256(100), + }) + const { value: sentValue } = await receiver.call('getSentValue') + expect(uint256.uint256ToBN(sentValue)).to.deep.equal(num.toBigInt(0)) + }) + + it('does not let you transfer to the null address', async () => { + try { + await sender.invoke(token, 'transfer', { recipient: 0, value: uint256.bnToUint256(100) }) + expect.fail() + } catch (error: any) { + let { balance: balance1 } = await token.call('balanceOf', { + account: sender.starknetContract.address, + }) + expect(uint256.uint256ToBN(balance1)).to.deep.equal(num.toBigInt(100)) + } + }) + + // TODO For now it let you transfer to the contract itself + it.skip('does not let you transfer to the contract itself', async () => { + try { + await sender.invoke(token, 'transfer', { + recipient: token.address, + amount: uint256.bnToUint256(100), + }) + expect.fail() + } catch (error: any) { + let { balance: balance1 } = await token.call('balanceOf', { + account: sender.starknetContract.address, + }) + expect(uint256.uint256ToBN(balance1)).to.deep.equal(num.toBigInt(100)) + } + }) + + it('transfers the tokens', async () => { + let { balance: balance } = await token.call('balanceOf', { + account: receiver.address, + }) + expect(uint256.uint256ToBN(balance)).to.deep.equal(num.toBigInt(0)) + + await sender.invoke(token, 'transfer', { + recipient: receiver.address, + amount: uint256.bnToUint256(100), + }) + + let { balance: balance1 } = await token.call('balanceOf', { + account: receiver.address, + }) + expect(uint256.uint256ToBN(balance1)).to.deep.equal(num.toBigInt(100)) + }) + + it('does NOT call the fallback on transfer', async () => { + await sender.invoke(token, 'transfer', { + recipient: receiver.address, + amount: uint256.bnToUint256(100), + }) + const { bool: bool } = await receiver.call('getCalledFallback', {}) + expect(bool).to.deep.equal(0n) + }) + + it('transfer succeeds with response', async () => { + const response = await sender.invoke(token, 'transfer', { + recipient: receiver.address, + amount: uint256.bnToUint256(100), + }) + expect(response).to.exist + }) + }) + + describe('#transferAndCall(address,uint256,bytes)', () => { + const amount = 1000 + + before(async () => { + linkReceiverFactory = await starknet.getContractFactory('link_receiver') + const classHash = await owner.declare(linkReceiverFactory) + recipient = await owner.deploy(linkReceiverFactory, { class_hash: classHash }) + + const { remaining: allowance } = await token.call('allowance', { + owner: owner.starknetContract.address, + spender: recipient.address, + }) + expect(uint256.uint256ToBN(allowance)).to.deep.equal(num.toBigInt(0)) + + let { balance: balance } = await token.call('balanceOf', { + account: recipient.address, + }) + expect(uint256.uint256ToBN(balance)).to.deep.equal(num.toBigInt(0)) + }) + + xit('transfers the amount to the contract and calls the contract function without withdrawl', async () => { + let selector = hash.getSelectorFromName('callbackWithoutWithdrawl') + await owner.invoke(token, 'transferAndCall', { + to: recipient.address, + value: uint256.bnToUint256(1000), + data: [selector], + }) + + let { balance: balance } = await token.call('balanceOf', { + account: recipient.address, + }) + expect(uint256.uint256ToBN(balance)).to.deep.equal(num.toBigInt(amount)) + const { remaining: allowance } = await token.call('allowance', { + owner: owner.starknetContract.address, + spender: recipient.address, + }) + expect(uint256.uint256ToBN(allowance)).to.deep.equal(num.toBigInt(0)) + + const { bool: fallBack } = await recipient.call('getFallback', {}) + expect(fallBack).to.deep.equal(1n) + + const { bool: callData } = await recipient.call('getCallData', {}) + expect(callData).to.deep.equal(1n) + }) + + xit('transfers the amount to the contract and calls the contract function with withdrawl', async () => { + let selector = hash.getSelectorFromName('callbackWithWithdrawl') + await owner.invoke(token, 'approve', { + spender: recipient.address, + amount: uint256.bnToUint256(1000), + }) + + const { remaining: allowance } = await token.call('allowance', { + owner: owner.starknetContract.address, + spender: recipient.address, + }) + expect(uint256.uint256ToBN(allowance)).to.deep.equal(num.toBigInt(amount)) + + await owner.invoke(token, 'transferAndCall', { + to: recipient.address, + value: uint256.bnToUint256(1000), + data: [selector, 0n, 1000n, owner.starknetContract.address, token.address], + }) + + let { balance: balance } = await token.call('balanceOf', { + account: recipient.address, + }) + expect(uint256.uint256ToBN(balance)).to.deep.equal(num.toBigInt(amount + amount)) + + const { bool: fallBack } = await recipient.call('getFallback', {}) + expect(fallBack).to.deep.equal(1n) + + const { bool: callData } = await recipient.call('getCallData', {}) + expect(callData).to.deep.equal(1n) + + const { value: value } = await recipient.call('getTokens', {}) + expect(uint256.uint256ToBN(value)).to.deep.equal(num.toBigInt(amount)) + }) + + it('transfers the amount to the account and does not call the contract', async () => { + await owner.invoke(token, 'approve', { + spender: sender.starknetContract.address, + amount: uint256.bnToUint256(1000), + }) + + const { remaining: allowance } = await token.call('allowance', { + owner: owner.starknetContract.address, + spender: sender.starknetContract.address, + }) + expect(uint256.uint256ToBN(allowance)).to.deep.equal(num.toBigInt(amount)) + + await owner.invoke(token, 'transferAndCall', { + to: sender.starknetContract.address, + value: uint256.bnToUint256(1000), + data: [], + }) + + let { balance: balance2 } = await token.call('balanceOf', { + account: sender.starknetContract.address, + }) + expect(uint256.uint256ToBN(balance2)).to.deep.equal(num.toBigInt(amount)) + }) + }) +}) diff --git a/contracts/test/token/starkgate/behavior/ERC20.ts b/contracts/test/token/starkgate/behavior/ERC20.ts new file mode 100644 index 0000000..2096ee3 --- /dev/null +++ b/contracts/test/token/starkgate/behavior/ERC20.ts @@ -0,0 +1,275 @@ +import { expect } from 'chai' +import { StarknetContract, Account } from 'hardhat/types/runtime' +import { uint256, num } from 'starknet' +import { TIMEOUT } from '../../../constants' +import { expectInvokeError } from '@pluginv3.0/starknet/src/utils' + +export type BeforeFn = () => Promise +export type TestData = { + token: StarknetContract + owner: Account + alice: Account + bob: Account +} + +const addresses = (t: TestData) => ({ + owner: t.owner.starknetContract.address, + bob: t.bob.starknetContract.address, + alice: t.alice.starknetContract.address, +}) + +const expectERC20Balance = async (token: StarknetContract, acc: Account, expected: number) => { + const { balance: raw } = await token.call('balanceOf', { + account: acc.starknetContract.address, + }) + const balance = uint256.uint256ToBN(raw) + expect(balance).to.deep.equal(num.toBigInt(expected)) +} + +const expectERC20TotalSupply = async (token: StarknetContract, expected: number) => { + const { totalSupply: raw } = await token.call('totalSupply', {}) + const totalSupply = uint256.uint256ToBN(raw) + expect(totalSupply).to.deep.equal(num.toBigInt(expected)) +} + +export const shouldBehaveLikeStarkGateERC20 = (beforeFn: BeforeFn) => { + describe('StarkGate.ERC20 behavior', function () { + this.timeout(TIMEOUT) + + let t: TestData + + before(async () => { + t = await beforeFn() + }) + + it(`should 'permissionedMint' successfully (2x)`, async () => { + const { alice, bob } = addresses(t) + + await t.owner.invoke(t.token, 'permissionedMint', { + account: alice, + amount: uint256.bnToUint256(15), + }) + + await expectERC20Balance(t.token, t.alice, 15) + + await t.owner.invoke(t.token, 'permissionedMint', { + account: bob, + amount: uint256.bnToUint256(12), + }) + + await expectERC20TotalSupply(t.token, 27) + await expectERC20Balance(t.token, t.bob, 12) + }) + + it(`should 'permissionedBurn' successfully (2x)`, async () => { + const { alice, bob } = addresses(t) + + await t.owner.invoke(t.token, 'permissionedBurn', { + account: alice, + amount: uint256.bnToUint256(3), + }) + + await expectERC20TotalSupply(t.token, 24) + await expectERC20Balance(t.token, t.alice, 12) + + await t.owner.invoke(t.token, 'permissionedBurn', { + account: bob, + amount: uint256.bnToUint256(10), + }) + + await expectERC20TotalSupply(t.token, 14) + await expectERC20Balance(t.token, t.bob, 2) + }) + + it(`reverts on 'permissionedBurn' (amount > balance)`, async () => { + const { alice, bob } = addresses(t) + + await expectInvokeError( + t.owner.invoke(t.token, 'permissionedBurn', { + account: bob, + amount: uint256.bnToUint256(103), + }), + ) + + await expectInvokeError( + t.owner.invoke(t.token, 'permissionedBurn', { + account: alice, + amount: uint256.bnToUint256(189), + }), + ) + }) + + it(`reverts on 'permissionedBurn' without permission`, async () => { + const { alice, bob } = addresses(t) + + await expectInvokeError( + t.alice.invoke(t.token, 'permissionedBurn', { + account: bob, + amount: uint256.bnToUint256(103), + }), + ) + + await expectInvokeError( + t.bob.invoke(t.token, 'permissionedBurn', { + account: alice, + amount: uint256.bnToUint256(189), + }), + ) + }) + + it(`should 'permissionedMint' and 'transfer' successfully`, async () => { + const { alice, bob } = addresses(t) + + await t.owner.invoke(t.token, 'permissionedMint', { + account: bob, + amount: uint256.bnToUint256(3), + }) + await t.alice.invoke(t.token, 'transfer', { + recipient: bob, + amount: uint256.bnToUint256(3), + }) + + await expectERC20Balance(t.token, t.alice, 9) + await expectERC20Balance(t.token, t.bob, 8) + + await t.bob.invoke(t.token, 'transfer', { + recipient: alice, + amount: uint256.bnToUint256(4), + }) + + await expectERC20Balance(t.token, t.alice, 13) + await expectERC20Balance(t.token, t.bob, 4) + }) + + it(`reverts on 'transfer' (amount > balance)`, async () => { + const { alice, bob } = addresses(t) + + await expectInvokeError( + t.bob.invoke(t.token, 'transfer', { + recipient: alice, + amount: uint256.bnToUint256(12), + }), + 'ERC20: transfer amount exceeds balance', + ) + + await expectInvokeError( + t.alice.invoke(t.token, 'transfer', { + recipient: bob, + amount: uint256.bnToUint256(17), + }), + 'ERC20: transfer amount exceeds balance', + ) + }) + + it(`should 'increaseAllowance' and 'transferFrom' successfully - #1`, async () => { + const { owner, alice, bob } = addresses(t) + + await t.bob.invoke(t.token, 'increaseAllowance', { + spender: owner, + added_value: uint256.bnToUint256(7), + }) + await t.alice.invoke(t.token, 'increaseAllowance', { + spender: owner, + added_value: uint256.bnToUint256(7), + }) + + await t.owner.invoke(t.token, 'transferFrom', { + sender: alice, + recipient: bob, + amount: uint256.bnToUint256(3), + }) + + await expectERC20Balance(t.token, t.alice, 10) + await expectERC20Balance(t.token, t.bob, 7) + + await t.owner.invoke(t.token, 'transferFrom', { + sender: bob, + recipient: alice, + amount: uint256.bnToUint256(4), + }) + + await expectERC20Balance(t.token, t.alice, 14) + await expectERC20Balance(t.token, t.bob, 3) + }) + + it(`should 'increaseAllowance' and 'transferFrom' successfully - #2`, async () => { + const { owner, alice, bob } = addresses(t) + + await t.bob.invoke(t.token, 'increaseAllowance', { + spender: owner, + added_value: uint256.bnToUint256(7), + }) + await t.alice.invoke(t.token, 'increaseAllowance', { + spender: owner, + added_value: uint256.bnToUint256(7), + }) + + await t.owner.invoke(t.token, 'transferFrom', { + sender: alice, + recipient: bob, + amount: uint256.bnToUint256(3), + }) + + await expectERC20Balance(t.token, t.alice, 11) + await expectERC20Balance(t.token, t.bob, 6) + + await t.bob.invoke(t.token, 'increaseAllowance', { + spender: owner, + added_value: uint256.bnToUint256(15), + }) + await t.alice.invoke(t.token, 'increaseAllowance', { + spender: owner, + added_value: uint256.bnToUint256(15), + }) + + await t.owner.invoke(t.token, 'transferFrom', { + sender: alice, + recipient: bob, + amount: uint256.bnToUint256(11), + }) + + await expectERC20Balance(t.token, t.alice, 0) + await expectERC20Balance(t.token, t.bob, 17) + }) + + it(`should 'decreaseAllowance' and 'transferFrom' successfully`, async () => { + const { owner, alice, bob } = addresses(t) + + await t.bob.invoke(t.token, 'decreaseAllowance', { + spender: owner, + subtracted_value: uint256.bnToUint256(10), + }) + + await t.owner.invoke(t.token, 'transferFrom', { + sender: bob, + recipient: alice, + amount: uint256.bnToUint256(1), + }) + + await expectERC20Balance(t.token, t.alice, 1) + await expectERC20Balance(t.token, t.bob, 16) + }) + + it(`reverts on 'transferFrom' (amount > allowance)`, async () => { + const { alice, bob } = addresses(t) + + await expectInvokeError( + t.owner.invoke(t.token, 'transferFrom', { + sender: bob, + recipient: alice, + amount: { low: 8n, high: 10n }, + }), + 'ERC20: insufficient allowance', + ) + + await expectInvokeError( + t.owner.invoke(t.token, 'transferFrom', { + sender: alice, + recipient: bob, + amount: uint256.bnToUint256(208), + }), + 'ERC20: insufficient allowance', + ) + }) + }) +} diff --git a/contracts/test/token/starkgate/link_token.test.ts b/contracts/test/token/starkgate/link_token.test.ts new file mode 100644 index 0000000..f33527a --- /dev/null +++ b/contracts/test/token/starkgate/link_token.test.ts @@ -0,0 +1,30 @@ +import { account } from '@pluginv3.0/starknet' +import { starknet } from 'hardhat' +import { TIMEOUT } from '../../constants' +import { shouldBehaveLikeStarkGateERC20 } from './behavior/ERC20' + +describe('link_token', function () { + this.timeout(TIMEOUT) + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + shouldBehaveLikeStarkGateERC20(async () => { + const owner = await starknet.OpenZeppelinAccount.createAccount() + const alice = await starknet.OpenZeppelinAccount.createAccount() + const bob = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([ + { account: owner.address, amount: 1e21 }, + { account: alice.address, amount: 1e21 }, + { account: bob.address, amount: 1e21 }, + ]) + await owner.deployAccount() + await alice.deployAccount() + await bob.deployAccount() + + const tokenFactory = await starknet.getContractFactory('link_token') + await owner.declare(tokenFactory) + const token = await owner.deploy(tokenFactory, { owner: owner.starknetContract.address }) + return { token, owner, alice, bob } + }) +}) diff --git a/contracts/tsconfig.json b/contracts/tsconfig.json new file mode 100644 index 0000000..13fad64 --- /dev/null +++ b/contracts/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "resolveJsonModule": true + }, + "include": [ + "./scripts", + "./test", + "./typechain-types" + ], + "files": [ + "./hardhat.config.ts" + ] +} diff --git a/contracts/vendor/starkware-libs/README.md b/contracts/vendor/starkware-libs/README.md new file mode 100644 index 0000000..1367c1a --- /dev/null +++ b/contracts/vendor/starkware-libs/README.md @@ -0,0 +1,6 @@ +# starkware-libs vendor contracts + +Here we duplicate the `starkware-libs/starkgate-contracts` project as we couldn't find a way to properly import it via NPM (only a few .cairo contracts packaged), PyPI (N/A), or a submodule (complex build). + +- `starkware-libs/starkgate-contracts` - duplicate of the original repo at [c08863a](https://github.com/starkware-libs/starkgate-contracts/commit/c08863a1f08226c09f1d0748124192e848d73db9) (includes only the files we use) +- `starkware-libs/starkgate-contracts-solidity-v0.8` - fork of the original repo at [c08863a](https://github.com/starkware-libs/starkgate-contracts/commit/c08863a1f08226c09f1d0748124192e848d73db9) which loosens the `pragma` declaration for a few interfaces to support v0.8 (includes only the files we use) diff --git a/contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessaging.sol b/contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessaging.sol new file mode 100644 index 0000000..d9b9d28 --- /dev/null +++ b/contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessaging.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.8.0; + +import "./IStarknetMessagingEvents.sol"; + +interface IStarknetMessaging is IStarknetMessagingEvents { + /** + Sends a message to an L2 contract. + This function is payable, the payed amount is the message fee. + + Returns the hash of the message and the nonce of the message. + */ + function sendMessageToL2( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload + ) external payable returns (bytes32, uint256); + + /** + Consumes a message that was sent from an L2 contract. + + Returns the hash of the message. + */ + function consumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload) + external + returns (bytes32); + + /** + Starts the cancellation of an L1 to L2 message. + A message can be canceled messageCancellationDelay() seconds after this function is called. + + Note: This function may only be called for a message that is currently pending and the caller + must be the sender of the that message. + */ + function startL1ToL2MessageCancellation( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) external returns (bytes32); + + /** + Cancels an L1 to L2 message, this function should be called messageCancellationDelay() seconds + after the call to startL1ToL2MessageCancellation(). + + Note that the message fee is not refunded. + */ + function cancelL1ToL2Message( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) external returns (bytes32); +} diff --git a/contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol b/contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol new file mode 100644 index 0000000..2f52bfe --- /dev/null +++ b/contracts/vendor/starkware-libs/starkgate-contracts-solidity-v0.8/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.8.0; + +interface IStarknetMessagingEvents { + // This event needs to be compatible with the one defined in Output.sol. + event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload); + + // An event that is raised when a message is sent from L1 to L2. + event LogMessageToL2( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce, + uint256 fee + ); + + // An event that is raised when a message from L2 to L1 is consumed. + event ConsumedMessageToL1( + uint256 indexed fromAddress, + address indexed toAddress, + uint256[] payload + ); + + // An event that is raised when a message from L1 to L2 is consumed. + event ConsumedMessageToL2( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce + ); + + // An event that is raised when a message from L1 to L2 Cancellation is started. + event MessageToL2CancellationStarted( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce + ); + + // An event that is raised when a message from L1 to L2 is canceled. + event MessageToL2Canceled( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce + ); +} diff --git a/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/solidity/libraries/NamedStorage.sol b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/solidity/libraries/NamedStorage.sol new file mode 100644 index 0000000..817b793 --- /dev/null +++ b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/solidity/libraries/NamedStorage.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +/* + Library to provide basic storage, in storage location out of the low linear address space. + New types of storage variables should be added here upon need. +*/ +library NamedStorage { + function bytes32ToUint256Mapping(string memory tag_) + internal + pure + returns (mapping(bytes32 => uint256) storage randomVariable) + { + bytes32 location = keccak256(abi.encodePacked(tag_)); + assembly { + randomVariable_slot := location + } + } + + function bytes32ToAddressMapping(string memory tag_) + internal + pure + returns (mapping(bytes32 => address) storage randomVariable) + { + bytes32 location = keccak256(abi.encodePacked(tag_)); + assembly { + randomVariable_slot := location + } + } + + function addressToBoolMapping(string memory tag_) + internal + pure + returns (mapping(address => bool) storage randomVariable) + { + bytes32 location = keccak256(abi.encodePacked(tag_)); + assembly { + randomVariable_slot := location + } + } + + function getUintValue(string memory tag_) internal view returns (uint256 retVal) { + bytes32 slot = keccak256(abi.encodePacked(tag_)); + assembly { + retVal := sload(slot) + } + } + + function setUintValue(string memory tag_, uint256 value) internal { + bytes32 slot = keccak256(abi.encodePacked(tag_)); + assembly { + sstore(slot, value) + } + } + + function setUintValueOnce(string memory tag_, uint256 value) internal { + require(getUintValue(tag_) == 0, "ALREADY_SET"); + setUintValue(tag_, value); + } + + function getAddressValue(string memory tag_) internal view returns (address retVal) { + bytes32 slot = keccak256(abi.encodePacked(tag_)); + assembly { + retVal := sload(slot) + } + } + + function setAddressValue(string memory tag_, address value) internal { + bytes32 slot = keccak256(abi.encodePacked(tag_)); + assembly { + sstore(slot, value) + } + } + + function setAddressValueOnce(string memory tag_, address value) internal { + require(getAddressValue(tag_) == address(0x0), "ALREADY_SET"); + setAddressValue(tag_, value); + } + + function getBoolValue(string memory tag_) internal view returns (bool retVal) { + bytes32 slot = keccak256(abi.encodePacked(tag_)); + assembly { + retVal := sload(slot) + } + } + + function setBoolValue(string memory tag_, bool value) internal { + bytes32 slot = keccak256(abi.encodePacked(tag_)); + assembly { + sstore(slot, value) + } + } +} diff --git a/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessaging.sol b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessaging.sol new file mode 100644 index 0000000..5388ac6 --- /dev/null +++ b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessaging.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "./IStarknetMessagingEvents.sol"; + +interface IStarknetMessaging is IStarknetMessagingEvents { + /** + Sends a message to an L2 contract. + This function is payable, the payed amount is the message fee. + + Returns the hash of the message and the nonce of the message. + */ + function sendMessageToL2( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload + ) external payable returns (bytes32, uint256); + + /** + Consumes a message that was sent from an L2 contract. + + Returns the hash of the message. + */ + function consumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload) + external + returns (bytes32); + + /** + Starts the cancellation of an L1 to L2 message. + A message can be canceled messageCancellationDelay() seconds after this function is called. + + Note: This function may only be called for a message that is currently pending and the caller + must be the sender of the that message. + */ + function startL1ToL2MessageCancellation( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) external returns (bytes32); + + /** + Cancels an L1 to L2 message, this function should be called messageCancellationDelay() seconds + after the call to startL1ToL2MessageCancellation(). + + Note that the message fee is not refunded. + */ + function cancelL1ToL2Message( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) external returns (bytes32); +} diff --git a/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol new file mode 100644 index 0000000..9e7c841 --- /dev/null +++ b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/IStarknetMessagingEvents.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +interface IStarknetMessagingEvents { + // This event needs to be compatible with the one defined in Output.sol. + event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload); + + // An event that is raised when a message is sent from L1 to L2. + event LogMessageToL2( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce, + uint256 fee + ); + + // An event that is raised when a message from L2 to L1 is consumed. + event ConsumedMessageToL1( + uint256 indexed fromAddress, + address indexed toAddress, + uint256[] payload + ); + + // An event that is raised when a message from L1 to L2 is consumed. + event ConsumedMessageToL2( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce + ); + + // An event that is raised when a message from L1 to L2 Cancellation is started. + event MessageToL2CancellationStarted( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce + ); + + // An event that is raised when a message from L1 to L2 is canceled. + event MessageToL2Canceled( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce + ); +} diff --git a/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/StarknetMessaging.sol b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/StarknetMessaging.sol new file mode 100644 index 0000000..8b2d68d --- /dev/null +++ b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/solidity/StarknetMessaging.sol @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: Apache-2.0. +pragma solidity ^0.6.12; + +import "./IStarknetMessaging.sol"; +import "../../solidity/libraries/NamedStorage.sol"; + +/** + Implements sending messages to L2 by adding them to a pipe and consuming messages from L2 by + removing them from a different pipe. A deriving contract can handle the former pipe and add items + to the latter pipe while interacting with L2. +*/ +contract StarknetMessaging is IStarknetMessaging { + /* + Random slot storage elements and accessors. + */ + string constant L1L2_MESSAGE_MAP_TAG = "STARKNET_1.0_MSGING_L1TOL2_MAPPPING_V2"; + string constant L2L1_MESSAGE_MAP_TAG = "STARKNET_1.0_MSGING_L2TOL1_MAPPPING"; + + string constant L1L2_MESSAGE_NONCE_TAG = "STARKNET_1.0_MSGING_L1TOL2_NONCE"; + + string constant L1L2_MESSAGE_CANCELLATION_MAP_TAG = ( + "STARKNET_1.0_MSGING_L1TOL2_CANCELLATION_MAPPPING" + ); + + string constant L1L2_MESSAGE_CANCELLATION_DELAY_TAG = ( + "STARKNET_1.0_MSGING_L1TOL2_CANCELLATION_DELAY" + ); + + uint256 public constant MAX_L1_MSG_FEE = 1 ether; + + /** + Returns the msg_fee + 1 for the message with the given 'msgHash', + or 0 if no message with such a hash is pending. + */ + function l1ToL2Messages(bytes32 msgHash) external view returns (uint256) { + return l1ToL2Messages()[msgHash]; + } + + function l2ToL1Messages(bytes32 msgHash) external view returns (uint256) { + return l2ToL1Messages()[msgHash]; + } + + function l1ToL2Messages() internal pure returns (mapping(bytes32 => uint256) storage) { + return NamedStorage.bytes32ToUint256Mapping(L1L2_MESSAGE_MAP_TAG); + } + + function l2ToL1Messages() internal pure returns (mapping(bytes32 => uint256) storage) { + return NamedStorage.bytes32ToUint256Mapping(L2L1_MESSAGE_MAP_TAG); + } + + function l1ToL2MessageNonce() public view returns (uint256) { + return NamedStorage.getUintValue(L1L2_MESSAGE_NONCE_TAG); + } + + function messageCancellationDelay() public view returns (uint256) { + return NamedStorage.getUintValue(L1L2_MESSAGE_CANCELLATION_DELAY_TAG); + } + + function messageCancellationDelay(uint256 delayInSeconds) internal { + NamedStorage.setUintValue(L1L2_MESSAGE_CANCELLATION_DELAY_TAG, delayInSeconds); + } + + /** + Returns the timestamp at the time cancelL1ToL2Message was called with a message + matching 'msgHash'. + + The function returns 0 if cancelL1ToL2Message was never called. + */ + function l1ToL2MessageCancellations(bytes32 msgHash) external view returns (uint256) { + return l1ToL2MessageCancellations()[msgHash]; + } + + function l1ToL2MessageCancellations() + internal + pure + returns (mapping(bytes32 => uint256) storage) + { + return NamedStorage.bytes32ToUint256Mapping(L1L2_MESSAGE_CANCELLATION_MAP_TAG); + } + + /** + Returns the hash of an L1 -> L2 message from msg.sender. + */ + function getL1ToL2MsgHash( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) internal view returns (bytes32) { + return + keccak256( + abi.encodePacked( + uint256(msg.sender), + toAddress, + nonce, + selector, + payload.length, + payload + ) + ); + } + + /** + Sends a message to an L2 contract. + */ + function sendMessageToL2( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload + ) external payable override returns (bytes32, uint256) { + require(msg.value <= MAX_L1_MSG_FEE, "MAX_L1_MSG_FEE_EXCEEDED"); + uint256 nonce = l1ToL2MessageNonce(); + NamedStorage.setUintValue(L1L2_MESSAGE_NONCE_TAG, nonce + 1); + emit LogMessageToL2(msg.sender, toAddress, selector, payload, nonce, msg.value); + bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); + // Note that the inclusion of the unique nonce in the message hash implies that + // l1ToL2Messages()[msgHash] was not accessed before. + l1ToL2Messages()[msgHash] = msg.value + 1; + return (msgHash, nonce); + } + + /** + Consumes a message that was sent from an L2 contract. + + Returns the hash of the message. + */ + function consumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload) + external + override + returns (bytes32) + { + bytes32 msgHash = keccak256( + abi.encodePacked(fromAddress, uint256(msg.sender), payload.length, payload) + ); + + require(l2ToL1Messages()[msgHash] > 0, "INVALID_MESSAGE_TO_CONSUME"); + emit ConsumedMessageToL1(fromAddress, msg.sender, payload); + l2ToL1Messages()[msgHash] -= 1; + return msgHash; + } + + function startL1ToL2MessageCancellation( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) external override returns (bytes32) { + emit MessageToL2CancellationStarted(msg.sender, toAddress, selector, payload, nonce); + bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); + uint256 msgFeePlusOne = l1ToL2Messages()[msgHash]; + require(msgFeePlusOne > 0, "NO_MESSAGE_TO_CANCEL"); + l1ToL2MessageCancellations()[msgHash] = block.timestamp; + return msgHash; + } + + function cancelL1ToL2Message( + uint256 toAddress, + uint256 selector, + uint256[] calldata payload, + uint256 nonce + ) external override returns (bytes32) { + emit MessageToL2Canceled(msg.sender, toAddress, selector, payload, nonce); + bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); + uint256 msgFeePlusOne = l1ToL2Messages()[msgHash]; + require(msgFeePlusOne != 0, "NO_MESSAGE_TO_CANCEL"); + + uint256 requestTime = l1ToL2MessageCancellations()[msgHash]; + require(requestTime != 0, "MESSAGE_CANCELLATION_NOT_REQUESTED"); + + uint256 cancelAllowedTime = requestTime + messageCancellationDelay(); + require(cancelAllowedTime >= requestTime, "CANCEL_ALLOWED_TIME_OVERFLOW"); + require(block.timestamp >= cancelAllowedTime, "MESSAGE_CANCELLATION_NOT_ALLOWED_YET"); + + l1ToL2Messages()[msgHash] = 0; + return (msgHash); + } +} + diff --git a/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/std_contracts/ERC20/permitted.cairo b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/std_contracts/ERC20/permitted.cairo new file mode 100644 index 0000000..2d1c0ba --- /dev/null +++ b/contracts/vendor/starkware-libs/starkgate-contracts/src/starkware/starknet/std_contracts/ERC20/permitted.cairo @@ -0,0 +1,39 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.math import assert_not_zero +from starkware.starknet.common.syscalls import get_caller_address + +@storage_var +func permitted_minter() -> (res: felt) { +} + +// Constructor. + +func permitted_initializer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + minter_address: felt +) { + assert_not_zero(minter_address); + permitted_minter.write(minter_address); + return (); +} + +// Getters. + +@view +func permittedMinter{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + minter: felt +) { + let (minter) = permitted_minter.read(); + return (minter,); +} + +// Internals. + +func permitted_minter_only{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + let (caller_address) = get_caller_address(); + let (permitted_address) = permittedMinter(); + assert_not_zero(permitted_address); + assert caller_address = permitted_address; + return (); +} diff --git a/contracts/yarn.lock b/contracts/yarn.lock new file mode 100644 index 0000000..f5c0f32 --- /dev/null +++ b/contracts/yarn.lock @@ -0,0 +1,3700 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.2": + version "3.6.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.2.tgz#63d1e26d0b7a7a3684fce920de6ebabec1e5b674" + integrity sha512-mOqYWwMlAZpYUEOEqt7EfMFuVL2eyLqWWIzcf4odn6QgXY8jBI2NhVuJncrMCKeMZrsJAe7/auaRRB6YcdH+Qw== + dependencies: + "@ethereumjs/common" "^2.6.3" + "@ethereumjs/tx" "^3.5.1" + ethereumjs-util "^7.1.4" + merkle-patricia-tree "^4.2.4" + +"@ethereumjs/block@^3.6.3": + version "3.6.3" + resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.3.tgz#d96cbd7af38b92ebb3424223dbf773f5ccd27f84" + integrity sha512-CegDeryc2DVKnDkg5COQrE0bJfw/p0v3GBk2W5/Dj5dOVfEmb50Ux0GLnSPypooLnfqjwFaorGuT9FokWB3GRg== + dependencies: + "@ethereumjs/common" "^2.6.5" + "@ethereumjs/tx" "^3.5.2" + ethereumjs-util "^7.1.5" + merkle-patricia-tree "^4.2.4" + +"@ethereumjs/blockchain@^5.5.2": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.2.tgz#1848abd9dc1ee56acf8cec4c84304d7f4667d027" + integrity sha512-Jz26iJmmsQtngerW6r5BDFaew/f2mObLrRZo3rskLOx1lmtMZ8+TX/vJexmivrnWgmAsTdNWhlKUYY4thPhPig== + dependencies: + "@ethereumjs/block" "^3.6.2" + "@ethereumjs/common" "^2.6.3" + "@ethereumjs/ethash" "^1.1.0" + debug "^4.3.3" + ethereumjs-util "^7.1.4" + level-mem "^5.0.1" + lru-cache "^5.1.1" + semaphore-async-await "^1.5.1" + +"@ethereumjs/blockchain@^5.5.3": + version "5.5.3" + resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.3.tgz#aa49a6a04789da6b66b5bcbb0d0b98efc369f640" + integrity sha512-bi0wuNJ1gw4ByNCV56H0Z4Q7D+SxUbwyG12Wxzbvqc89PXLRNR20LBcSUZRKpN0+YCPo6m0XZL/JLio3B52LTw== + dependencies: + "@ethereumjs/block" "^3.6.2" + "@ethereumjs/common" "^2.6.4" + "@ethereumjs/ethash" "^1.1.0" + debug "^4.3.3" + ethereumjs-util "^7.1.5" + level-mem "^5.0.1" + lru-cache "^5.1.1" + semaphore-async-await "^1.5.1" + +"@ethereumjs/common@^2.6.3", "@ethereumjs/common@^2.6.4": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.4.tgz#1b3cdd3aa4ee3b0ca366756fc35e4a03022a01cc" + integrity sha512-RDJh/R/EAr+B7ZRg5LfJ0BIpf/1LydFgYdvZEuTraojCbVypO2sQ+QnpP5u2wJf9DASyooKqu8O4FJEWUV6NXw== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.4" + +"@ethereumjs/common@^2.6.5": + version "2.6.5" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" + integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.5" + +"@ethereumjs/ethash@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.1.0.tgz#7c5918ffcaa9cb9c1dc7d12f77ef038c11fb83fb" + integrity sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA== + dependencies: + "@ethereumjs/block" "^3.5.0" + "@types/levelup" "^4.3.0" + buffer-xor "^2.0.1" + ethereumjs-util "^7.1.1" + miller-rabin "^4.0.0" + +"@ethereumjs/tx@^3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.1.tgz#8d941b83a602b4a89949c879615f7ea9a90e6671" + integrity sha512-xzDrTiu4sqZXUcaBxJ4n4W5FrppwxLxZB4ZDGVLtxSQR4lVuOnFR6RcUHdg1mpUhAPVrmnzLJpxaeXnPxIyhWA== + dependencies: + "@ethereumjs/common" "^2.6.3" + ethereumjs-util "^7.1.4" + +"@ethereumjs/tx@^3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" + integrity sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw== + dependencies: + "@ethereumjs/common" "^2.6.4" + ethereumjs-util "^7.1.5" + +"@ethereumjs/vm@^5.9.0": + version "5.9.3" + resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.3.tgz#6d69202e4c132a4a1e1628ac246e92062e230823" + integrity sha512-Ha04TeF8goEglr8eL7hkkYyjhzdZS0PsoRURzYlTF6I0VVId5KjKb0N7MrA8GMgheN+UeTncfTgYx52D/WhEmg== + dependencies: + "@ethereumjs/block" "^3.6.3" + "@ethereumjs/blockchain" "^5.5.3" + "@ethereumjs/common" "^2.6.5" + "@ethereumjs/tx" "^3.5.2" + async-eventemitter "^0.2.4" + core-js-pure "^3.0.1" + debug "^4.3.3" + ethereumjs-util "^7.1.5" + functional-red-black-tree "^1.0.1" + mcl-wasm "^0.7.1" + merkle-patricia-tree "^4.2.4" + rustbn.js "~0.2.0" + +"@ethersproject/abi@5.6.3", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.6.3": + version "5.6.3" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.3.tgz#2d643544abadf6e6b63150508af43475985c23db" + integrity sha512-CxKTdoZY4zDJLWXG6HzNH6znWK0M79WzzxHegDoecE3+K32pzfHOzuXg2/oGSTecZynFgpkjYXNPOqXVJlqClw== + dependencies: + "@ethersproject/address" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/constants" "^5.6.1" + "@ethersproject/hash" "^5.6.1" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.1" + +"@ethersproject/abi@^5.1.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.2.tgz#f2956f2ac724cd720e581759d9e3840cd9744818" + integrity sha512-40Ixjhy+YzFtnvzIqFU13FW9hd1gMoLa3cJfSDnfnL4o8EnEG1qLiV8sNJo3sHYi9UYMfFeRuZ7kv5+vhzU7gQ== + dependencies: + "@ethersproject/address" "^5.6.0" + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/constants" "^5.6.0" + "@ethersproject/hash" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.0" + +"@ethersproject/abstract-provider@5.6.1", "@ethersproject/abstract-provider@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz#02ddce150785caf0c77fe036a0ebfcee61878c59" + integrity sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ== + dependencies: + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.3" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.2" + "@ethersproject/web" "^5.6.1" + +"@ethersproject/abstract-signer@5.6.2", "@ethersproject/abstract-signer@^5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz#491f07fc2cbd5da258f46ec539664713950b0b33" + integrity sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ== + dependencies: + "@ethersproject/abstract-provider" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/address@5.6.1", "@ethersproject/address@^5.6.0", "@ethersproject/address@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.1.tgz#ab57818d9aefee919c5721d28cd31fd95eff413d" + integrity sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q== + dependencies: + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/rlp" "^5.6.1" + +"@ethersproject/base64@5.6.1", "@ethersproject/base64@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.1.tgz#2c40d8a0310c9d1606c2c37ae3092634b41d87cb" + integrity sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw== + dependencies: + "@ethersproject/bytes" "^5.6.1" + +"@ethersproject/basex@5.6.1", "@ethersproject/basex@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.1.tgz#badbb2f1d4a6f52ce41c9064f01eab19cc4c5305" + integrity sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/properties" "^5.6.0" + +"@ethersproject/bignumber@5.6.2", "@ethersproject/bignumber@^5.6.0", "@ethersproject/bignumber@^5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.2.tgz#72a0717d6163fab44c47bcc82e0c550ac0315d66" + integrity sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.6.0", "@ethersproject/bytes@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" + integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/constants@5.6.1", "@ethersproject/constants@^5.6.0", "@ethersproject/constants@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.1.tgz#e2e974cac160dd101cf79fdf879d7d18e8cb1370" + integrity sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg== + dependencies: + "@ethersproject/bignumber" "^5.6.2" + +"@ethersproject/contracts@5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.2.tgz#20b52e69ebc1b74274ff8e3d4e508de971c287bc" + integrity sha512-hguUA57BIKi6WY0kHvZp6PwPlWF87MCeB4B7Z7AbUpTxfFXFdn/3b0GmjZPagIHS+3yhcBJDnuEfU4Xz+Ks/8g== + dependencies: + "@ethersproject/abi" "^5.6.3" + "@ethersproject/abstract-provider" "^5.6.1" + "@ethersproject/abstract-signer" "^5.6.2" + "@ethersproject/address" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/constants" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/transactions" "^5.6.2" + +"@ethersproject/hash@5.6.1", "@ethersproject/hash@^5.6.0", "@ethersproject/hash@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.1.tgz#224572ea4de257f05b4abf8ae58b03a67e99b0f4" + integrity sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA== + dependencies: + "@ethersproject/abstract-signer" "^5.6.2" + "@ethersproject/address" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.1" + +"@ethersproject/hdnode@5.6.2", "@ethersproject/hdnode@^5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.2.tgz#26f3c83a3e8f1b7985c15d1db50dc2903418b2d2" + integrity sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q== + dependencies: + "@ethersproject/abstract-signer" "^5.6.2" + "@ethersproject/basex" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.1" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/sha2" "^5.6.1" + "@ethersproject/signing-key" "^5.6.2" + "@ethersproject/strings" "^5.6.1" + "@ethersproject/transactions" "^5.6.2" + "@ethersproject/wordlists" "^5.6.1" + +"@ethersproject/json-wallets@5.6.1", "@ethersproject/json-wallets@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.1.tgz#3f06ba555c9c0d7da46756a12ac53483fe18dd91" + integrity sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ== + dependencies: + "@ethersproject/abstract-signer" "^5.6.2" + "@ethersproject/address" "^5.6.1" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/hdnode" "^5.6.2" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/pbkdf2" "^5.6.1" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.1" + "@ethersproject/strings" "^5.6.1" + "@ethersproject/transactions" "^5.6.2" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.6.1", "@ethersproject/keccak256@^5.6.0", "@ethersproject/keccak256@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.1.tgz#b867167c9b50ba1b1a92bccdd4f2d6bd168a91cc" + integrity sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA== + dependencies: + "@ethersproject/bytes" "^5.6.1" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.6.0", "@ethersproject/logger@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" + integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== + +"@ethersproject/networks@5.6.3", "@ethersproject/networks@^5.6.3": + version "5.6.3" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.3.tgz#3ee3ab08f315b433b50c99702eb32e0cf31f899f" + integrity sha512-QZxRH7cA5Ut9TbXwZFiCyuPchdWi87ZtVNHWZd0R6YFgYtes2jQ3+bsslJ0WdyDe0i6QumqtoYqvY3rrQFRZOQ== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/pbkdf2@5.6.1", "@ethersproject/pbkdf2@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.1.tgz#f462fe320b22c0d6b1d72a9920a3963b09eb82d1" + integrity sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/sha2" "^5.6.1" + +"@ethersproject/properties@5.6.0", "@ethersproject/properties@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" + integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== + dependencies: + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/providers@5.6.8": + version "5.6.8" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.8.tgz#22e6c57be215ba5545d3a46cf759d265bb4e879d" + integrity sha512-Wf+CseT/iOJjrGtAOf3ck9zS7AgPmr2fZ3N97r4+YXN3mBePTG2/bJ8DApl9mVwYL+RpYbNxMEkEp4mPGdwG/w== + dependencies: + "@ethersproject/abstract-provider" "^5.6.1" + "@ethersproject/abstract-signer" "^5.6.2" + "@ethersproject/address" "^5.6.1" + "@ethersproject/base64" "^5.6.1" + "@ethersproject/basex" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/constants" "^5.6.1" + "@ethersproject/hash" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/networks" "^5.6.3" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.1" + "@ethersproject/rlp" "^5.6.1" + "@ethersproject/sha2" "^5.6.1" + "@ethersproject/strings" "^5.6.1" + "@ethersproject/transactions" "^5.6.2" + "@ethersproject/web" "^5.6.1" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.6.1", "@ethersproject/random@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.1.tgz#66915943981bcd3e11bbd43733f5c3ba5a790255" + integrity sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/rlp@5.6.1", "@ethersproject/rlp@^5.5.0", "@ethersproject/rlp@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.1.tgz#df8311e6f9f24dcb03d59a2bac457a28a4fe2bd8" + integrity sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/sha2@5.6.1", "@ethersproject/sha2@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.1.tgz#211f14d3f5da5301c8972a8827770b6fd3e51656" + integrity sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.6.2", "@ethersproject/signing-key@^5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.2.tgz#8a51b111e4d62e5a62aee1da1e088d12de0614a3" + integrity sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.1.tgz#5845e71182c66d32e6ec5eefd041fca091a473e2" + integrity sha512-KWqVLkUUoLBfL1iwdzUVlkNqAUIFMpbbeH0rgCfKmJp0vFtY4AsaN91gHKo9ZZLkC4UOm3cI3BmMV4N53BOq4g== + dependencies: + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2" "^5.6.1" + "@ethersproject/strings" "^5.6.1" + +"@ethersproject/strings@5.6.1", "@ethersproject/strings@^5.6.0", "@ethersproject/strings@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.1.tgz#dbc1b7f901db822b5cafd4ebf01ca93c373f8952" + integrity sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/constants" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/transactions@5.6.2", "@ethersproject/transactions@^5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.2.tgz#793a774c01ced9fe7073985bb95a4b4e57a6370b" + integrity sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q== + dependencies: + "@ethersproject/address" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/constants" "^5.6.1" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/rlp" "^5.6.1" + "@ethersproject/signing-key" "^5.6.2" + +"@ethersproject/units@5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.1.tgz#ecc590d16d37c8f9ef4e89e2005bda7ddc6a4e6f" + integrity sha512-rEfSEvMQ7obcx3KWD5EWWx77gqv54K6BKiZzKxkQJqtpriVsICrktIQmKl8ReNToPeIYPnFHpXvKpi068YFZXw== + dependencies: + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/constants" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + +"@ethersproject/wallet@5.6.2": + version "5.6.2" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.2.tgz#cd61429d1e934681e413f4bc847a5f2f87e3a03c" + integrity sha512-lrgh0FDQPuOnHcF80Q3gHYsSUODp6aJLAdDmDV0xKCN/T7D99ta1jGVhulg3PY8wiXEngD0DfM0I2XKXlrqJfg== + dependencies: + "@ethersproject/abstract-provider" "^5.6.1" + "@ethersproject/abstract-signer" "^5.6.2" + "@ethersproject/address" "^5.6.1" + "@ethersproject/bignumber" "^5.6.2" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/hash" "^5.6.1" + "@ethersproject/hdnode" "^5.6.2" + "@ethersproject/json-wallets" "^5.6.1" + "@ethersproject/keccak256" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/random" "^5.6.1" + "@ethersproject/signing-key" "^5.6.2" + "@ethersproject/transactions" "^5.6.2" + "@ethersproject/wordlists" "^5.6.1" + +"@ethersproject/web@5.6.1", "@ethersproject/web@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.1.tgz#6e2bd3ebadd033e6fe57d072db2b69ad2c9bdf5d" + integrity sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA== + dependencies: + "@ethersproject/base64" "^5.6.1" + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.1" + +"@ethersproject/wordlists@5.6.1", "@ethersproject/wordlists@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.1.tgz#1e78e2740a8a21e9e99947e47979d72e130aeda1" + integrity sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw== + dependencies: + "@ethersproject/bytes" "^5.6.1" + "@ethersproject/hash" "^5.6.1" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/properties" "^5.6.0" + "@ethersproject/strings" "^5.6.1" + +"@joriksch/oz-cairo@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@joriksch/oz-cairo/-/oz-cairo-1.0.1.tgz#660d7fc9ccfb78d4a77354ff8a43150cc6a14899" + integrity sha512-UhDE9gCiUKtz2ryrr9a8hA24ivFdBy5cdlI4BcmRmhpRChCdfaPjI6w2xdiDwxCh/ZhC/Ij9EnG1CMLqOd5g0w== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" + integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.13" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" + integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@ledgerhq/cryptoassets@^6.28.2": + version "6.28.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/cryptoassets/-/cryptoassets-6.28.2.tgz#fabc77c46830348d121452976cdcc19908e0acb2" + integrity sha512-i+33VVNE+54HrC0mHly6JXWO6Th+/7n7vNpxjhUQq+1IL3K/ex1HUCwB61O/siDInjq7OZ1Roq9CEx7tAsED2Q== + dependencies: + invariant "2" + +"@ledgerhq/devices@^6.27.1": + version "6.27.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-6.27.1.tgz#3b13ab1d1ba8201e9e74a08f390560483978c962" + integrity sha512-jX++oy89jtv7Dp2X6gwt3MMkoajel80JFWcdc0HCouwDsV1mVJ3SQdwl/bQU0zd8HI6KebvUP95QTwbQLLK/RQ== + dependencies: + "@ledgerhq/errors" "^6.10.0" + "@ledgerhq/logs" "^6.10.0" + rxjs "6" + semver "^7.3.5" + +"@ledgerhq/errors@^6.10.0": + version "6.10.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.10.0.tgz#dda9127b65f653fbb2f74a55e8f0e550d69de6e4" + integrity sha512-fQFnl2VIXh9Yd41lGjReCeK+Q2hwxQJvLZfqHnKqWapTz68NHOv5QcI0OHuZVNEbv0xhgdLhi5b65kgYeQSUVg== + +"@ledgerhq/hw-app-eth@^6.26.0": + version "6.28.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-6.28.2.tgz#06fd19b9277442f4eb58ed76f4bc8299acd15a81" + integrity sha512-/pGJW5QKsci5mkjcUeP8RvDw4sV9gldp7RWKTKlkldqeRh2kV75bAdStL2p99fGdDfGkfYotpTfm3oOXQpOwiQ== + dependencies: + "@ethersproject/abi" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + "@ledgerhq/cryptoassets" "^6.28.2" + "@ledgerhq/errors" "^6.10.0" + "@ledgerhq/hw-transport" "^6.27.1" + "@ledgerhq/logs" "^6.10.0" + axios "^0.26.1" + bignumber.js "^9.0.2" + +"@ledgerhq/hw-transport-webhid@^6.24.1": + version "6.27.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.27.1.tgz#8fd1710d23b6bd7cbe2382dd02054dfabe788447" + integrity sha512-u74rBYlibpbyGblSn74fRs2pMM19gEAkYhfVibq0RE1GNFjxDMFC1n7Sb+93Jqmz8flyfB4UFJsxs8/l1tm2Kw== + dependencies: + "@ledgerhq/devices" "^6.27.1" + "@ledgerhq/errors" "^6.10.0" + "@ledgerhq/hw-transport" "^6.27.1" + "@ledgerhq/logs" "^6.10.0" + +"@ledgerhq/hw-transport@^6.24.1", "@ledgerhq/hw-transport@^6.27.1": + version "6.27.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.27.1.tgz#88072278f69c279cb6569352acd4ae2fec33ace3" + integrity sha512-hnE4/Fq1YzQI4PA1W0H8tCkI99R3UWDb3pJeZd6/Xs4Qw/q1uiQO+vNLC6KIPPhK0IajUfuI/P2jk0qWcMsuAQ== + dependencies: + "@ledgerhq/devices" "^6.27.1" + "@ledgerhq/errors" "^6.10.0" + events "^3.3.0" + +"@ledgerhq/logs@^6.10.0": + version "6.10.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-6.10.0.tgz#c012c1ecc1a0e53d50e6af381618dca5268461c1" + integrity sha512-lLseUPEhSFUXYTKj6q7s2O3s2vW2ebgA11vMAlKodXGf5AFw4zUoEbTz9CoFOC9jS6xY4Qr8BmRnxP/odT4Uuw== + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@noble/hashes@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.1.tgz#c056d9b7166c1e7387a7453c2aff199bf7d88e5f" + integrity sha512-Lkp9+NijmV7eSVZqiUvt3UCuuHeJpUVmRrvh430gyJjJiuJMqkeHf6/A9lQ/smmbWV/0spDeJscscPzyB4waZg== + +"@noble/hashes@^0.5.7": + version "0.5.9" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-0.5.9.tgz#9f3051a4cc6f7c168022b3b7fbbe9fe2a35cccf0" + integrity sha512-7lN1Qh6d8DUGmfN36XRsbN/WcGIPNtTGhkw26vWId/DlCIGsYJJootTtPGghTLcn/AaXPx2Q0b3cacrwXa7OVw== + +"@noble/hashes@~1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" + integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== + +"@noble/secp256k1@1.6.0", "@noble/secp256k1@~1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.0.tgz#602afbbfcfb7e169210469b697365ef740d7e930" + integrity sha512-DWSsg8zMHOYMYBqIQi96BQuthZrp98LCeMNcUOaffCIVYQ5yxDbNikLF+H7jEnmNNmXbtVic46iCuVWzar+MgA== + +"@noble/secp256k1@^1.4.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.5.5.tgz#315ab5745509d1a8c8e90d0bdf59823ccf9bcfc3" + integrity sha512-sZ1W6gQzYnu45wPrWx8D3kwI2/U29VYTx9OjbDAd7jwRItJ0cSTMPRL/C8AWZFn9kWFLQGqEXVEE86w4Z8LpIQ== + +"@nomiclabs/hardhat-docker@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" + integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== + dependencies: + dockerode "^2.5.8" + fs-extra "^7.0.1" + node-fetch "^2.6.0" + +"@nomiclabs/hardhat-ethers@^2.0.5": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.6.tgz#1c695263d5b46a375dcda48c248c4fba9dfe2fc2" + integrity sha512-q2Cjp20IB48rEn2NPjR1qxsIQBvFVYW9rFRCFq+bC4RUrn1Ljz3g4wM8uSlgIBZYBi2JMXxmOzFqHraczxq4Ng== + +"@scure/base@~1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.0.tgz#dea45875e7fbc720c2b4560325f1cf5d2246d95b" + integrity sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q== + dependencies: + "@noble/hashes" "~1.1.1" + "@noble/secp256k1" "~1.6.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" + integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== + dependencies: + "@noble/hashes" "~1.1.1" + "@scure/base" "~1.1.0" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@shardlabs/starknet-hardhat-plugin@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@shardlabs/starknet-hardhat-plugin/-/starknet-hardhat-plugin-0.6.0.tgz#94fd4ba5f7e788474ad55a5b21b7acc23b104ed6" + integrity sha512-rqKZqfE9uOLTMxQ44pZLVs3eAm1ylxjQGVZuHvTR292N8KwHl7IaSd2k9yORaUobFdpHxt5LQoxFPlO8+pjCoQ== + dependencies: + "@nomiclabs/hardhat-docker" "^2.0.2" + axios "^0.24.0" + exit-hook "2.2.1" + form-data "^4.0.0" + glob "^7.2.0" + is-wsl "^2.2.0" + starknet "^3.15.0" + +"@solidity-parser/parser@^0.14.2": + version "0.14.2" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.2.tgz#2d8f2bddb217621df882ceeae7d7b42ae8664db3" + integrity sha512-10cr0s+MtRtqjEw0WFJrm2rwULN30xx7btd/v9cmqME2617/2M5MbHDkFIGIGTa7lwNw4bN9mVGfhlLzrYw8pA== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@toruslabs/starkware-crypto@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@toruslabs/starkware-crypto/-/starkware-crypto-1.1.0.tgz#754da7f0d6529de619ded73bd7636372d3da4b5d" + integrity sha512-IWqri38bd6kIlj7GDhxLby2Sw9LKJ+ShbfbKUPl0CAuv2QLOjGFFL17o9m7s2CUIZ9IMmz1a+yDT9uEfQvNRKg== + dependencies: + assert "^2.0.0" + bip39 "^3.0.4" + bn.js "^5.2.0" + elliptic "~6.5.4" + enc-utils "^3.0.0" + ethereumjs-wallet "^1.0.2" + hash.js "^1.1.7" + +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + +"@types/abstract-leveldown@*": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#f055979a99f7654e84d6b8e6267419e9c4cfff87" + integrity sha512-q5veSX6zjUy/DlDhR4Y4cU0k2Ar+DT2LUraP00T19WLmTO6Se1djepCCaqU6nQrwcJ5Hyo/CWqxTzrrFg8eqbQ== + +"@types/bn.js@*", "@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + +"@types/bn.js@^4.11.3": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/chai@^4.2.22": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04" + integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ== + +"@types/elliptic@^6.4.14": + version "6.4.14" + resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.14.tgz#7bbaad60567a588c1f08b10893453e6b9b4de48e" + integrity sha512-z4OBcDAU0GVwDTuwJzQCiL6188QvZMkvoERgcVjq0/mPM8jCfdwZ3x5zQEVoL9WCAru3aG5wl3Z5Ww5wBWn7ZQ== + dependencies: + "@types/bn.js" "*" + +"@types/level-errors@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/level-errors/-/level-errors-3.0.0.tgz#15c1f4915a5ef763b51651b15e90f6dc081b96a8" + integrity sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ== + +"@types/levelup@^4.3.0": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-4.3.3.tgz#4dc2b77db079b1cf855562ad52321aa4241b8ef4" + integrity sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA== + dependencies: + "@types/abstract-leveldown" "*" + "@types/level-errors" "*" + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/mocha@^9.0.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + +"@types/node@*": + version "17.0.34" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.34.tgz#3b0b6a50ff797280b8d000c6281d229f9c538cef" + integrity sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA== + +"@types/node@11.11.6": + version "11.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" + integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== + +"@types/node@^16.11.10": + version "16.11.38" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.38.tgz#be0edd097b23eace6c471c525a74b3f98803017f" + integrity sha512-hjO/0K140An3GWDw2HJfq7gko3wWeznbjXgg+rzPdVzhe198hp4x2i1dgveAOEiFKd8sOilAxzoSJiVv5P/CUg== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +JSONStream@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" + integrity sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-leveldown@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a" + integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +abstract-leveldown@~6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb" + integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +aes-js@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +assert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" + integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== + dependencies: + es6-object-assign "^1.1.0" + is-nan "^1.2.1" + object-is "^1.0.1" + util "^0.12.0" + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +async-eventemitter@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async@^2.4.0: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +axios@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.23.0.tgz#b0fa5d0948a8d1d75e3d5635238b6c4625b05149" + integrity sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg== + dependencies: + follow-redirects "^1.14.4" + +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + +axios@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bignumber.js@^9.0.0, bignumber.js@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" + integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bip39@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.4.tgz#5b11fed966840b5e1b8539f0f54ab6392969b2a0" + integrity sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw== + dependencies: + "@types/node" "11.11.6" + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bluebird@^3.5.0: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@^4.0.0, bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cairo-ls@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/cairo-ls/-/cairo-ls-0.0.4.tgz#42c4eae4c1eac65eed32fe66896fcc44531ddffc" + integrity sha512-n/dWpvbt0g2ioQZJAneCgFe0kxMo6LncSF/GwdjffbjRJC/gCCGrYNPoa3OgKCoLwGBny+DwXiJhJY5UPV5pdw== + dependencies: + file-uri-to-path "^2.0.0" + glob "^7.2.0" + index-of-regex "^1.0.0" + request-promise "4.2.5" + vscode-languageserver "^6.1.1" + vscode-languageserver-textdocument "^1.0.1" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chai@^4.3.4: + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chokidar@3.5.3, chokidar@^3.4.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.0.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +core-js-pure@^3.0.1: + version "3.22.5" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.5.tgz#bdee0ed2f9b78f2862cda4338a07b13a49b6c9a9" + integrity sha512-8xo9R00iYD7TcV7OrC98GwxiUEAabVWO3dix+uyWjnYrx9fyASLlIX+f/3p5dW5qByaP2bcZ8X/T47s55et/tA== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deferred-leveldown@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058" + integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw== + dependencies: + abstract-leveldown "~6.2.1" + inherits "^2.0.3" + +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +docker-modem@^1.0.8: + version "1.0.9" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-1.0.9.tgz#a1f13e50e6afb6cf3431b2d5e7aac589db6aaba8" + integrity sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw== + dependencies: + JSONStream "1.3.2" + debug "^3.2.6" + readable-stream "~1.0.26-4" + split-ca "^1.0.0" + +dockerode@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-2.5.8.tgz#1b661e36e1e4f860e25f56e0deabe9f87f1d0acc" + integrity sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw== + dependencies: + concat-stream "~1.6.2" + docker-modem "^1.0.8" + tar-fs "~1.16.3" + +elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4, elliptic@~6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enc-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/enc-utils/-/enc-utils-3.0.0.tgz#65935d2d6a867fa0ae995f05f3a2f055ce764dcf" + integrity sha512-e57t/Z2HzWOLwOp7DZcV0VMEY8t7ptWwsxyp6kM2b2zrk6JqIpXxzkruHAMiBsy5wg9jp/183GdiRXCvBtzsYg== + dependencies: + is-typedarray "1.0.0" + typedarray-to-buffer "3.1.5" + +encoding-down@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" + integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw== + dependencies: + abstract-leveldown "^6.2.1" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.0: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +es-abstract@^1.19.0, es-abstract@^1.19.5, es-abstract@^1.20.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" + integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + regexp.prototype.flags "^1.4.3" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-object-assign@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" + integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-cryptography@^0.2.0: + version "0.2.5" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.2.5.tgz#dfa636f0fa1978d962a13362d0850befb9ab8e7e" + integrity sha512-aWvqiegXgSTwbuDE1DDnM7taLteLcHVHh5nMZnnD2dwlvH6w5bOxcdXW20oS+1aLDorDlrK1c82stB8jsLDN5Q== + dependencies: + "@noble/hashes" "^0.5.7" + "@noble/secp256k1" "^1.4.0" + micro-base "^0.10.1" + +ethereum-cryptography@^1.0.3: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.1.0.tgz#7048d184ff365a5255ced5cc9eb7682a273c4db7" + integrity sha512-wyNVTBR4wIR2yoXdMv4Qt44mTVBpPgSW/DQCTmNO6nQluwpyrAIvmL4mxPbziFuc6VWJQa3rwUxn0nUFU03nyQ== + dependencies: + "@noble/hashes" "1.1.1" + "@noble/secp256k1" "1.6.0" + "@scure/bip32" "1.1.0" + "@scure/bip39" "1.1.0" + +ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458" + integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-util@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-wallet@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz#2c000504b4c71e8f3782dabe1113d192522e99b6" + integrity sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA== + dependencies: + aes-js "^3.1.2" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^7.1.2" + randombytes "^2.1.0" + scrypt-js "^3.0.1" + utf8 "^3.0.0" + uuid "^8.3.2" + +ethers@^5.4.6: + version "5.6.8" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.8.tgz#d36b816b4896341a80a8bbd2a44e8cb6e9b98dd4" + integrity sha512-YxIGaltAOdvBFPZwIkyHnXbW40f1r8mHUgapW6dxkO+6t7H6wY8POUn0Kbxrd/N7I4hHxyi7YCddMAH/wmho2w== + dependencies: + "@ethersproject/abi" "5.6.3" + "@ethersproject/abstract-provider" "5.6.1" + "@ethersproject/abstract-signer" "5.6.2" + "@ethersproject/address" "5.6.1" + "@ethersproject/base64" "5.6.1" + "@ethersproject/basex" "5.6.1" + "@ethersproject/bignumber" "5.6.2" + "@ethersproject/bytes" "5.6.1" + "@ethersproject/constants" "5.6.1" + "@ethersproject/contracts" "5.6.2" + "@ethersproject/hash" "5.6.1" + "@ethersproject/hdnode" "5.6.2" + "@ethersproject/json-wallets" "5.6.1" + "@ethersproject/keccak256" "5.6.1" + "@ethersproject/logger" "5.6.0" + "@ethersproject/networks" "5.6.3" + "@ethersproject/pbkdf2" "5.6.1" + "@ethersproject/properties" "5.6.0" + "@ethersproject/providers" "5.6.8" + "@ethersproject/random" "5.6.1" + "@ethersproject/rlp" "5.6.1" + "@ethersproject/sha2" "5.6.1" + "@ethersproject/signing-key" "5.6.2" + "@ethersproject/solidity" "5.6.1" + "@ethersproject/strings" "5.6.1" + "@ethersproject/transactions" "5.6.2" + "@ethersproject/units" "5.6.1" + "@ethersproject/wallet" "5.6.2" + "@ethersproject/web" "5.6.1" + "@ethersproject/wordlists" "5.6.1" + +ethjs-util@0.1.6, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +exit-hook@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.1.tgz#007b2d92c6428eda2b76e7016a34351586934593" + integrity sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw== + +fetch-intercept@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/fetch-intercept/-/fetch-intercept-2.4.0.tgz#be8b0f17abaadeea6de52ecdb6e9ed081f03480a" + integrity sha512-BPZ2LM9Dh1ua2ovQf03N6rhWg1qxdVD5qK/G4llvcemt6M+jjxCuIDxJ+6IiG+uz//3UQmgfKEv0gOGvYIxZ7g== + +file-uri-to-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba" + integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +follow-redirects@^1.12.1: + version "1.15.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4" + integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== + +follow-redirects@^1.14.4, follow-redirects@^1.14.8: + version "1.15.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3, glob@^7.2.0: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +hardhat@^2.9.9: + version "2.10.0" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.10.0.tgz#23a640293d52ce79388660b2872624b2c6f94e5d" + integrity sha512-9VUorKvWNyW96qFXkwkpDUSeWND3gOZpm0oJ8l63JQJvWhxyxTJ92BcOrNylOKy9hzNNGdMfM2QWNP80fGOjpA== + dependencies: + "@ethereumjs/block" "^3.6.2" + "@ethereumjs/blockchain" "^5.5.2" + "@ethereumjs/common" "^2.6.4" + "@ethereumjs/tx" "^3.5.1" + "@ethereumjs/vm" "^5.9.0" + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@sentry/node" "^5.18.1" + "@solidity-parser/parser" "^0.14.2" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + ethereumjs-util "^7.1.4" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + lodash "^4.17.11" + merkle-patricia-tree "^4.2.4" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + qs "^6.7.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + slash "^3.0.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + "true-case-path" "^2.2.1" + tsort "0.0.1" + undici "^5.4.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= + +immutable@^4.0.0-rc.12: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +index-of-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/index-of-regex/-/index-of-regex-1.0.0.tgz#3a7637b4e27665f6673a4751a20b01477ffbd3ec" + integrity sha1-OnY3tOJ2ZfZnOkdRogsBR3/70+w= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= + +is-nan@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.3, is-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" + integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.20.0" + for-each "^0.3.3" + has-tostringtag "^1.0.0" + +is-typedarray@1.0.0, is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + +keccak@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-concat-iterator@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" + integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw== + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-iterator-stream@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c" + integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q== + dependencies: + inherits "^2.0.4" + readable-stream "^3.4.0" + xtend "^4.0.2" + +level-mem@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-5.0.1.tgz#c345126b74f5b8aa376dc77d36813a177ef8251d" + integrity sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg== + dependencies: + level-packager "^5.0.3" + memdown "^5.0.0" + +level-packager@^5.0.3: + version "5.1.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939" + integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ== + dependencies: + encoding-down "^6.3.0" + levelup "^4.3.2" + +level-supports@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" + integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg== + dependencies: + xtend "^4.0.2" + +level-ws@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-2.0.0.tgz#207a07bcd0164a0ec5d62c304b4615c54436d339" + integrity sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA== + dependencies: + inherits "^2.0.3" + readable-stream "^3.1.0" + xtend "^4.0.1" + +levelup@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" + integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ== + dependencies: + deferred-leveldown "~5.3.0" + level-errors "~2.0.0" + level-iterator-stream "~4.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= + +ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +memdown@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-5.1.0.tgz#608e91a9f10f37f5b5fe767667a8674129a833cb" + integrity sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw== + dependencies: + abstract-leveldown "~6.2.1" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.2.0" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + +merkle-patricia-tree@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.4.tgz#ff988d045e2bf3dfa2239f7fabe2d59618d57413" + integrity sha512-eHbf/BG6eGNsqqfbLED9rIqbsF4+sykEaBn6OLNs71tjclbMcMOk1tEPmJKcNcNCLkvbpY/lwyOlizWsqPNo8w== + dependencies: + "@types/levelup" "^4.3.0" + ethereumjs-util "^7.1.4" + level-mem "^5.0.1" + level-ws "^2.0.0" + readable-stream "^3.6.0" + semaphore-async-await "^1.5.1" + +micro-base@^0.10.1: + version "0.10.2" + resolved "https://registry.yarnpkg.com/micro-base/-/micro-base-0.10.2.tgz#f6f9f0bd949ce511883e5a99f9147d80ddc32f5a" + integrity sha512-lqqJrT7lfJtDmmiQ4zRLZuIJBk96t0RAc5pCrrWpL9zDeH5i/SUL85mku9HqzTI/OCZ8EQ3aicbMW+eK5Nyu5w== + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9" + integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-fetch@2.6.7, node-fetch@^2.6.0: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-gyp-build@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" + integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +object-inspect@^1.12.0, object-inspect@^1.9.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +pako@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d" + integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17, pbkdf2@^3.0.9: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@^6.7.0: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + +randombytes@^2.0.1, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +raw-body@^2.4.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.0, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.26-4: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +request-promise-core@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" + integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== + dependencies: + lodash "^4.17.15" + +request-promise@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.5.tgz#186222c59ae512f3497dfe4d75a9c8461bd0053c" + integrity sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg== + dependencies: + bluebird "^3.5.0" + request-promise-core "1.1.3" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +rimraf@^2.2.8: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +rxjs@6: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +semaphore-async-await@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz#857bef5e3644601ca4b9570b87e9df5ca12974fa" + integrity sha1-hXvvXjZEYBykuVcLh+nfXKEpdPo= + +semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.5: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split-ca@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha1-bIOv82kvphJW4M0ZfgXp3hV2kaY= + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +starknet@3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/starknet/-/starknet-3.9.0.tgz#ee7a3d99effef0998b365d95dd85f9b01cdb463c" + integrity sha512-/sn3WHFX7f+A3vVf3I+Kamg2KIW6494vpCcZWA09IQ5RZXrozjaBtYWT41SoKKWZ3b0Xg8WF//SOkRVCTZOZkQ== + dependencies: + "@ledgerhq/hw-app-eth" "^6.26.0" + "@ledgerhq/hw-transport" "^6.24.1" + "@ledgerhq/hw-transport-webhid" "^6.24.1" + axios "^0.23.0" + bn.js "^5.2.0" + elliptic "^6.5.4" + ethereum-cryptography "^0.2.0" + hash.js "^1.1.7" + json-bigint "^1.0.0" + minimalistic-assert "^1.0.1" + pako "^2.0.4" + superstruct "^0.15.3" + url-join "^4.0.1" + +starknet@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/starknet/-/starknet-3.15.0.tgz#3f9ab20c6d6a094b33272f971f01fc5fa9b92c2a" + integrity sha512-+wqAHky7ffTpyJGGSLkzVt8c2FrMyu/8R1cAB3n++VyuBuTTS9+qD8SLXhXWJiBxCzlznP8KkdWQC9N0SCTokw== + dependencies: + "@ethersproject/bytes" "^5.6.1" + bn.js "^5.2.1" + cross-fetch "^3.1.5" + elliptic "^6.5.4" + ethereum-cryptography "^1.0.3" + fetch-intercept "^2.4.0" + hash.js "^1.1.7" + json-bigint "^1.0.0" + minimalistic-assert "^1.0.1" + pako "^2.0.4" + url-join "^4.0.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +superstruct@^0.15.3: + version "0.15.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.4.tgz#e3381dd84ca07e704e19f69eda74eee1a5efb1f9" + integrity sha512-eOoMeSbP9ZJChNOm/9RYjE+F36rYR966AAqeG3xhQB02j2sfAUXDp4EQ/7bAOqnlJnuFDB8yvOu50SocvKpUEw== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tar-fs@~1.16.3: + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" + integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-stream@^1.1.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@^2.3.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +"true-case-path@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-2.2.1.tgz#c5bf04a5bbec3fd118be4084461b3a27c4d796bf" + integrity sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q== + +ts-node@^10.4.0: + version "10.8.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.8.0.tgz#3ceb5ac3e67ae8025c1950626aafbdecb55d82ce" + integrity sha512-/fNd5Qh+zTt8Vt1KbYZjRHCE9sI5i7nqfD/dzBBRDeVXZXS6kToW6R7tTU6Nd4XavFs0mAVCg29Q//ML7WsZYA== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^1.9.0, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y= + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +typedarray-to-buffer@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^4.5.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4" + integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undici@^5.4.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.6.0.tgz#3fd695d4454970bae3d151326ee4ab645b8d1962" + integrity sha512-mc+8SY1fXubTrdx4CXDkeFFGV8lI3Tq4I/70U1V8Z6g4iscGII0uLO7CPnDt56bXEbvaKwo2T2+VrteWbZiXiQ== + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util@^0.12.0: + version "0.12.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" + integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +vscode-jsonrpc@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz#f30b0625ebafa0fb3bc53e934ca47b706445e57e" + integrity sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ== + +vscode-languageserver-protocol@^3.15.3: + version "3.17.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz#e801762c304f740208b6c804a0cf21f2c87509ed" + integrity sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg== + dependencies: + vscode-jsonrpc "8.0.1" + vscode-languageserver-types "3.17.1" + +vscode-languageserver-textdocument@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.4.tgz#3cd56dd14cec1d09e86c4bb04b09a246cb3df157" + integrity sha512-/xhqXP/2A2RSs+J8JNXpiiNVvvNM0oTosNVmQnunlKvq9o4mupHOBAnnzH0lwIPKazXKvAKsVp1kr+H/K4lgoQ== + +vscode-languageserver-types@3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz#c2d87fa7784f8cac389deb3ff1e2d9a7bef07e16" + integrity sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ== + +vscode-languageserver@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz#d76afc68172c27d4327ee74332b468fbc740d762" + integrity sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ== + dependencies: + vscode-languageserver-protocol "^3.15.3" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-typed-array@^1.1.2: + version "1.1.8" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" + integrity sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.20.0" + for-each "^0.3.3" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.9" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^7.4.6: + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..efce7f6 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,16 @@ +# Plugin Starknet Documentation + +This repository is a monorepo of the various components required for Plugin on Starknet. + +- [Contracts](../contracts) + +- [Gauntlet & TS toolchain](../packages-ts) + +- [Ops](../ops) +- [Integration Tests](../integration-tests) +- [Demos & Examples](../examples) + +Additional documentation can be found in this directory. + +- [Getting Started](./getting-started.md) +- [L2 Emergency Protocol](./emergency-protocol/) diff --git a/docs/assets/godepgraph_starknet_relayer.png b/docs/assets/godepgraph_starknet_relayer.png new file mode 100644 index 0000000000000000000000000000000000000000..9d60c82a7a6cb198830ad536b24120140835b1ba GIT binary patch literal 76856 zcmeFZcT|(x*EJgT2zZbp2q*}Miik9&O80<(NE7K@q}NCZEf7>t1O%ibRjE=#?+}$v zsM2es212i)h1?y^?;ZF1#(nP?cYOEXH)ou2fal3m_Fj9fx#pbv1V2|-qWYWpZwLfJ zrTp~C3kc-W9SGzvPKxv3FZZQdPr!f3Ua2TOfe=amd~L{yhCpsYl%M>g?UlSb=f=2}<&QP9q;hQ4g69j3YhcN)rzowj!>l(mN%6~byp>??-v>lO}~ zUi?}6?c>MuMKSkPhW@^F(<-PqXtm?yG{J#6y6f}h&u=#mrDSBHJC0L#q|wQr@k#jl zNG~Zi@F?K(CL7)9{_l^F;<6~m3;+IASh@1t*-wuXONCe=kmnh(|38Jteu#fa_l$(otIH7ZfyY@8CmP1X-!UsdfAv zqLB8??xCTwkWf86ZA%H-H!1o#`m38KzHk*Vrk}4wIYB-@%;(`D>S}8*1U>vQ92`g+ z_9XoNy`>nZG+%Iy#3V}=h-E92l~q}2Xn^1CbCvI#qbI1*y%;euv8Hd}jN;Ie{=XrX zKccp`4O&`UzKFhYx>J(gbD!Vzg=y-tJ~(5v;%Vi%$8JVuIwBd>j|Ma$<*GsZjAkfQRi6>?bf-p zxESy=_rMX`!#fj@ zuU}$(3|SuU+~4UU-MLa0OpWc`A)|Ol9z)dWct%93l)W|qT4+$|IOtEr>-Zh(#>9#= z{%CQ-%J>YZiKV)B4nL{rCY+MXj#gW%WoL|v7Z}yJcA0pZ_>G!#Dk$usl3x89j7x7C zNYV={sLCtdCb-Nw%WTxgD}_7$4$d`dFcC2t%9Xun#NNs;vZQm`2?qDgnno!V#Dltj zbybvAVxHmZV7-=`h;PfU_i5@$y4CJ>_1y8XdVGe$Zoe~G@0aPA8XA@({3gO#lWL~# zE-(n1da1qTVd6^^@;kz{gtAESwgl!z){-7!Z^fxE(F#4xZ+04ytHp!z&D6cEp*n?Y zRk1Lx)EUZc8lBB~$>&C$EbMu{d?6GCkGZiGIfh7InH%_rY5X%OKy`c ze&OQTxfl1@rK;P^gPhQ`RpaFJTnMMlKa0q!Y%b4`Uk-muZMNU0k=Y-$49ZG)Ao9Y~ z%V#GK(Lgnx0mst|)ISKL*Q%=B`h6|lNe6~|P z1bSGnq2&Sd4)}W0JkHD5WZAE~@Kv zVJ*|%r-xoJm@qgc*-egOqha@jj)H=^>9nRz>X%0{bYKNrH*U4IZ8T2I^~py_;wLTN za-P?hvQghScY&H+_#T%4a*?1h4d00N#HSeu!`bpd&G8^!L@j=2 zPSv>wTUt?__IUoj_xkYUkiGHrXpxGAdI>}Pi1e4WA+Lajv^mb*t5jF)5%R_E>$Tv-bT_(%;k1`w z;tv(_Z=3Oz{j3>$2^F@kOcwI>3dy4<7n}S|8zSc9gFnQ^ccs)}8;_}L=cDR}3#%U8 z<6-1KIS#yJL&Ki>5w&xAoF?UNdxys%RQj_c)mRo8DRdK~B_|*+$xB_j6IUW+Ww-=3 z-mM^szOA2B;JeqRQAGa~@5SHVJL@&uofsldl%xmpICuCqz+B6Nv*h zs)@Uke)vMe@+G|N!OtBO(U0OAF*hgNf45)O816LtCLmk_hr~}yZhv60R}XHR)0py@ zSRx*#<@QRs;TiNMJ-bDy$SQrdW{rAeQR($3pYn@*79y33B=<*~%d+oxb~>{PX4(>t z+>i~TY!SqR%;@Ye7A83_Yz-FS(R$rty>=xam|khh8@qjxlI{A#*|#f2$MX&N)LO#6 zLK@;|p08>W->@-MG#hY7QK z1twOnLCq>E)}zS{1e08Xl+UhOPMXaAdR5j@>q13u^4QDdj$cnj*DpCqdYsIKiRtQU`>vG_ z#QB{bGIFV|QELq2EO+i3(2RWf&MlD>UanCvg(HjR-^0EjOxvzHei0Wk7}8RVP`|Rd zeYmr6JdKxtt%$xJEgm^N!Lp}#&4M_6LDPAl#CF&p%q8PbBtWH)SDR!HJ5*?7yomm% zSSUZr_kWxEFQ9y^K29a9LB$vuQ@v*1_v^2AQ+(y6f+;SG}I=qMA0IP8rOf4BjKArZ)?aB_PEk6bAa@>~s;oJlgtpU5Hw8IWyOywJTLH3-QwbV1}k{9|yx_#e1wy9wyH;fkeGKvw{qw zWvkvFm&T7_4|aMSri!Mn>zNEe`@X_a_y!Sl9IOB7VE~G-Ml0vRyWbSVcGTZQljbpI zHP9Mn)Zn#66(Mt!5yUP-JX(?UCG5?rCE4dC>~EukkJs|<-@i-PAnvb@2vq6h&-Ka@ zSK>{Xd8@D5NLd)X-F}X%B{tgAVZjRKo$-} zt2r(IFmEEGW?_{3*fw`N)oT`;p@f&73G_^b7o9#BLN?&voTF;}!u!c`j!jO#%5|Zg z#ktz;SKwPFv*h?ROu{9tff;VY6h~9el^Kb>?4@Lh-;yQj`72Ble~j}mEMduf4dj=f z>cVhu*g+oDYTPSqBB!3jf0pO3+Z$$}WNO^~6Oc>309MG+_@AGgNuuw)P8vO@uZz1` zgA6&%F6KNu-;oQyImTSNa#;c_abeksr_L%CZQGkfZ%6r(S6-_AZ_7^89nhJY*)vSW)vK8Nse+^P zQ=hrq9RAv^*7|oK=cQRhsQEfzh^$(8yejUVh$!n@Jwk$_= z3<<^b%A7n1d|vDA){7u?hJ>yJX~Lh&QPdnB7LJ#TyR?6%{pAc__g)t8KinznO_la` zRkJSo`QSwXM_v2ZkrL~%(vs-ABHJ%tlJ{3Qj97$=-vuBO@|gZS zc5G5}Yd$7-{ZwKn%rpn@Sa&T+zkIAO1Xvzf_{Z=q*ez^bO1>S$i+KE=y&?N9p?X@8X-?li^s>gSEk^TkDL)pe~V zC)3JVDJaaMQK%zaq)oEs&Q$(J?MkCV(czu~(;nM{KegoSj&;ZDYJ8hNGQtzV+8QuL z)L_2;19#tO^f=rmO7bscyV+Il=F3MXrJ3pI486X%XAgbQV`+Y8r(MIp_SMgK1-9k; zNx7t~2la(jV0B8_dY*lmRO=@VGa?_`ouCQNXxZ^UXo4EMC?|6PSR>csJOaVwjUwEe!&813{`QEv{}X-nv5NfsyR6)~ZzPY&N<~rHE2;wUJMR~dv zF%FHp$}l8b+LQA&d{v(}E~yS)C|S#V`F0EQ?_1=4q2bclWK|^L@xbNlf|hkfpcO5a z2A#|g>N|A7tCjd^y-5VTzV_%753+vY5NpJ6HSc7FoOB39(Svsgtu8oA5x$bYzi2|+v-DylEN%T627 zrj-_DJMLj`S8D!@(Wdl46hpNVeq9zZAL%V*BP00giN&qlff=KMqOC}=oTI|^!NQ5Y zE4S@WB{#okyy(q(0w1tdnUjge`>s1J>h zGAfra*GNIz{@q8*(BfwQ+azrN=wO_ zzMH-5SnLkgWtVyVr;i1ie9%lk$L?(zO23$bP0gR0>1Y)T{Oo9&we)YDYmT%^5)-@j zI)q-Uyf)m@E!P8jr;^`s-ceZ-R{Dl=yh?U$8!dbMCx9riQc#uZx8I$UcDgpC$CY{^ z{?&835HV-t2217Hy)Loor7Szf0 z;qvw0IT~r875))!+Y_(%S?k_dx!td{)7{~+UUfEUpWkMu+c;2!*hKP<{~@<(du0Le z+s+puu*BCZFbFt)sUI{4psqW2F7+R?BMy#q@=Xy3GinYaag0o!%VTcCG2CmevA{OABrtw$$!_Xx4R~sfU4SU8()?xC7UH=g*cw2m!Q+gQ-a0ksO3{9y zy}O&@$yjJ230obFHS={Lv`2y#cuXt1{vb%!@g6TP5C8gP8Mgkqkg4yVw-r3PSE1wO zpvH${ySz_Nk16AMxu>gL(gJ8wH*;iD{0VzwW-#SLXDfG3dtcy*C%KH40O^%kzy+RSrfw$HoP8onv*)-KDIp_DsXpYQ$Xg_ z3zzV)Bm3uwx};NgsTI3=@*}6o>Ie+tSQfDrN;ujt6iVD9w>rv4@+XNwm+QS1Rz@_A z&}NIhiLj=O2*z?~+O1F0b)LOF9d@s&yd73YO)UFXB#U+O`HC8Tgj=kRmT>%)q=rCc+!x@}zeDG}_{E05b}9WVhL_$O;@j@*Osfd!=;^X~Yy3nhU~!_XRUM3^&19(4C>|Dc%7#y z;uJ-REHDPp+4Oi#uPzxxiz6@Z>TsQ>Fk?Oe;cd4Z)hn|Ce)WlPIhvh|z)R169`BEf zj{{YZFHIKZ)|={GXq2OAO<`_fZocBNM)wWOj9Fi!U+L`?{Jf~+GGh?8LNe8d{sR{c zM&%T04HJ{U!!~AAl^@3A+%1I4t>zL%-mAp9uT9nMk7iwqAunq10MjWYANDl%W^Iav~V*~bsNUTFkCQR2-l%Dse#7J{r40Oh{5oT$7rM)vq`Bh^Yi zv*JJ50~-FT(HeC4I8I0Xh9gpOr(yT8l~f{M)u-#IYy*5rYuYO+yU&&^tHyxhf{b3b zf*#UBz8YNRH>ow>!yOmZEVAesM^=YgEo0L(e6~BFgcIx+YARc25XT}kLJoHvz>Oi6 zfoC+_Q;J+D*9QF8B{AY2lD&R^yq%rswUDlmg2$i$I%?Xe6F{jYS^s@y^qjViwyN)T z2dT=d?Wk4h<8hinqsRzTMf!aaI%6;)-kphlOg&F;-LEuvVAp$ey zJv`#j7)UoK58ap=V2%Dmpe1&&mFQPYC7nxDkz&ILF{0hCf-jZ(o-u;^T|GS>HY|_b zI>MjqxA*k?ugB6O+YvQ2h~4wT0R^=C-Q8hF^nj59?4aHWAKAHvMwYL zJnwEN8tr})9ABj)F^Y$lO1J#Bx23A6!118I9G(1xiE(h$mXUPdf?Dk2I$P-BIl!k{ zzAuLJ4oi!P4ZH=%i}PO>(m)b*?gVBSRyi|-)y|xMnG_n>cb{2059Z*&3r^`)1TU9p z#7ie$`Sm7a$8g>hC& z9_ty5adC3SZh677=gy5TTfQf~vE5J}+_^~B7+mq@ZSc}Jqi=DnMkh^(b79MV{{}qo z{kg5D6s69PT&wrAG#rw2V`5@edZwvC<$&G%{Evshxi?**3b*_WD~=TFJd_x(y7zWF zv4mMGc`Wg??bvktEGfx$x?lYqjz!?>vUV1&B>w(=^%4hTaCw+w9d?n;;Q3~l$J$Z3 zJ?8)!2m|YyGC&nx?SE>yq3^h%&pYteaV%jdpG#(|*}?zRE&IaTyOJAvD2bIn0lm`O z?Pnx1q?~sBztIIq3x@Q$sRm~2?DP39AVJSQPou$tIQwKOlcJ3D`3;ulzdzaicQV8O zT<(9y?%(kEKMWMZ#{LW?8fM|8`Dl%vo}R|NVIu&d=QjWi_l24y)7V}*ld>R=o_@#s zDN^39vw*bnrIWk%==Dp*+a!g~kirwlUVYnp%LCXy0W{%HZi#GMW)bBL*djd{-v?4q z*9AiTk0<(Vg#&4WpHNHh_L(;LSV`Oh$G>uZCN-Jy4;)8}K_dX@DUW^6#+?+^Ad;w7 zPD@%Qt8}%V8;C(oC52m&pmF#nA7m|YgY@0^XW!LxS3==l>FZ5gfDS zID76N>Mu>K7D7ToL}FuE^7DD-ws2lj16Lx$-)U)dhbSJKzWzzMGHfNm_%h#8;nrB> z(+S&h3*lNl-b$lNjMF*Dn@?MmmmrVthoaHgm^kO6ypX_~O_gO1ppiFYkvd2y>+NyB z`C~XQybV3K^$Uj+VPJ4mQ87}=AYWVn0$ztZ$YDQ9?tx)J z<3kK_3IJtQrE`u#!7biyIzvH8VgmPgBza{~e!__}382uJe6j(9EBptfyR0cBwF{6xm{|^0p8JNp17yWQMlVcd3ct7Sqd>OXAr0z5RRl>q)UB1F zEY=DQDy}Wv&X}D&%WP+52y)u{tF-jJmDN_YG0P8i0k#M(-MzEJXY~)l5%}EDgy5na zEXDFT^a{<)TvXKW|Hy0QuSs*t5x5DC!p9+o30_jCF3QT;8DQ27AAw}}rnsooRoS}+ z&JGUZXyany!I*WCO5kIayC5CXGRDLn>Rovp8pH6*SHl^^NhMc&EEp>j9jV6h^j}U+ z5WW{M3N-IF82f!v0$s%oYwPO5ff9$-VU0lMes3q0EVd-Y}|wSsNW<(9<$QtHHEVSI<0g3KhKxH9OBSE$N)>_WgUqw z@qiim6DmMw;}9X^1Mu-4ssa#InnVIdZ*R>A=q3l}L1TQpq$W1y)yZwdI$pVZ%zp9` zfVnT>udv0=3!M)=r(k>LL4Z0KB07g$(lQF6)_|IdluqY$cH-N@>JIC7OxeUsmASH= z_dJFib#hLxI{IDXgY{Ld;YxrMU;|cK8)CmqEDcec*RSy^+MYB*?4*G$Wa#d39{472 z`p-Yzk|KIddc4L5%jI^UgJ?~1)oRI82(?yEESI;c>{L++9Y#VYN-Ts%CNk^gS}Bp- zuK_4?%hoV!@NxS6hk%_O;wVtwDzbFSDJ%r`62!y$e>FVTATZE>)E4-YMMSWChB7K*zAb|3jd9NgU zdN5;97B0I{f3eIaq5+%gr1Ja{b#r%7=eCH)i>sTx0xXl=X$egkj|$$;*!(lgO9G(OpP>jiy!8)7FZ*zI;?J7`Vd*h4IS zX?QJ@Lq5G^6woc~$fEGpS8b_o>J&48at4e>dk0z)*Cj;XrgSTk_7|WJ4i2U~;WvDi zT(GH0yv0u-pf6sQe)(f2fNWuYVW^(i0pIZ3Uaw=_AJ4~d=d1!QAQ-PlSTTc25q2+* zn4u6ud16Xo_L$s(OH9UnwI+2WS{^?eIwme2z+aR3)$cfQTO~9UkVE6{OP>$62kZt& zav?mPKeC|UC+1L{`6B2#iA^JBfF^4?M>uBR+Cy?p8<)JENy<<(k$TnqNjaLaHwFIV ziqa&JurYEbG9A9V2n}b3b*PDv#LOusQ`?c;fv@IG=_UFE^E|C%@unapixRRq#|NK| zF5dkhFasLhcmaJ{xsR4ste)#Nu?q`;as>_8FpdnX6T(&`t*Pa%o<4a*U+|DC+ZHyT zZzcLDo_RH_wJXl;1C53zZ1&FwBWAg+Y_$y;;z?AE8-CIg^H02S)JW|fBe@ljIQ`Qe z%&g8d(QkPIGC4YkI?U3_sf0YLkb}>wZ>1{#XM}y}-4XVsaql|ysalxi<`2L?eV45O zL2#x!LYPU--w3idRXsIBm&t80NN?Hg;*4ejPHyR`+HhIr~T7* zgI>;ds?rH?vm!aY3Bt=Y$LmHFw*4Fan*mr*>}lnQS{kgxr3`-{A~l~QXN3)#Z8Uh! zQ;7{G(?ztU)vi_c6L(~_(!3Yfd5Wqx5*?T?JMPW4R3-Z(6ub|C*0k4oJHps=wItX^ zO(!OHO2YDK|Ir@S6z(L&M%+^7QezS058Ui=>m{sy5^9}ymqH&fs#>5@KrMq z5Ah&;q+!Qvp)!Qs4nRn4z%ltIE#&lfNpc?@k|Z1ssl*w3HBl8#RKQQLvKkpbl>Cnd z$cyUMGeh|$0GH{^BC%V8A@B!2@ZMcYQkV4u#Eb?jP#aS`WxUaRfcyV`rbNwaW*|I{ zmV2k&dckAJc&`+?ou1;!ktjshl;;S0Hko~zc-hZK(eEQ2C+WvMRu9@(palir0au;F zcYLzLr=Bp*np!Z_u?QIWA|X;Zu-c{R*9}owkK=l?jvD$$#{}K1OY?F*v8CMlv#^83 z01*|28+Q6rY>p%x_R30ZHFvX!X0pX>ffSWNui*>mC5+GhSdjmAG>L0DC7$$Rj1h;7 zBt7bPDS3lOU6h}8w1{`;1y*E{X@#vO>Yo6d5`bTQ$)sGwyf6lMa0~O9U?$URVJ$uN zM>yJF;AgM4gDn&4M}KgblkCM}QhGt39tY8eKiV5?X63lFg~P3Yy8&fFYI}Ep#5U8) zf#eGqIYYM}KzkX>_a}~vI2+dOe;4XKNeiZDPkcC69Ic)xVci9IS{(U)5c?^K;>t1g zv1{u|0Ybg+P`Uz;|9vQC-Z~&j6a*=G0--p?Wk`oWMpcW4V~jw#*utjC9!y}UIV{^= z$@(sRW0yYJw2LpkuI7r}+M z%LBa)`{NSQV}o(jH$)x5bZ`WENy*Fxb0K7W+%fd(BxM|U4hZ9LnrnUkQJy&hVLW=_ zK<}31QoZK2)#8148206X2y1HkemX~(QOF}s=7=kAv#%b6+N2(~GUx@;E_NqeiD*NssL*d<7Z={s zk~}H2a`CCsx6K-u?svy6VuNUp(tPY^jizWM?zvc@8jmW(t^xgnnO7*V*!T1VSTAHw zrr|&@*V(bgUDB#+s?s+JICBf+R&AvW4AQeW!dN>NU$CmB@KJesMZFm*G!_RhD?X4z zTo^VYx~>$mt0t31rF3@o$b673hE~oQfyftiQokX1C$M-T6>bW+$`7>GBhM;Du90-K zENY)MkF105*|x4BR^Rf{XMukMJ|$11z+4NZ1K?ZS+nPo4a|Y1c+mwsSAjR_DL;@ZN zw9^kQS}i3$J6UM8g@=i+{>g|qeLdR@tP;Cy55A@sI0AiF1fF4KB{D;k07@4CT3P{8 zAf|xWGS0w*t4Gb3_5RWm2(4NfQ_ZMOR;Vo4RAwB$i3us8a)zUXGa>8q=+ z36{CJ%2C8JFa!$_PjUH5sV<7$p2$Yv{s8RV2$RVmh+dEyir3cb#3}%glCU2~3uwR( z7r+Wz>u-Ro(eY>2ze=@MK}iS$!B$5{hf41`a-VEYl~GYJ;$%06hmp5EM9~5D#pf4b zm|OMq;3VO`Af{vLDrwwTs(hwDU9S)`lp+Sno`BgFeiVJ=KI`d!y3R!GeN?7wm9zq&i_u@TrrD87XIJLCQmO@L|cA-K8utqAx{T*5B=;- zg4LG*#SL6oz#e3uX9V&Zw#<5OX+jK`9k5XUd~sKKb90KBKR%q9l>pz;1_O;W`k=JD z`T(#9yrWK4K%F5}y39QjgCdTR{!TC6lGwQ!JW6)1lgFZ_CfJj%X5uQH+Jrivny6~W zEQqes^Z2D{LR*BCAat=yN%51d>K&K_$#fvIy{L^EN~wjBf}z`=oDHUptBJ9NGCSG% z1_jYd;8(vegpnXer-1AS7D`GCvt*_EH5l3dySj-SD7wl%lr4G~mXjLtWs=*LG}r zPqD`vdNHxFu`z+P_H2LYn1EHI8ChM80sTBc?m&kE4p`4rf5iIkatn(XBXlyMde&Ii zIQfy7=J8h*{$==VFh^j-w9iT^50clgia)T=9N9o->bu31=DVGQ79cJaR+;+k_UCL= zX8-_RzB0Jnm0x67W81F;MWx&`KjJ~&IPQk-i?3H7o#XOI&-ZTEN;e69L)`D=sbFVh zKo+sVuqg~yRvdxT7sytpGL&YgV_KOKlG4)dRpynt?hodg`JT7{T!+T?n$_590tX_6 z`9Lj9WN2u;L$q!!PEm!vL7QF~W@QBq-8z+M($3kpbRl_KuPGAFtB69?%a4HXF=*Or zu9++K8nOMhQSyTgDZDZ8afvo^1Og|Q0?kOSm;&}rIPXM#&CfSl$qDI0uscaA74X|7 zF!S3sDj|8%7mfQG33l;jr(@*oCnE+n4STC)PyidD$VQ1Rui~o#QP1mL=739$4r$Z4 zr3kP>xcKqvp!ppmd7N*jVb|9YJH3zy`w$Yy2IkKb5R8sP+1*LNk_8+G4cl$9(}=AW zmPTI>kWd~gK7rOO#HqIRxt`$kP|SjsPt#=l1X(f$U2FpBnYbNCIf0?0<;PkB}Di9{j#e&KkoS8V1_QUYj0}RjNl2 z$7^7;fstz3d%cD`LumupyjJuIeGX@W#0pJ}42>tVYLif71x{yZkkY4K0KQOg087!=^6%fl0tdbl8EES#U<3xS;=H}o4@?>H7!RXa7bSW& zxZ^Cn#tpX~aaQ0i4D17fE6Gq-9&eTk9D6`NLRJ&@n~#H1++Qeb_78YY8or9W^aO0vNAYbY0*YDC$(O`6ZKwG zavT6p4X@RbFo)ro_&5*HndzHOlO}JcTMUpP5sDe4K`y-{v=b&~@99;#MF1Yrj>Vyw z3*<#cHKmC8h6t(B{U;{Ca$DMC2bx>}@eU5VzOejFDe1AEoRo%Xr;qPVlLY}lX4GJV zUx%fJ4*xOk1XU8R2)Zw)c}MS!7N%&}0Ta8w6s#-3a^R0cPD&-9k7&5mlSQ2;+n^`{ zJL;eX;deZIz56IYkT9ed-9)Tuff?7VRGhk6kY z$Iu(QAg;{zSIkD7^-4(%CP}eQd5hRt&S9@VJpvX%HFjA9D1`%Nez4X|W1djoG*W9SH?)?EpJ1pE;f zc3sGNsqY)#qS=)&U+W3DK!di4f%j+!7Zi9T0Nn$89mKumoQ((;JTMdH`M(C~0%Swb z&N7CEwapQab_W{vCrExn&^&pr{?6Jr0L$UNac#N7#x%g+ME?3xSI~aK*Q(6cTtUp0 zloS^mZA=3n*ZwiUqM*_ifL}$9(IOpSH0w7wf(FAY>&we)^GIrL3VgrIVM-!QP@V!5 z0;4L2cnT6__ileJn$-ZsRb{SH^+=U_7BB*>5%AKdz*&sLy|DGAv3V9!qn*Q&^o@_C ztb@P?PgBvx-||)J^;(4x#%m6cMSy=u!c?xM9B;o$Feyq@Q0{}o_FJECs zhxwM-r*}$wf0A>VZZr^2VT}`r2x&UJmtWTA>Z-(-N?N&~hJ74x!t9}YJJ2h@Q5qJU z`46lp7O*#yx`lES($tc?Yl2Pj@LkSK^-F^r9ZsXa`KYx*9{#o6&gWjSz+^@MqTyAlwU5*=MlRrHVqCSZNh6+A6U6}f6an;QKGn4=($ z2B7=_zk4HK1{y&>5L~Aphd4dVCq@|S=F{!zp) z35@HXeKfinxsqS+m=TYDIv~SNwj%WS4F>@(KBi(8K50DOo+!7=zW0{(v5rDZGq~dX zl&4BaNNVF;_yB)hfd#fFOuU~t${_OT9k>b&46vO~N!wS7^U+~XZbkCRw(o$yJ6&ph=iyHHfG<87fi zl^tTstKLaCk+iSlzi44tmj_bzF=bU<7T6Os>I|B2z(1Sn4m*#HtqY&C&GkU{^mK2d z1%U9{aNu_Va&t94DG6*G8Rfsl=nd{984bu{3KKWi@h2J1&KGRW!6PVTfZxwl`MxO9 zR-(YC6hVvFHX&9r$b_y`AmZ@wG!C@lDkv|wiD=SvB=bz(a7jV2k)bG>DIqME@UA$OWdh&}BKp=7y z90KuGNV46XuXLKQu|ZdzTXnz1QQq6bHd^VFWGg&S0%p7JZxZ`l>v}tKj`DBnc68{$ z2;C3$TRh+e$>$eH*LT1_1-;SrGhz4*tEMoWc(qQxpQ{^D)40Ag9h`|%4f^YG0G*0E z*vQm(axz>Q4t7u_reNeDkSP0?|Ix^(L<(6 z!|cJ{nK)g8t-EL;sKF4x*3rd7MbfG^Ee}FTcXss(xv+ z9Su@9$nhhyEur!hB!~7a5m1!o*>mX~e^XKdBB+M;*Sm|9auoh2bL{dI*fjss^}3DJ znRe0>c-#jS<1u~ntCA9nw!5ZWrk}1oyp?e!GTUQqJnY)TS97gl1_lNkfiq1(RUi?7 z)Z0rEUm+05>l07UL)1tD^SIf1S+5M?7~iY?z%fjpSJZu}Z*_GQXv*MYD=Yzi1%}|| z>a+U^p4|_~9p4(@c=h_8jt-aGgX&JB#pVkO3&A4{3=HwcuFBSPq@fzUPFk>PZa|2> zyY7EqKmh5M!6F$?uOa0Es2%nCX$NFOI1rP%T1o4(Scv51NVEo*0^J}-pgfIqxgOH= z3w6*g5OJV>D@Nkt;wAd4vZr&hbTm-XSH3D6zc>d;%vOqEQ@Y{ugknY#$RXJl<_?@5 zQRP9vqYT8eGr@b}1rR|iOI`hRhQQ|25FmEX^u0>)-D(lC?vdJDEh9F1yMgbm?5^6F^wNSUwSY9tRP*Pl>enUc-F1S4N+owRS8TSq%-P#m4xW8v496HI1m3GWt#$jfrG%sU9bDgRwSF&R}%s&==|tCeKDp8w6R; zPbgvu_+EF42|XAE*w@LGl|_k0M>tN6w?=_)ZW71pb`I|4xzEhy_^8-ijJhOAVIJH` zUHYAu>@UkJ=M4VxRMcMom>w=5G56_H`lO}{)699nSzB7#LCCFJNjI-OJQr(D6?!S~ z@teG{Y4#h`Ne_~$BZR@2IoEZ7#98hb;ou@OAA-Q z@bfm3(EuY+;GM9(-Ae{Z zBxt{I9b3K(BN@{`5b@sxg1340k7X%+LuTAP$jwjOBhjh?+%q5I|2<)wv}HHpu;o>x z9P0&0pripsC>mB@z&rT%?D(5vB>)P3DOYxT^w0d!z6|*;We`Ub8*5N=$a!|c_Zy@K zRHt^KBZFwO#`C5X8_Khi>=+OT1r+3xn~uh=kDev>JXbmgfd#32jQ&r4dAvY+@?w`^ zXRNamagiLN?d*Gy`y_vPU>GGexhLcKH+h_wT>57y{_{pRKLO4CO|j;Z>wAg6 zAm1JCDBqtw+i43nUtc=A-zaI`Pl`(vH~zd!4i8SSY7?~r8Np+q^0F& zR{MHU6$iH9?(&N;#*v}Tv7p9hTGb-_$m7o8GMc6h<&ulLWDuCVbhEEM|g4F%P~ zc=-7D{dBULyk6M7b|Tzw_er5{TQ4tX0$Zx8UYozy)yClLbu4u9QIz-D6=P9oxoWMe zC!a}c0Rqt`15fc?V3$nZ(YIdwZY$xFjW<%_j$0jEzv+g(FBxn;zq?Zi3aZ zM_X*2)5V(fBVBThCIkR2LrwSaCeJ$_bn>BwD=(it#bXiD7W6#@OVutO7STzsh`47{k51gP+5X_4^aFb_?2JHhiGt6$FrP@+uI&+7ln z3sCi6ub11oAp(I^ysapApRh?Yk@0V|a&;Yfdm-bM1!szS)SbGa+LcfNX3$(qb1w8n z$TmLo^ZC-UO-K|W%h<}6Tz@_sdxsm_9+~1WBI-P3-`5=Mli`9LuP8-li7`W&g%l~a zn)J-X*F2)fCOrr5S$Qi*1=4=O_~9ptOq5OPrlmX_zy64Ul+v(1Tc4^s{`2#0*%;yE zEj!{-v4fuPK(_RU%XZ_Hh1(}J7=PmWfW}6$NdBM68ou0IDtdbINpBnX05Thm{;exA{KYZlgBeJo*!xm}hI(6^oIS~t*LUD60+3XWxWu?W_c;;})=PkI65 z`>QH57jq1S~hK0F)h{B>HTO`)RMUsU1X zM$PX0JG&daRd;{?!g@>@m-Jd#Cy60RqHm6R!||wv1IAB}qTgYuk4h!3Ue+zU^asrE7;(CoM45&d zZwTQ^48p%=tTSSz=(k9$$^>}x2JZgQK5i( zvcB>22Of*6261W3!nPWQiL|eNzPgRqb zsMps*>OtiBiefz_9lIL>iF&(}_NXtSn8x`D=AZj%|L+U^yqwh@l7qh&t zr;k^~f0phZDKo)3abnZ=x_a3knZKL1y|K61B=_+x{oVRfbNNteRyM?%2>#W`-pWY2 zi6qC9-f!};18=UDqW2EoU5pUW@3U$C2#ptDl6%tHd9MPVp5jpx_@ygXu8)CB7;QA@QE2v`uPV~-x7hqM zdT`)eHTk>LqK$n7$t0IK35$OLLg}>9X(KBqB1L@QZ1r+$WoN2>xfS@?%6nglT^jXD zA^zM2k0OJ)x+Gr*jrFMsX!6@%6y=!rwDH^9jDRGs4`b0p&9Tg_>C$-h3-w+Gj*)e4ZYK#(#Ge)rx{tPo z-d)5=T7iKOyUe0%sC~!surNiE$=doZe!W4G&j~YJh~uNRy}Wf_cGd7-6Z6-j*VmQ5 z@{a;Qodj*Xj=T4K?Ze4}fLc+FqTd%G1A}$SMowYqG%xq^pH%5imBpnc*Zd_B$AoQ- z0Z}K!Sfk0ISq)%PN18y4?o0bnaD2LQrHRe!C2@c4xYBXi1I?F;o@bM7^q;6i6&f!W zS&e;@2g$53E32;YWcz2lsjGlD;F4rP`Swin6sm%JpY&RQ@W*Fg! zo5sjv>1JScLJ|uD3r}G2Rfd{m^@UrXeKH;j-d%iOVqsH%Xx(cBO*t6UB2JuV;NFC$ z`3;v^C~-9Rf4XcC=VWEo`Ra;w8SSedDV~3G7?wjfhTbq&3EzK4N;1zEvWCG%dCLvc znF#0_V(#+Q4;aDsv^53>XyR6cY{QQFD|FmC*O25Vn}B$u6bypl`}+nQRin%O+H_3e zKHYZ#?_68x7Us{n^Nlg_Rp3o4O=@o(9@=m`F;G@MW|J;p4251xl~ka(a)p86I*a7% z*(V%NGVZFa6OJ)yD8fF$sH%2H1JU&Sy8Juu_@SOS?vXnGVJE$QSQt$HlXXqfp=*~~x1 z=hJ}AVn#qh|DCDa(EyiieEH8L`|0!k^T@Rc&)!-Xe7JDsq1WrV;X;AM#nTPf(;{L0 zF}?<$kta_S#8cFX3c zVU9+A&^N&kf9>$^yihSD``*iMTwQF1jyv4Jl2|{0_i^&2RNp0aO~niUf(YysiuIGs+OaEtGZFU-zoQb0FS}U9O`7&TcH{J4^7$= zt|2)arZ1XaR?K*KYnF!1=F=gSyw&CYP5yjNKCPlJ0u6(bAKm9|y|?FUh1Z@% z?E)M62Xu|k41-hq+H}KlHcyWGS<%nCga<%hLLn+su{%)>erPqez1bdL!2IC zSh{?lMzf^EBdMG4JkBZ}z2MpL&J7E8&`Nq+8ec7p0yx5Xqcve|GR6v zY9rJW!wT-*`jKMcx`C|oDfWaUg04pXz?jdxiTzdp>A+bA_00)AQ2XDAGGM}yoB7;o&4A`=jLD^wq% ze*Ic)3QEx{8rRc(aVzj%ovZxqg@TL%!ZEQ7UNvQ35f}G2$7GeHD_9G4CWn7Zmgw*R zAnZROY7pmHWCDLAJ@rE0mYY|*vAxoex3l)yT0jo4jJ*CzJ3GQExhT8)d@D;u?&CqW z8Ym8z{YJPt8!L08KBs?{qhw z6I3r@ZcpWjqgTTB>g7e&ADplMP-(xiTAUUQ~Rdz}+Ij8cvv~ zN&__*^gsY!)NAD=d(_dUx6kp)_r`s48hqLmcfW8xym{gEqcsms1afL#2mbZZnr=Sk zfiER5AGc;@E&N&MyiMxZZod)>qX2(Z)2eYtBcb`S1BG@a>QOZQ!-Z3CZGaa;)-GTj2l2 zU@_YqoFW1H8+Owi?0C|Vqga>7?tXiL9H67_iJBfs_k}uZhAagI7TJ^6q&w;rjGk<@ znF*NGiilL~!A7osYSr1nvZK3ryLzGHl}=@unE*4SI1D=)m86^C*Dqpw3XRIY1F$0) znx$~Oe+(%4VoPP0f8I7(tKh~(fbU=zWQJ`59%WEj@PD!Q)=^b;-^1@QK%|v!kx&}x z2I-LQZcyOR-AE~^G?IdJNjC^cgGk4rySwvUhv)nJ?(ZG<-v90$2S(Q4b$-}*2G#^i8d{6Em>941zf&%=-2>gF*tmKQHz)Ad zzb@3=4gJGyRi#?e+{DY!zhP@)Jxh#($GI|T?sIc{HIHI7S!xWPp{=CM$)G)!?XVU{ z!t=vs`aN5sBVt=!AWA5s9$#AYaE3^5P&g3^IiGf!$UrL2%+N6!(GYmaTF*%>t*H#J zD=+P8YmElr8u(>hUb!>P4d#Z+0+?4Gqona)<~jc)b%vv02bos@%Z`&#SIc$bV^LwD zTfMV*xf>XxMC~eUJnZ$8OPe?blo3Og=Bqz&Ih#x4utpszsmuAH)6;tt&Q~i>HW2a6 zYh59|<3mEiIk2QUSy(}jykfH<1z-SPdG z#+6{EX4H}SS3XzJtDacDx)!ii(C2bkU6V~Z{gDNh__H%mRsdS>crcaJ#7lLvRWd-# z?|!*H2qsWJnNM=1&D^j|+;29k+~?xp`_ZVQ=iZof=ButW^;($sI<8NaPk&{VE3tVt zji7?#WHW_Uf>8?B$Scds^tyG&-GG+(oBlS}2yVxv@_VGZZ{{f=`0ls*kpqR)`c>sf z9h%=pDRsGBK2YNqz#&~fngvT6p&V6Z!R3iiyk#1X){RdU==(vhEs z|A|XZR^#!gdJ_uoj&siN2bQE>2DP}AISf)OAl#xRCe~_d!lAgSmN?10@jjQ1y~`#J zDkFC|ySB*#f2_eS+MFBMr3_#$#3loKgFmf0Hg<)Wdx(~M(yO)>nfn4}1FYB6urW2Y zReK(X@-m=xZHl{!68Lad*CaUKrw3^1C}0l%G)$-R(k?@;u9%+r@jPda`QzN4AJF2q zCz~pd=UTsK48=EmD@Clz0{)=uNwWSuBMyQ$ks4$S=o$?LweqCQ!_3!r0i2}ZTlepa&2F!!c79fz4IApm) zSB^`Klj510uP)X^NCb*T9Jt!rs}H>*j3 z^8B$bn<_`nJMO5Yd`m^u8AisI^pX(rwF(#~gTA-Hcrma!f?3oTa^isc zHQ;X`&p%ra%rUrYbAnkis;EKxv6H;iMrss%)1(>ogYYwo&<^l+NPxgI#qGHS+SXXx z8__6A<(mnm`$j3qo|7{H7bKT10^*MQAp^Isg_2JPre>V+$tB#A3BOwL@4bpo5g%o8 zKvWnsKe;}_1EEp)HFZ$Q06v{9o=G?I1|mdaJhrh2_h7&;m528q3r7ul-}DU8H$M|A zLsnEYH}n3NkOlbS9uRHWzp4Q8k)49&qNe`M0*wV0B=E%2Mbo76Rs#>`7s?Hua&F-$ zVR%wExR7i-4N-uv*HR^hcoQG;Vp>XAbi)zKt&4yEYZXHHb6L@VyW}MW+(jGkMhYo~ z^5k>GY9{mj9l3l>h7jNV;Xx~FQx>}gR*+ll;^_FOQD8*z{`bChzVOCnkq!=i7SH@$ z6a-0sNl8vgUMDWb&Q2&o0;0p<%B6sJyT;H{JL7lnw4-T&BUxxdp_p`%lR6s;Uex%X z-g62j9|1qHDarl$G`i(O#}I2eiL>bnN#}^Bq>;|qY8$1vzfnjPE>;Ug;G?XW2h~GE z#7VNxh0&e(APTVcfWJ~hm1Yi6lYOf9nc!f`!0$F3C>)-_B$=7D`a?^{3$3m<(R?LU zMj!3^NI_6aSW-RcZMoby^~((KosT(d!Gr_Xs6X7QdIq{jZ*XwN^dh58ao$l&hmmN5 zBcQ9;rpfJQz(?WSp<53*i6$`w4vJ-z)tY7@vPHAqwDC|M&70|2HNF|DSL; zeDUu^2v0!!_hNeq-u>U}J-pcAzt{hI(0xz*udai4!~eg8K_vH4E($$v=%|J2EfWn* zt>Z=%r4$+w2P#x$q1Cz?4-XH8+=?R!b8!g1!AVHK&m6>G>}vgedvisC-U-mcKup2A z>vGJOZ{CzTZH;}8KoR0sRZw`*YcD1BxrXJ3gedSZhz0U6LULWuN%`KFYM_(wPzIcz zjO!1i@Q(j9Yy;8iQ4L5LeTimy$BO;VTyt|pg(KYf{{;3uE`XWqFcQMI<02LVwZt|b zwM|TD`1{!~fPun9JfF})05xQmB*?r}E_|jcJ`88e5`ma?wrr9xk!nqi?SgP`97Bp+ z&LOjafL_V?+VV0Rbc(IQFEA8@(!D_@Sm;(PWt^2H(EWYvYFsk+R>|Hefc* zs<)Amk$A%NIyL)WB}kusP=F|qHQt=ULU9?CZpqj!Vla(%r)zycHXkSzAr&JUpiTHW4Bq0wBgA#bI~Wd?6d|(#B(Z9K#%WwP6(d}H>HJ_x1P2x3+V6|# zZ`c~}^gA*lWRtbz0a&!Z2}&mNIOXe=xCl0^ezSBx*;H+N^FoJ`ni`#e<+qnX?(haE zWF(voS9=Q|O|)?&B_;7WtP-x6hu*VA07$!nJTTq^I9#JBSA0_BTtLVskRx@U#d%w! ze6sM`h8bTxl9U7p#MBqah`GzGTTZu$((U-xNn0?6yrd)&R1%^fh=$LcE)`APa~DN< zvN=jeLz5R|oWS-W>dK+1+r%9>%q+P;r+^?i>}Y}iY#J*cKu!?fke8Ec?7OvVr18BV zJqaI`LLy>02#UjE*!p;Yj5#X5@XPx8I>-ijU0vhAlS2IUAyQFIO%2StUY2`7JI)l5 z3W9_KS`5GfT0!5xTPNffZ?!!=uZuvW=N&RfQvX&Is&71y)q0;YV>ZIh2ojh01>)jH|@br>ZcB{t<}MLC5I}7+EenJN@^3#7<+qrNh6_}PZ1HI zN>l~N_Qyvx?g;z*`SVjJQP2RPpORIo;kmi5S3K!KA5VJ|<79ZUZaMNa788Fon0AIi zOG`_IKLKx|xVU)G{nOV6Gh<8N1I*eJpoZil<>mum{yZf|L?_12PkI?i!aHWd(p}~W zGH3t;@lQ`L*m9-($y3e=y02Q2{t$Ia&Ecuyx}%mZV=%osRA|BS{D)LtULHk9czy0T zN)p4!LO`M($N?1>tJNt^Z3{}tKB3(`{fs4ev)^VIO+DytjVQ&kV+7fSe1J)?p0oHFc@YcP?u- z-W=fsIdaD_G~`5I!aKAj!nK;s`qK}V60sGEcdKU!Nw6q-?W@T})|ts$!k&Uyy=;3F z)LHX(#*EjvT-TB7yklJEIGnSC!(s$r=V_pL8i|a?CO?>$i|X+*e|>RWb`sv84G;Bs zUH-jkkQDw+gxW8gJw_elPJjj4E&Nfoire(!z2@Yz0@XO~(pEwLZbul|-GtNMbcH9+ zixK4#UIc10{y1HqZoVUlsU$KC)rren!_-aQ&d#rm+(DSAmCWI#1^3DmG>P7xKfJ^@Mn*5sPchk7 z8rlww?d)V{gJaGky(%h5Isn!`6FW#8Y-i!(}Xul*J%bbFSWhp@nvqm z|B{ymWjh8RHZ+sMF%%%1l<}D6&?^6|tncWeNaV?74LLu4|B0M_@Iust+=_7=qrDwn z+(;$qVGe7X(Nh3|DA4pJ0QKT`E?<>W3X6=1Js8Aotq}Z|1$Zh%LXBegqi{QHhICU% zG^kx^-L{5H55f2E*TC1#JgnV;>FyII7r~20-s+Fi(G5C)b-v##U)E34dv!7KINf`~ zrZnJm6?%c*`GIi)1ybot|NBD{!yJH6UgY|t$HnnTRzAq3OLzkeanB2>DiQ{|a=QoC zkQ4uz6&@`$-25q1axmgbx%p2ZIKASiyFNI6Y;h2HF{K&m>7V zE>fe&)8L_kd`$qCQRS4#@r`;!zuKZB%ko1Z267ZbJ01tCDzKa2S*adUO8G5s30%MT zFR#}S4Q+;5>C8VCYJAyyxJS+-&1YR1^g|CUH(02Da(S{C$GPiMhNmDSQuiOQp6#w; zo#sIj;-^5dqsH#8Vu>&KwP4VN;HxEuyBO7Gxbkf?_hqfKN3ICO*Wz9!&2QwJBq_%+ z*@L{(lL4{d%+<(ewV7Oy5iQigT-vn_8OSD^**h>2?W)~XM)9Ez^pFveGE6Z!b2N3W zbw}yx76ga|nN$?ArKggRu2W+9#Dfvte;T7s1?%CuArtaaJ$hu2*xSy}@*tffYK5i4 zT;S5OPMH*49a@K3R6kr0vBx0^LAX;`fs!p~$R#Z_lai$uJz9f~^Qh8GFV#|q#xPEv@ z51-R|rZo^pOVO)<{U|(#Wu)G2g>zx1la!9jr5O29v2`pNgsz81l&Zj_D-bVedOkD% zIlGz@TG)i@6(fpaFYrR$n(R&kFbFFae^}>x0=9yBE$w)G!q!4yt-yJ14~}!NdgVT} z6)yAh*>pZ%L;ez>mL43eCg7j3?hdR2{DP~-TpsvLaCoAZrt_2&lQ_ro2V(vw{6~V9 zoM~FuU^Y)VcxZUQ-26)ST~=F79%oIJ_lkCjKHi_?+JvO5-qW23y7=!H_F^YRV||>Y z{XIJ!vD1&UJhe47RS{5|@$CyRM2hF0Z=QZBFl<)oe6K&4qI3b!Ai)N$)$Q)+=ACJ` zg+2mBx=yzAjD)QM42MSe%{uzleBVZwO>~QN@xVZTQ?)B&0721MG$QMU8|O1tKuXZn z>%b$bbJH6gM08pPAOaOt=Ty*xNeA7_mW4-(k51~eS?G~n@LZv30^@Uz%IWPYJYh-h z{+3(nO(&P5!0`-1{O>jX83u`R`+7Sn&bKtp$d7{bQENwo$;V6T_?Imvm`2}BsXOMV z2!z@9VwA*fuo(QR^tz(G8*hDsmiv13aQeQ~M~tR? zwZcRr|Ba5=yk1>z_R2@sMqNd;sI|0~pf-v6k$2vdq8v;v&jf#SCD^#vHNvMe_%I?!*qsNrd+g;`lJkPr&0k~2g{*8__NM4LApqbMhf z#&q>P2Y=cvfp9wrQ5}SD4ENHiAqHx~v z;#ghA#zEKN1Q5_BYr5?DP@UAb3LpoXUYRJ$fUawhZRNZpy*YKVT59|VA^Y(c;C%++ z{h22i9EttAYZ%x2ZGO7-i%A?iZ%ibItDv!K1HdoolIHEcR;URg2~a6nXhH(l{2$&- zA~r6M#orkE-XE9~5#>_|hkt&rzh((-x328y=%mBI*qw|nbvq){s`%nqXLvSO^8FVG z+kn_})$-vAdZYVE!-?8TH-LStq+}Z{Pq)MRlgcs3cK?>I@!p;2>oI5!GW7F%d&*dB zj;y8ff+rO-HNF3mz~$P5-8i^jpVVMM22i5e_s2xQIqQj{;+(dqVP>{_uq2Eml~eDw ztr6UxJ!{xN$oE$blxC!5*q&5WC6u5Uul7eM&*)K;QIFrK?~LWB#>Uyvs^?hSU!aCg zp{DYT5|iu@Mb4qUoBP?KrIr8tug|qB`R~18^b{UYUwe?Bii$&Ewp)dLCN z9amR(re;{&%6<&T)<5+_e6ZKJie;P5Nc#|jev|0}`np+`wiQ>T`0xvPJbATrkPg6Q zs@XqoFaV@VAx}$l;x6uzsJ>^0W>mlkoNocvI_Im@ldZ_RLz%VP8(q@ovy#6Fhyj=m zjfY=qQ)^S(=wiF4EYk?X#AAO+GwP#be@3!JrMhl>0#+VON(S>P9K9Om0w15~Nl!3l zoh&T7veMrM3&!;&!g;)o*RO*~-90+Ou$pgaf#dU{j>raEShTYp>;Y=k2PPWa`T^4b z0(L;*XA(!e|lD+=i>$9 zB;XMYfTjY`e03Q$N15vE>|4{{pGJ??_GT(RT!b=_UT)+dl$#ZK-Z;(8Ea#l|y=%5Z zM5g%bt^S*e@_K-EfNT4dCa?nL;K*0q<+Lj8mv@?Q!K(rGKLGG(bOx%0({o1eIQQWr1kSx z`RR*Jwif{jTd{YETZvoT4N7T+ji-6i27uL4`%I}|dERs{W_%3YRiicyiV10gwylpF z2e~#Ef&(!D?CEOS7KBT}!*@Mpx!Yd6HC`fC?=1W&RV0|USy{P@aeN6BdI6k9+B1qK z-6kERX9QT$Bb5ane&Vv<9Jfb%%R4ec@vb5WPX=U@1iHG`Io|(0jio!YfvplvT*>nd z0t)K;*=*9^hKmFO);}pcaFz<0d^U-@yqkUen2eLL?ydjV;hZykzVm(w(po_C-W@Cj z&$y&vwi>Vr9JD-lkal% zUf>*#nI?%yunoRl>YQ`mYZU$zf?MO%9zyE>q_d;brG6zYj)eEN#=8;oK!IuOeE>CjII1WVfkXk9q>Bc2Wl)xfQi z{f(S8=yZbpxbA9ht^rS2eT!-pk3uu@$Uk9eJSd$zw9=;38|L|cgkde5jDEjF6xbgE z4l58Ek7?JD%gOp_d+v`x+nKSeM#AlNiPjbri;MGA)7x_GPhesqAZGUDWMI`!1((#1 z2_Ji&eTx^;RcU+|8-L9aGe>tkdk(4fNJFL#lD8`sn6= zq{%6AVgbe?{K=>JSPAgM%ai5CgzVC_TZ|=V!e5LDF@^h1KGq7@`m>IE6se|Rlr+Gl zDU;M&gX(#6(ZU%&h*S8^e~_w5>F%-D|NG**+mV@+)RVJqMLm0cPa&}qy0a7LRJN?4 zchh0>l?9?VSqBwm#onL@l3~~<{L^2Lgg<#{SGnROd0e00LSfSq=#4>WfZS35tN1^_ zR~a;(ahD3jo%+?(PG?@FA(8(>d#UfLO#km;uL8b`e@HJ{s{bOrSUGHPh2ME@=G{U4 zLa@)P2L$SYL+!tDUPu2k=XGMtAFfS^Llpqxw7G{$TU*7-EW}NomS;qO47rY@3FzwY zfvaEwo2E$sjGaYq!WBtx(I1eBE>FB9B1Se&7B|&!gy9~@jt=x>E=8olT&ZY} zyIU9X-`~_oNy_^J56svt-=d{0OCQWU=+|?GZ#6MXYV<5LuTIH~#^g zI9+{xRXZ4&*tv~@ZF+SCe7uJbS5ozbsy9Zu9Tp5a*j`j5Y#})CJ9ydB*}JZYQT-J9 z`uH2v|C$mQIKDy^)8#vt-Z$Q}6&vrx#ev8>7n~Sb7hg$Z^XMX!xwvNzF4(G6oB|Wa z-G5|XQFe5m%A4Xx3HYY~73F7}uX&jf3WM|YRM^Y5k% zu$|cHX-jLmtsCh2x~op+eKHCbq2ny6=qQgfZ*VqHjo|h73mz8ppA>)o6k^Yla!a?LH*?QOnjFASnef)RnBD{S10N{wxXE{=nvOe` z=Y5qv1Roiff=DwHS3OCSYb^O`4(K=aB)WR5>7~d{D#~-THimh`&6A~6SECk?THoKb z4h)*rNI~yKe~g&;hPu+4%hd-v9;evCfbTCVdn)XNxz8{s`_EWVRR$riZGXcH(m?=L zIrBrqF4c1qdq7Sz;p{MY6Y(khYQZ>U=Q9fa(3{L>`|CqBr`7aC=0{(fO(8JTwE9kv zSKXTpAGhk1i2Z{~Q zM$&%)Omy^QA@Q0ki(u@{SdXB=WeoxGn+x5KZ|6`Io-M4TGP-{eY53S%RcI2VM=&uPKA6B_lM z=CYb`x{UF2R49K^KxW9U<5IZZK((}7oMT-h5ocWi+>$Nzx{9iEd?PMOe0d;o78QSV z6o@%~6_Z{J2x)RDK(O_+v4pO`R(gRdg&z^(Fgyg#NocyeK0?Mx0N4iJUK8)(_uy%= zMN>^ReX+?3i>V=@dKv{d;;Ui+c*iuYhV%Dkt6)O;fBsznR14#Imu1wR+N&xHcDGZj zvpHZNT^5fvczLAgrSaILUO@_(1$_Yfp%76CbAi)c6|{_gPpAIW*1az4=U*j_T+dGx|91dwnFi@9FnUQBk^7F4!30%7EP|s!4yrNk_LgLX$JY z81TBzv0FFATn0FJe;CTds@Y2{+H(QU?RoRK^383u)ci!k;ZBsarG8B(N=p-c2#3= zaiCxWOH!Z?imMqNb&~lsI>K`v0BUW{OsL+U=0nd~&Mesc0n~PiiZWVSaw*mFjI|2fF5<{Nl_z&xuq2}Am-m|$ovq_efM@C?y zY1-ZnD8Kj9btiyzc0$3!)vv2?YDbQqyau^DJy}Np46ED7jI<_ZrT(tTN-hd|^A9m^ zmHA9v5uKU|nE)R+o+5Uw9*s~1)aC?79<<{zS?gEQ?k#s~qTp?!1%XrquZ!C&pdN~F zWsXjFz^dbUG3x>7rb=uab{Xj&0mt_{ynD-Q%NociCAGJg;UJ;NdyKvGgDU6bz~-r$A+siTv35{p;bJ zMvF)p$$g@={-q8C+ZN!bZ_wqY+3aJ`4naXacE925jYHUE z2DwseaLL`1C*nlhRG(2+0{L|p;;GX)k>(Qp0*2I;3GzWgT7#@@J=A2-yi_J=6Y)RwlX#R%2kJsw@;IKp_E*`cOh_n`ZU8U-k zQDz&qku_bj{Ee_2s;g`y{p~4k?DxZEn`S7;)=}WBF+8`OEA6$k zx!jGhASrFDGp)<|L40$ub^^+7&Xwrh!2YBRq7g2q@O`M%m;zBSdK#L)3E7MQ)3ZA% z`p!oJ>T!b@WNKPQ+l(MMM@VAjyt&G{05x46L0}N zmr5T)I+jYGe)i4_?)1(Tq#Qt@NUoant~o zreyTJR_cEaTf6Y2P?y(E8<}d}-psdTLt)~g;;Uw+R2A?VcNmeaw&BWdfkVI@T z+tj$0l12A}Sx~UeRXB8ad)EqXtSV| z`(I$*lyf);TQ7H)<1*L_Zou;Q`jZm@p&NR-(<|V~Max(W_KuISG}7PBN0u}!x|Fyb zz{FG$IL*)?K6rvQm*-n%z03N z>uzh$#|Idf`E>6fI4-aGy}(XCvgshGho$Gu#L(UKt8=3QV@w4ahauL1k-h|FK<=W} zLZ&UcKk3SUu`1|qrJJ&khBnCi*(zFMlw2cblRt;v(?qX(nnNPu!GvZ4#dblm+bpnj z4`I2(oe@yIrt96cw348Gh{^;|eHb8_e{5V2?sPw*Q_E!n3c_iQf?RU+4N`85o4~6a zfk^KEJQFS5;y?hwqE^epHH$PM2p$MmAOLQEkg@9$2oU0i{fjk^<_oh0W%-p9p3w%~ zda&CbaNS}Uusnev6#*`pqHh&WQmW|aq?-aqS@udV#`YAvxbX&E2`b383Rvy;r)l6p zd=Sf$R0Y*$HI`$3WPmgNI)F0Z^20OG3{eK6(yhdpjCu7q)7sVMR73?2l}=z@npH+{b9Q!66ViH?*_dvZYj{^{>Aqze z_=1wof-mwh2W#=$r%%>?Hv1i>lp=Hu8M^8U^GJ0C`vM4?wLgg-_oTo>Lz@^WYyPiO z82{RP2ae|mK~#(Hn_A%1_qli;qQTCtW)g~T|3C%NSaRP)Dt|r4=*1W06RO!9A$~k( zf5?4|2&S4AlHtT7QsY(i$hU_zVDWY7cfGxQ5pyw+R!-h)F9N6Y(jz``;yV%>KFH0y zk4a58H0xL!vDwojrR#kScyGiu=Go|Zg$SvPmWz5W{DvuA&ccfA5Jm`b!nuD)l1o`p zZ1?Zd7ryRdxEZnCDn}=qRC$4eU8?GkbT#k|f9AvThkqN)PmzOI-F?7E-usVL=yC`Q zvKcLz!boXe^^`p7(l)JW-saZ=l0mQw6sLb(K3&16c^wJu3kJQWG{_ax5_p6psZ zPA~o^Ft~D8u2>;A4)Dbwkq5qnW1Q5~b-2VYtHM9MCwkVxL=1TmKq;jpz664FbyCkW zY#beb=na@)yqJCif8}$WeeG3If4`*a2f1zFg{j8Ad7wIe4v}WVKYxf05f*;_a?oJC zRYG6oRVL*OHkR>nCp)B-06s24FD!B#D?Wd!A?MNRd_eBYBl=wUl@zC_M0K95U`I^A zIv&<=j|qq}18}F3E%CDb_x@+RQ3kCXB5XXoqVeF{3U|ogfcxO@7kl($t#9vcjE%y0 zQX;~LeD`yrDKq891*x-5cVsL#0@evgyu3_)P(FUd2pNHxHZ%&bl&L$ibz_W#y-%@L zu(J9%_&Q!APBz)~-eV$gj`Y(*t)PSJvt0Fb2D4jB$M}`lCMu()L=zGT#-i?ci zf3r9!dBXFpKRmqS2Dg_gm;#^%LL}pV4S)cQDwJS=G1iaSlDf67Bz?``)Kx||asUyk zy_et~oROQ5cTpn@wE0lc-#*eZM<5wY%HA4cA?Tu3RN7+eWn!YkMNGyqvh}3B!whB> z3{ICzmP^6(M0)~J6(dkFKE5<5PYgYKsX|E(w*Bv|Sx9K;ct2F~m}nZ+JyGbr7e^II zg>DY9WW6~i>gDM@E*xIS4n?xKPx$KZYQww zhAZ#oOp#;|0^wt4!RKm1pj{qjYQ`3Bus@rDgQXuc;(wTl8?$D<8SzsIwIlO7?)*y8 z$zcJg2?hCsJfLZ!^-adV%dv*1!lPNJXlxb(7f>EYxeGY#>bY+r18dQ^l2vOkvr}__E zP{K9-J6vp3`rmot_W#Z*|E~|-&#V7u^d8GONF4z_ETgWzz8FdxCMJ2LuV25C2OuFM zBR_q5;B;Rh3GyrcesFPSM+?*eFKAh+@%;Jo08BXb*kW*geKbJCVYR;XS0N9a>tl6y zdviDd4&22R_Jmh1;6I6x_kRevM$m+V=sjeiQ1G}`;3Qngl8Im58wtRq0a@cy6$`xV zF?HauAu=vop(x4=^+r8Gqu)q#L60G}!fN1?zK5NxK-`2(nE`^CIr#d{3b2cjWP31I z1sYJsd)nZ9uie7E(R==v-?L}Wn$VsC9;6WdZYyDM@lzn+1KtqaP_f%dqtY-^{;BGN zbftXNg0UHwxuWr{K+GsgesDum1QKK(@t>v=+&7iw{cMBVc(JY%4=IkN9nDiiF zfHq_~BZDke{!9Y zGaxFouUOKeDCi)*Wd;Kw${`_gD2j9M8?v<6%ZwlfKq1WUu@sFdUtAF2hF;UnalRER zx!OH)LdspHB!3vzp$Ja3?l+PGC(t~@9%<656l&^2P;l?^ltux=5kqoyEUJbIVS#H8 z?;R_{g*^m>rih0);wOaco+Jke(Ia zLVSqHvmI9 zjTRq%AC(BW5BdH+ePn2rJ~Hxo)l;EBil>ILKcX)#n$RB$i3zVhg5;WXg*;G^g%8+u zFB1ZS&Lmp;$EW~F)+A-u&F7HF`=*h>n}!LOWWgxIQXN{_MKdf2Z3P$wPdoHqSSA7x zU+J(ye4*G@BO=JJNFCg!B9il?kmx)J^>p;~g#-x6o zX|(i=;iq49RF=11L(X~OtzHoat(G=~za3MtHa$nG=EL;G=zw`bJxKe@qX!TbYm;_J zJ~n*(ZeI>tp#9zO1ZhPv4?`(eVCNn<5Q{EP2qczN^Nnx5KbWw-&0W=#kH=je<~ppA zipPbqtKaEHA3$J|a0rYJ(AADDzgCzv%7@$Y3fi~e}g61Q+SXZaDUhPte zW_Gvf6~eMIa*V^THKR}%+_z(R?YBXpxOAH%744RF<6}YlbMs1 zwLvb$ezrtiU*x>O*26DPO3Hk3aVRQ!rb#xdZQ>t5tWLkWSijbOX>)Y=35FIuZV87< zNu^ow!Fx3;PDVoz{bJNrzBq)ljq~R%>MY1vom}P zXl@ibwRN;07g7&;Cc54Y92v#0!)m7A+Al(stTQ!1|5wa5x`490#uta6`!DtV5ph;m zxSLwk&2tM!whDe!M2Xn=)7P)c*18_Vw*{Bz*Jdy z$|_Md8Gubc@$ zj#zZ#oLRtb#cp}eHZQcXTjlCm_UkMS7EV~}w9>k|e&Zsw?yO>H|MpNQ@#PT> zuPWb>qP%cVQJSmkaU>KL7niJ4|JEPUc$?N6-&|(5bTCt&qW9)8A`etGTQj-j^$N$g zor~+E@uo|QNv39cZnv_5zu)oXQl@?y_$?86ItBGeH#SL2({Uejbd_1oMtEISZA~gW z7(gJ^@C89dOA3_Z*y)Kq)&Ec7t14PviE672r#Y_`5Xp}_K59*gtZz|>k_>@@`eHpI zsZaE^h~nf+QyrJ0wtJ%wM|t%K*k3?mXjsyQgjbcVxPdzz4ASQu`6q}^dIgF6KTe&j zFI3p(gD-X-crp`7;SF2zFm`;Qo#GICKayh&%*ELHXp7udKJ;!`bE78k8 z-zAODiF-hDAD@#xfG8X!AS0s}YRAXMjs1YafX80!T*>f80OqUH-J6xJuU&E}yRPfxS-+McQ3J^zV2vKYkG@TI z*iSuN0;*+geWj=*V*5nO_493S+~L;v?X|<+H+Bs9v{bj9siujEZ_l22k$Km+hZE9# z{yYZ`Wg};{{gv?MJG&)FQ12VyOnPTnY1!L+>wWzG8We~n;v7SGj7lg7a3Xb3rMt<) zMNds_%X+46)+zql2+Tb2m5QupzxO7ilfV3}vm6h+I}cWtan~L$z+>DF4JToBFavje zEosVs_Uw(p@q56kxhEu_-u{ZA0gg^+vUQs+gMxr(nV?*9jr#&P$OI45wo?Q{Gb98Q z&{FoN8=Zo}LpPlf`9oaxwZ$ZT(P*j`MOT)I#S%K!M)s2mufI1rkARTGWtbE38Ed^LLZL1~%hb1NgE8i}1 zsmV8QMDsLbw1%J*HQ9#6re;5~Z|%?b_c|lMy!JX(B!4`2p=Jnc5TyM$?+}WM*YS(cz4ZdNmzEW}dBElC ze5EG!w>%sr)y64T@AQxgCOsWtRVX>~F6+actNZFje-eKR->GBZgEatd$0TfTjpv+g zVBr&A?;mgY{O*hl4@({@g5Aw{?5#Mg;qu*{`((e9x(4NOz{xob^YFKlhveza!!xU`?>P9_`SwzP(EcRNiwR!{SU~S zZ*;Pqsk^{>)gH!z#K3QP6v1~+vk9St7ij$kk|E^p2X*8a$Xzf{Z38t;~) zBkIpTto?!Q)=J#EjTUNth-XCexxLtAw~jklMHWIj4< zUYC~_N4gl%NsVb-3mkG;%rO!5^k6BG*K=(#;+S(D;8(vr&zwMCnwXcaRNGXSX4oD9 zJZ0zSRWuUIow}jbs{WEx!ModNd2u!by3F%&$&h4Ymv4!-?XrkJ9GowJP@Wa%K~mzfaJ< zMtdkHA-gi-%rh+q-Rgl$X$dj6{W3W7%i?c(%kjoANCH|NtpcJt07NzUg3F#)k@f^D z%SDSv>DuqaGRd^XKW~PaZ#h92fxp)HG$-KQ=Y}+71`b9FY*O!W!=_)!E!s z&6~YXFst#XsEjA5wm>o^y!hp1MAjfZ zvTb8ISD?P6Ruq7#3lhY<{ZcW7%Oyx@Pcb)?*GVeM{%(f4~`dI?cBuevgX%ypH==Wv41?J+>!!!U_4AO?xVT{8*}Y zK_M4N=Be~PTJ;J-FVf5G_#zbzUe9%}`xRJqhs-B_zFq17yBzT)Rx+RK?I@}(Q#8-?F)-$yFOdr^j&cGO|I65j+T6hJa)mv_BkOx#F z?CRHZxc~C~IaSF!=Vl(w0gZsdr~^I`uuC(_B9(%j8^+Qi={KIyJgUZ`4}I%{Z!#rN z$SI}19ZZ@tmFU7sZRXmNIBH3$#~Z76W@n(u(uS`|T*yVmEjAa|($cCO%=>Z`Tgb^% z9q~Q<3r4i^^l2)84tv9eu?j84Vn?eG#-V@Mit_00_Kfk(8wMUn*X@&W<>y#CX&odq zs{5sr<$;*ME;@u+sabkEpYmf-cgc92s*!-{3k4R+@-mW?``!LR`zyJMo!OgU25q@r z5PCz%di!f5H!pcgE*O>vO{w9Zf&9`2MUD9Ry#_PHz#h(Gw&8-Vq{03Tc}p}}x98); zNPGWy-PNV89nriI`Iv8FdC1m8Ej0L9ENxq3JD@OCN)VcVf%+c!DYC_1S6`9)V_8|( zBHuvC$S`@kfSOM839XIFK;ibH^Y;6(CNKHmW~Xwp%pOI33}t1->DQYJ>AF@dHa2=T zojh6ZZbK)_3j%{8lHX8Ns1+qBW^TV~+WJQvjZywf9O>2uV0(D#If|JtJLN!vMNu)DH!P2o`-927<}R`{FVNs1+$JY7AIHvty8WFFgJ zx8Xv-{8CHh9^PuYdWV1@0SGM9&WKZ&Tj=8NjMmo10(BJfk0K(0z+Ur=@B*}J0OpRz zNt6#1gibLRJ4Oo*OD?#%ISN#p_&?2pO)25!rU*v+-XukUD=4>m3wt<=eZJ?kb<1Iw zfw`#T*+3~J78rQA^|qyDah1V^P(qCRh9RcoTTlQJdEJax^|gNgRCRo_gWXDiT3{(C6kP&3PvzB!XjQt=>9UrA0s_m?JFgdULgML82PE#cd+#tH*RZl`s4$ z{mT~%L&FPJTly@AfUuo0DNhP2qYD$7yYPO1xBkR>|e9&$6c^c4+~Pn`<(w7CY>8>3t2 z#ky;YOEBj>YmP)~okol1ws*dVoEyc*;+gG62hMxCMn=boZQ(K4Ipa(z{B*aMG+E*x zk96^!PV%UgvuCPv8(fvC|4GB+Op`XfD}0ZN>PSBf92EgS6Z#KJ1a~I}jk_?f?gT(> zq&@jmK9Ap@s%GltwJTmXSnJvV)4hBR97PamJwwQEAk=8qzpXD;D^Qe=ZE-m+f`$Fu zs8VZY@0aPG^^yv*NcRw){<~UR^7#_^9>qQ82(;acUE-@)C6p(*-tBoq@Zr_kayU4M z;A|r}?PK*x;u_5BUlHMOoT}L8aheV?%+Yw;=)KN5K<~bq2<|JYcb+-ASR3%XF1^;5 zo6)#FnY2>Wtw$ywV$xU3`=~(jSf}^wi@Uk4M_r5hSc(4L7Up~&NRj0Okz7y%=hW#% z6EK1F0feZ2IN;~!2a>mem(3-dbY|sy@bZQdLSkfCUndk_S~}sPMrm$rR$k?sSP?Q~ z_&k1?yE0y{xn?rwMJ&uQHzB0pRJ%l2mB3^>uK9SVi+~kK{G`6!E^};F(`H`YE5834 zSe~pnL8p1&QLAFjlGL`{J9XupUon@>coaks6{&xgpsSpB+&+iP=HOH$`;M@h9T@Cn z{f+x-pFPY&($&?#_UG1_k>6i9<@aQkl+${*3L4bx&7--fLM>XDy;j6&m91zO2=Ikk>@;*T|og{Jz^GeQDNcMI;X7wOmLovD<}fi z3G&HENN$YvW>+#YjH;=QzJ9%^LCXwdA+wo;PdistgiZtLi4pH8xQQ@1{Jm_;ST2Ob zq>53G7>5LU=Ruw59-R00#3{TetVjL(g{O+e#m8h~_)3-kD)9VT85N?UFfINZqR_JL zSf_^y<~VBzY9{ie1XW zszwnWUspKfc)5Vhi%&8i!DMOXo7d}orN*Z&W?4BXvlVw@VOndcA&Byt_j$X-opR_y?A@!NY$EIw4DHU}|Z9m$Rn=KtIMFThY zkPF8PCmm$sQ+e%-Ho^!}MHffl%JQhIH`=m@;u{AEw{g&oKCm)%t1Yl`aMH&+0oqpU zreu5Uw+t!D1wA3}sILZq52BA+*)lj-uZG_i zY&tA2+Eb@e!!W1>XCUbSV*y-*fb0JJN^d-kerLb;-OwLw&D25TCa#oY6zJ7Av?@C)$nPO((`(ACw(WM zaxGJ-m(zM!9Ep7H^O=ufJ<-L@!u{ara(70 z;ZLne81Ydh>ij;NBQ}E91{{fCwG&3V%FMA+D;Twk6ATb#gIaJT%8_urkQ!R(Pr_PU zJS;CiDlcEbu*tsmbkla*d(;uOF;S9+xws}047MV!*5W~!8P5KQZ@^*2V7YOjes_NH z_d7{%T#?&S_`2UCOHt8j-VaI^N<#y4Ua#UY!8ryy7y_G-twNcdiK9M ztDp{^RRJdD?O-4{5(6-y^)5E}1T^~R8*YAY$;s_Y)k0T5HDNrT3o1_5qs@yWVDqSz zYa)G({%SavVk{FhnxFMO+n#QcqEwR}{32p*gPD6rmqxCZ_PP%;lOmNYP zQV$L_yBf-BcTNDN88=7G&;gF{>l37}kcww0AyG!0XcSgm?{i=)5a*!L2_ z*~Z`?HBeB21c0Q#-?b-j5O5uU+Ucr7`#Rp??EC=iyY*$HHz%q~u0xbL<5tYgb9Cz{ z?>vq6W^>oqXFel(gQ=xuWW8Yp zHEfe^t^HZP>S$~0X_02R%gH7bl!SE|$t^r~9RE>ZKcY^aC$fZ$KTpSRTi2~>Rm5mzN(d%d36;#kdgpj_cv0KKK7=wrg z5_xe#KR2mPqQ;l#a)cGl!TB1vYPt0fdhxkJCA#Xg>+{vVQ z@7QyJ+e0yQ3_cJ8Ie7XeQZVco+pmIIrd(M z>v8mXU*F%juG{syU4MU1x7+*HJI8B0pO5Eb-S3abgU%&EzSd9tJtU~~_9laqw2?SJ zo}b=eVyJW-6ML}3-q@zg2^qIQs&l-SPhkH0{zM(H_95!f_uf=ecPqOqTCJqoTe`c8 z5ItOdEG_LNFJIf(IK^qg!>;qyYhKyQ$!SB|dZ6@0UG99(lJlwjt7KMRMUTP3&LVI5 zAnYz)Q!7=yI{{KZ>-q*_n5S?Leapq12o@mNb^dU~l*9@KzIk&BzZUlz)XMP_;LRZD~~0OkyH*0>m9wb|LKg%hXDL zRQe=OyPzMD+J)K&gN0L5u`Q7%`qg@>&;F#Tu^7Hug*a4U5gi#5m5#zx>y|2~*M9p` zj>`KL5wsF4=*+y839-fX^z@t%TC9Js2+Yt5>f~ zjQc?*X_Sr%Q{2B5!)>p{v~SQtj$#=3t`LvW$e|uB!pwbPt@hX%PJ$YZmLM8V=v~+v zZxfvAiO`ewf6O-UoD0G|TZ?!RIN_1{n#b*e^4XL~!-fd^S+;mVc*4@zjgF3Zp}oWW zmyp-;I^IG_pUd$oF!uW?hV=RQ{Swu;W*cyUyVG@%wuT4eIcn8ahG={Z#PYMA{kE9$ zIBR)@U$&XH&!3l^v)MR@fZ50l!9sSK<>-LZw;!UErDh(@Od_L#dw#5h`*MByly&*? z_rC#6M@h=fobx`)QKi?f3yNYLRw(qROiW<;&z?Q!@B5CwQW+ZDtanT(Um@M`I4Wh_ zi%^vJS7l!2@wOLAkS`6CPGc2x$Q`h>J{L7wb?nu(Igdi3e)Be=kmue4&VmfQ;CPF#0V7=Oz7?HpMy>- z%T8B0@Xw|fW=tAh)>TUYFiBdxVe~WrBEJ3#Y0W!AGaBKO$WO3zER!13r-i#-ctnzAt=bm^#t6Dfu+2Swso1FV6QHm>-_a#FtJ8F zrq2z^ARa3zEyP=?g6Y*jC_N(L=H*m53del0kb#W-M`2lJ+prmdj0$%cZ~6NAqo8w7*w1kM zH^)2mR5`e;%XV(OsmO4d24dt-LBrJUH~Ca(jye4PGJ^*V0W($E7Xc1BG9wYM(7iN! zw1N?Ho3bTO@>SXMf)QY=bN1Bo=0DGpq54THD2%ZGvqj;zd{T`_1BiT)olPg7C*GKQjhaut2&+=%yM}Zjf?=ew8{iQ52Pj(=sVk9#qF}-|Mweqb{?Avn| z-#>L0^#UHK_H73Dmb19GyoAs#SAAjF>6Cf;WgVX46`Vgh#_q+!v|DSG?<(}*Y3Prh z`DU(Lct@=r=iYo>U8N+OvN*fE<!ShPaxWw^NcQm6vP8tVZ(%}58LrI!53Rli5KJDeX z)>v>VjRA)iy5T@BB0oU@0ttu+(q7(wwMX|lK%P+|>8F^!)Ty7NC+H?G4&A(Pf^K$m zFg2p+@x-3aJCqrFWaIrj^S@%7T<0%d?7@`&rV^_oyCD&iaDzc%9&hXv4p@9C3BY2; z33w^xAntJCe251O)iX7|NMK4sy$Bem>P6hungal0RI9~7jMcr|*C@~7+pST(zK~)6 z>WINC?@PG;aZg{Jgqn9#Ls<8&#ge|hz##S>|IM4FOtlSQ>oL>f9`FP^Za%?;gEP+lvw8l~ zB_e_`ZAQE!1x5+%&!1><@oV{brjKy2@ISbfeR;C7s$ccIOoBPC+iN26H)P=CT(&v)b7}xDX>tCQbbEtCR13uIBTE5caEh;ep+4 z9(J6ZD(rfeeaSLr?@}kgUv0A~O*WR0;9n$UQc0&^zd*l$G##Jh!z2DGmogeeYehpt zbA?uKy&Dir<*$*b5=VV#XCkCRAl)|lRlpry({om+5l@WNXq zkGuhlkNk8uL<@8`dN=|3y+-wW~I3-Nz^G(vu% zPL9y(8wHU)=x9+2k-aIG$X2gPhwzS0Fs(3;)!-DSL~+~-ym0LP)_Mo@+#9J6q>ACT z;PF247=3&eFYbwgLS!oR7-A!!7ulO4rT-009$~~ZX0j1DZQh2!mx0Qf0O(l9=ell$ zn+`QUKM%b%D&0Uisp7M07Z2qc_#AEkGY)RJKk<=$pXV0ds$w7|Hw;q_fkx0IB+!JKY89FH!6@uldB)?6p83b0u8pHVEAl&F`dK+Ry4ND0 zi{LKvHN4e;E>l3we*Ai#`wY5YN+M9f&==d3Yabd_0&DApo`#o^_Lt8_FCiu-28Gbt zP{xCKulV#6blE!^c2HGS1%8<)6)~QR_2yg`q&U|*j0>V#V7l9D#(%G%l=OJOk_UH% zpCz`F9yCPE!8jV7B@ZF}r^gIP{WFSro6s7)}c=JiqOGLh;_c!%*Gj8B*8p#hVS$*Lpn z%d5_s>K1;`Y_BN#cGC>zxnf!LsJ+5-Ma7lzTJP4D4aa+Fs)M4dub1_Y7ewuhUM^_i z$Fe<1&HRo+abJ78YZw{udXJE@$O@e%Nl5RTEEm(v_5OR-S%S-HJ@4kXiZ1$5x>X`- z-$;GEi}xquKJ-1q3B+>Lt-D=D(p*upJTdYFd&WMYh$Qj5nd;dn><*HaYt9bHYL6aH zDsPP-Fic#PYQ2i5^MBvA-BMhK>7J0vGt+X{H>tP&p%Z1v#5w!)1_r>j zi|CxRsZ=Y_69%SKw59m_7zP7a7lXW8SIM2upHH_K3oELAek5)--;yLdF5Gac!KfgX zm1#FAH&^%7E2CHUy)P|^!do)kH7M?of?@}7{J!*2Mn*>36s$!R1P~y!Q7HNZJ97v~ z5s#Q2t?zy{DWYv}GNZnBjpoXWF&hexz&*m`G+-%I5uGB7lOu?^h1GiY^_gmKlAELT zy?J7|xXY7A#T||~qU3J;)q*`mdHFYe&9e%4Okac)_3knYd<|21J_$_2--l;^iareu zw<)4+ZhHD4#*;=ytwHwGPi?)I2PcMetQshKhNY!EahHhjMn3yC7HI82!_;Tsup|e( zI66Jnaf{wE)B&h_T}JDU_tYpj&*HTSwQg(TSkSLY#D9Ek1J5WqCer#8h!SayWdTi7 z8@FwqN2wwF^6}Jz1qUw?@6j1j*Z}FqFw1xxNfqxsb>>z>g%CKncw}F1Nrbd*d&&nz zY!%zV^CrC5d%({AQPhV`ANM^LRhe9n@?tPN0tI%y~xX>Mm;=X9bXLA^_j0-dD zcw`?vM4L(~gqDq-S;Ojt-`x6pqt_YB;;^S}^|+>vwi$^TiDcTtxBv(#JZKlBzK* zYIC?naR<($66=ewC|YpvAUOM)Bcvt%Uifv~Vgdnpaz5^50PdOX|9$4NfLk9-{LYA7 zA7@856X7n|e&?wy>ECZnvV-f1x2k{J`~5>}(Vqci=kliusGc1PkJ2t2idX2B3~HGKwJD>lqp-WCp3(= z>R@?2Qg0Ax9N0JP(|Ndkv1pw}Kg!@}{qtxXjaOQJyS^8n#WPm&)I0h1=+~5{d>_>k znFWOuvSc5qxV(?5v5&Az+1)x=QFEF#NbWUcLq;*N^1E(*<5zH4*0DY)%E$4ZUw6X< zry6q<5z(ch>KDg9qe8##9&{x^04+1(G3@b|mgu$Riuj*ciFCuBdL@-Vdw=|Zc-^e2 z$$Au~RxVEAvoqhTu-#e!_>+~F&Sav*s&tE#IJhc3VXVz|azFUmT1@~MCt5?S{QrcS_+jS%gPO?5>jDTT@Ii74|Gw{0o)sDh7Z$vx zBnhZv`@MAy9&4d0cVrI>Wb#t8VV85P<}|2@P1AkLAmyiju#ow(`Y?ZLstFKkJw8YC z+P7zeY+eaHe(Bbq5NdG5EZC~=#qI6NeKoR!X<_i+x7A@jki1TX z)}-RSW`AA{Wod!|A6lCXTFIkJ;t;k_oPXdQK|X_c(Xy7g*P`SalxQ8(Sc|{uKrw=} zPhX^nxW*}IW{|>E{LL=zuJlW1uWqC#6@CG<5W)*EVP@jXwboVF(h4iK65PU2Tp>>( zBM~GuTsDlGjC-g8kzn&lCJt<>@}k?`{Q4yft)jiEao|0qY<40Uq#)^DHu>E@{B+ov zCnEMKRy)hO_!o28Z6H|HuRcCPF-V!iZVJD8?(>Cp8ijyL?h$Sa+Bgwmpd5JS^H8J;IV7u{f*CdtL7}dFWZf=Ab(oO z)TcXtt>!9u#J{cEf+k0w&{=K|^Stfpa@IBmW)8bQ@v+z9GXuR5XML}`zH^h@7Zkcq}LS$cYQih7`8Pgz_XOU{Z90IW`B*M zr~`LAb!y>+Ehwb={eGh=LaBC*FyTFPI4`z9-RJ1uy6CtdkDt_~s(1rw6>m`MOX3~J zAGV1>z!;(j4}fyUyyb|Ns2QF|ys3Lp>V|T=%fXHMF;6N_^~FfeQ&*SL?Qmutd_O`QsKrwYTYi&vQVSfFmXXQSEJ#tZ zu;5f_tmaTr9f%Tt=`8;y{Tq9-@_WT=x_zQj&)Q~^(8aoZo@I~XMR@#0Z#xVl(2o#$ zB^tXeIKzLH;b4Dj-gEyS{Bxp0p8IrbYlaLAsScQJ@0}6%y`j>x0BgnHRk`AQq)9;k zRQX_}@*PQEZSA9)+NGF=m4SkJ><;4gZBI~dF`~QBjc{qX9LcV|-PN1EPBpl*xHs*- z!s>P8dT=N7R(2ex$&$7WjSkZK==TSpS}gM90?MIT>lgJgz)v>1&}zQh3^~d+N{g`C)8Z6x?c3%$h*5kHNA5501jrXns+AWK|m*%54EqWenwPrn_ z%DZw*I`|o+toJ*-eMt^bIkEgMtA2YM#5wwOaElDhg7&%w!J;2X?qNErgKl6kQrz1$ zL*>B4C$E_XItn>xDtP39s+}@kVU#Zk#PJFy*$5FTvtbl^KrulM+jm5W9x)Zy^6``~ zq_(Gw{7=lQEjLfaC&1pJBOxIHHXxug`vJ|D!%O2Bq$}&vX;g^{(bBrY-bYx*_)n&T zT*jMoHlofoO!Hzj5`1*F*c$eEKy3XvW|IDB8aWL z`LsKPK?+#%^Z1u2v!3PEpxeG*--tZq+|Y=KtrnsS&}Er+5^@-xWIW!FY+lWAkkGly zo#0k*RnW5})*!;qO==-5$v=>Rjwsyc&!0cg3STZx2!Q2BJnSoUjk5H|t+GllO)f+X zm*S_0EPSaT*-6S=n05HI;QIX{Ug^wPELi zo}L3RRJ@cco)hQkC4fjj`lqTA&^LvOjUcQQkh{!>G9pM4F~iPi1P!V96CQM-J`(RM3{pHr1sm4Q~<@k&!YDlhne!`>r*SjdsASZ z_n|D!bcm1M_m`>1%w%x9ZvIqU1Fc}$OBpS@^^KMQZwd@Nx;G1z8b62R=6lF!qV zQ}eAF=nOqlNfp3JYT$KY0pm?m9J!bi+B!@ZSqN?~xx4h-0WmGx0e(~Yf8^A+@rj)7 z;o-)H)AFb5+{}Epeuohm+Pq?vM`!H(k7U)>RhV9RkyaK==xVy1tx3-owzJUt5R!6%Lal&RGiJBosD4u3;ngMUfY({3}@cB=NxIwUwMU(^La$j@uq zIrff1?|pFa&Z|ep7ko@@14Kg&OOS_TQvPU5VXM1vZDsk&@f|+VwqfP1n5#Y;sc)(QPKyyrx|fo4pD zzN1^s;=o_N;|lbvSXt;}&~u^Z<5DHC#k9?8A?G?D5_DB*u;-uSffP$AAD|638$Cl@3NiFgEYl(1eDCwb(m* zy~7Eb+R|Q&;|eVgVlaF>Un+tl!Yyd_Qrd`iK&*&P$BT#z{xzrkS7<)6-hl!WDM*Q7 zm?~Z^5Aj#(+3>`?BQY~GgUKaFhkF}TMW$UgQ;k)%IPXLHr8Z9Ll%`ECBo8}QZOEto z?3Eh6LY~MW!a}o_RamH-sV*#H6IZzk6iUi!lVG&E+M&y|tur(ENtn)54+Cat0Mpm; z@PH!+MJj=r8cWXK2nbduyxr+ZQLkB;xJ!OZxp(XU@>H0J-V{{XOG?Lrk!s)8;jf-$&I771-^AFvbqr2Z`W! z_K>q)fZPiDGICZhvuyPp!B+$2XugOV z#r(}W3Kce;&nTY7lM)m`rT?9pxRGKnBo*!^^Lhcr>&@TkogGfS)M?gJgXy&$E}Gn6 zOe}LE6aS%Kr6XIXc95;{J>w#W6Ryr}>eKb0(XOjK2AlieJA?}6qD;WLBbNsqf%YQ0 zvDUD#rDk>$nd&WxD+K}nZeQTS=<}n{2i~QZ9zA^-U9GdTY_O3bcb&~$^{z_ZY+C)| zlS-ruhiBuWN#4HYoU+EsosTa}>Mwi;y4xA*Z*7hN^f%KYH`#5{@{6FJwJ>-dg0_&)@Dv7j$;v{ ze}7p2XqTVkC6}pfi$;n%ZmiLYzqj_m_w+d2g+dGGd-_KmU%w)E7DEu9Him$j={CPO z;O)7e4(vYvn4Nxhb^hMoFx>8FIex8p{;QhKWo*fIa>g2Myo+J9zb$`hnao{O$&4J4 zF?LP%e9Ry^CCm)N$~?6KgUCgeT!_ED9U1}!DZj#XEwDZzp-e71T$j#XdGSVp~vuNb}gO9J3-4Chij(ZLCg#m_t_bZ9HRX^HQ2FBzkpPJd1JN~=W{&tL2<79Bh zV1*_Y{ZGs}inqXrjG__2N{9Z~yuSf{%>_Gq8^_(&8x}Aj5`vo4Siz-o8L*ak`<0lsUfu4xg_)$d#+Lo%na%N1Z` zxS#MDlm9UP;XkWVld|nm?L_G&lSe5jd3J6qZ(~N&I?fHqApSg-pS{^Qq83+#NGX8d zr{#=E$)1S&geTv7E(-Yd7>BY`hV_lrkl@}M;!h@;EOCa|(FZ7ZlkKrBChZj_HUBgq zOS2Kmq!Ck_E4}GG6|Ni5kj`OubsXAG^{JLPlQa`-L_R;t7~F`&UuWx0y-4i($G+E4 zeT8)-ZgNDuEwf47vzp0be0&@x{0O=z8U=fF>#0D6tG&364iL$_oQe+zeul@h+pw&7LOmbN!4|3bp~qb3+XlLhwnh^1 zUhB>q#=U7Dp=n>c?|D%=fkMN9d~TbH%MgnPzJKq|C?_o^y}wt!GIeF5*s2`+>zqyH zBoXTMbWG(R8x$K#hG_Rsu~p@AdB+GrXdAhpP22#?ABTdFN&}-G9%SEV&*H!HZLHH` z{i1S?SnqH;a;UX6bG9S(&TUPg^-IV<_VaWOV!f`O`Nc1~Iol}sw{hOHHe-IT)Y_>+ z=VZRNJ7MViI)wLd^xEOucZ{c?B`ZuyU6P3;M;j2?3{L$S+vbf~Umvp0?8VW<(>tIq zJms(XxlG<7lABQG%Pxq1;L@O>x}E6|l(tEp>ZHiu2@L6M&5gM8r0qwL0E3nXz+u~g ze_19~Xe72F5eIJ8|3Fi4r1)LV`V~>1J@%)d&gENaHr>0)g~gZyHic0xDZ< z5a@|%iWOQ>ku0Yri>FT^SLEnXfZk{34(Xm>feF&i4K&WUP7u)Mfz(Ft!za6+hqu30 zXKWurNd|EYZ<-c&^4;341eOTRMV&jmAUpqK#cknB@+C15 z$|=6wx(ft9poNv_N3dmd$5tfcD42e2I6*uQ31oYr5}tw^j3%=IWd1zXL)A`8aUG&K z8vD_oKgLUFs!#QofTeCbA>ria21y$#7(&&T;|a0w84FbLLicS*++@pqnHnkqy)eqh zya0o*(UGhzZLQEaTGDCZ>OiSIaM6Gg*@c9Zq5fO_%2(g-^YStalz}dQ+6t&E{}vOH z=e;xtRI&5+GmX3{qop2uIUOPx?9Ve$j(b(yVG+I4Oy^AviJjxYqNelbNoU(5^jCn) z_|SSe+I7RuW{9uE;L$?e#~uoHXpEXlM7_J86b$<$x3?FVm__Ha+sa^OYLGx@~<(krwg`*jrFN6Ug8 zgb?+}!95OM7&>R`48X`_aAg~ohRiNrymP50 zcQ%?8d{7Urs@REJpCc?flC7<+m5YL`Xt9$%(M-jC9MZ&sOTrcMG)UW#2M%e<*MhoI zZZodvR0%RB?`2mON?@l-oyMaA(&D2qyUjMZ?aW9gtpX3>~(UgDF>WX=*V zORaCj5HykxkcP?{&m0(5&D7r_4Smq$JGFCQG1JPw;@W;tH7m?H8)e_#8mX6|J8q$o zyY`RtG+wLd^Z~T9p3rc=hqY&&ur!^s?UL@7QPBw0Ues zQXDZU(Dmf4WWA+{L-rj;90OxFHrBLlhTW$laF^Wt zK$;3;X0Y!ljAf%jWpA}(w-E6aTm1r7swRl13a!C)JkT1o;k!Q(jYx%Y`{QEdFJ|*s zJBW?&Ap9*Bra8S816p0dX3u)cO}gVXy3|;wL0b34u0a;NL);(p=Cw?Rf&3KWx}r?y zMy~^IKH7eLLk79xj>}S6+LdKq9~Zq=e-&lUwVA}3{WyJa>3a8*BBQ~E$kwQyM!kw- zC8@sA!hMX@@~^~S42F|sQc2ior!!^sR?tr-NN{;q^mz8zVUW=Q#)L~?Xd-FuQp2C< zT^Yung#~H}r)ykHJxBRidBLJ5^p}Ei0+G9K8fbV|usiX`h+{Wwda8)WWMC+*u)5c_ z=1W)C9lgpp_pvw8Tez3~l@d%w&ZF$IWHQE`){ewJvCv^Vhxb!`d^kTpMW|^k+az92 zU1Mcq$;JjIuOwz=dDQxKi0(}-ohS9eE*5N=$p4=FAd#4mX8N%%ML8XQWOVT63}Ly0 zCX78mcwx=ii>&)Hx?i?9Q418NmF#*GB69R9jheR4oa<*ZX$v5ul9o9jrlAb1Ggm-l zq&{1np0*~!+f5D|vlO@wkX6Dcjzt_(a?i0~g)FFnWESXqY=erna7C;!v zjH^<0u+f&kSchM5a$hm=G2p5k=9E-Ut%*tdXnAjeA<*vUi-Xahdkb#yevMID6zcv=3+1Vr>pW!8eT6 zQ1N=preCreZ5Xr%voe#9*&>U*wiZNnorlSGhEdI@PFvA?imV0Gd4CHlLN46kG}+%w zpRCulJ6I}WEFRdFE-s>NU{5I8S>xe*_N2IoS?YqRCTo7RLvCyih{fS!`6 z=y}fGj`Y|$-01P1*9AgIxD@T)uOifp09V3GRqGL*gUgq#vbgc1Tse&ocdD`I*SgNS z9L~!{ll6UjTu8J`jP2pupzNX@+jAe=e}`m+OI@*wRHpVNy`N73w9Z1`*m~4zXLS!pdRCs^L-hFEc zy=_pqdxO)a{!>i5fJN%Cv*@fw^`Pshr$q{KZ98ag(D5K;n4_@Pw15RoUH!V#{J;fG zeeWjy;xonEY8JFsAj8?h67m6kfo^$?S#%Z5CKj9Bdg!{Bn2})=R!ssD{^VA72K}j6 z&2v;nL@WK-CSJ2;v9d9@aaS8GuJ;sTzj7U}r7_b$$sKE??L&PxVXLt5sQZ*tnZW4w zhTS#jja1slN@>-vk0{_wSK%g+^v<=4 zD^sNo2!?52>@roxxJ(7Y3Pcn;=g2rqar{9~%wL{g=x z_!+|_zz5&OL{QYo1Bf1!IBEX_PwT1A==LRO@Dw}vGci$!SKy2(zbpObhdQATsYU!= zr?e3jPmB_bv@y8vK1%tIU}_oM%C}HbI_JXmKuj>?f&qd}*N#TAVHO@c`DRF?HT1vq zL-fx+IaTNiRDKy_gL55?9XCvtQv)`0@Mv0M8`c zC!xN2i3)uRk6<{lYy9@@(xB7NS;)_SzrnsTW<8uJKUYML`z?-&A3ywIO~1gJ-Ynj= z(g*nj2E-o`a&&nK-<7vvzwz24V00||%I6$iVV~3`Sb-&dw@-uRB`ycg?xFG=9tU0h ziRulvIoPwhPJ)NGH1M;ghRxM=oB9uqGQ7RkgN7tHugQgp^8 zuh8;W{E$dt^{2l3I*WS^U8N7Kl0(FjVP0*yBj!q=Th6JUPgy@RfbhZeEDAOvHHiAV3=ePm{#P*YdG z6Ba^pGvo<#g!Hrk&ug6zp#4a?&y0g)o*^W3zQ?pWy6aT8M%eg$@Ql2Y-UtW~{JU^V zL8a{vJdVBSzng6O>_jfQawH`&q#ug<`lv`hFnb^Wqcsq7yxWj1dN8m{EYj$B<5FX= z#07>B+O9d?^$o&du6!D_R*?QuDe_Uv!mUbScHg&8erR(Ia*9^Fb46obnYQ-Z{lFXS zMjaNjLy_-K^3C^;-TCzK3O`8p^|g?*QtBy(V#MYM2KUxvY*IHm(PqfOy^zy?0(RMH z!DEJx(NoyylTZFFxWdUt^WXXNukStm5C2r`%Pm~22cH`U(=4wDVR;O~W5DDXqwH=X-po=#oQ(fpDF zj8)4lgQ1gb<%{`)Dn~2F*y?KRl8rqXv6#sWPbge)YDCi{R_(yb%j+mTH7+{yx#<_f zU}3G!GPG(3&xoV$R5|ZrR;@IobB%)Cl#e$^EzcGi93O>hXkj?RiI&GHzKKP zu1kt;7#@1aPlA+;oIK8H(2Tnc1x4sdK?2N3`XYNb!C3#1kqoz;WzXN2rFy5(04f%C zh#XAu+Vx6K!$T5r=7{}qV(+h*_ojXYFyJU7gV~qlV_mxdCM((= z!}a7uH)x~zXTODcJyE>bRG5Oi{s4J!Lx<2ttB(JfPS+C^(#b~ceYghssq^&TTqZs^ z#+`aBND=tBhazipdH5i=mZ-&%Py5t=wh(5dE2Q4vfq~_}e9p}ZP`_?x5j`RCcBW(~ zrw4wJ5Q>ogp)llM~v&{-#5dY*SNMXjm+8)So#*m$- z{}QS3Em9-YWawRX1Wvn&rRF{ed8VVbB`KsA_hd@o%cpI=wckyojO4&yvW7l5hTo&M z{}}qmI*&{rjG~<6dXL=QZ~4aU?RgSjz`uI+_stL;{~p^P;?J%Jv!`chT@ThkB1MG@ zgSJP}NOLr`tpv&nx#Yc=mw`M3MqvN<3oPLU_^+StpE3yqL$6d;ci`xwPtucB|xGj#^EdX;dggN zMn`5w+2bVLq%Iw)f4J0c^;LPB0txqXkpwe0GVz6;q~tB%?CC6PM>RFChYxd-UKi(* zZEZgxIP2o_dY8nT9=L*Ah0|J~@x^JVDEIrjVG^z{CRBFul68LY@OE83-DR)|mT`^Pa z966CK2Qe_FNFJ+m zt4+gD?FT2ek4E}tM6|j(xib}Mg5#}6&y>`*nr7NciHuls*+RZ5>BV7~UI#sY?7A1d zu%IJ#%IL(fc7AVVVjor1jSaUrqb0}etH8os^}fNL=1IAFgmh(*S(vv79_!5rX*m{_ zOpYI7?k6X&(>7dPgFQ3DjuPMWOhHQvsr-TQHr%UE*-DJ?={v<(>C%jAgRD3^{F>+{ z_DS%QoLW4A4=x=1h{T&Hr9u^08OewUHV%9(MUIGlSPRdaAsDgO_3zJm|^q&;>6$sIG zI1-3S71!K2vlM)Cs-zUP;E0mEZa0;4EMmF0@XSgKU#o}N=VGDg-?jebCvkIPPfRRE z<{ccsM#rm5EpDjmXR_~*)wm_G{rjzlk{nU%9ye}KFbfIKWio%N7qiIVS`a^A!0E5f z%eTaLqZyrfv$dTE-d{$1qR~E1Vz1tPvFLp?`_6rd43TB&_C{u=-E%J5!pmzaM4vr} z+-WB{(t3BjMMo;n@maauG%2W3NiYenJt_O~JlzK76cKAOl!b?3AvtE;J6Y9Vvn5qee?BgV1h9j@ctXLEEaT-rD1Gb8Vr zy()ezARFlLPD4#KOS9_GThFs-KfdE@dZlH|R+vta7mHb+yrlK@K<(fz=r0h6HsHli zlRGgEB;s@3MHrhq@Y3?iw2UxcxRul{C!btq)eX9oF@1ag0=+fWBgDvEYMCMMB!# z&&eQ}4!RE#;sl)fZu7Ogqtt~vBmUo9UZni&K6NjO(`0US97bHKDXOY+Vv~>~`*Ur) zIK7(75Ip2H_H%Pn4SE7~>mR!{1Ma3>v@o4#h@1x#s3L!NzRR#KQPKvBUD-Q(HmO~t z9K(a|4cAxFqeWyb_7|A!FERF{w0-56ro!$^uCG6a$U*aJ3CzLU(f7!+#O~7{tW=LW zSB1ruK$0=CAxL;*A=5-QDj%v|=ns~54!rjw1-J)>Saqvjjkg#!#Cf)HgXpJJ`9aYnN1ToZpkHBDnT@u5#mEztQZ zLe(YP&RjiK&*>xfmI^NIgwOI_9)mPDv9Olfk6wzS`>19;@-3(Sk%9=n@9N$+{*R*j z&?#u8G2|r%1%#>Yo%&Btop&MIakvEj&=mIgSTE9MXm@6JO=h-zsh~$5w+LxJZuN{j zw75^1I!YNRxM8Z3x>c}T4-ekV)z5wHu|4uOm;F!6SBdl#0z4YHaK+&!74)KOenia5 z#4Iq~3{A1V+O{V=G~6CN9t{$-9;k3d>c0A=Ygm78f6NEx8VxQb_=pqShA~mjD|!XH zpYE!}!C*4Aj})Vx^U0GdRf4{`kh7HYnENiOcMtqY+VZt} zTW|(5gGIeCd$XgiO}8)M7sK>X47|9Wn&aX-3X$V6pGY_{`yrfb&COKuf>u3cj*NOv zn&6ntUzU=MxlixATHm8^y#B{9es_3fBu2<}v5l75mmG6EuwCi>;~&Hvo*$e zAv^4rvz~|Tl3E3?SvN9BL;$-VfBBu`I}2O-qQ|a|LPyz2!ACES z4q2VP4wC6<$F}#oh&HLRM)7?AC7nhpo9R?MlC#fS#7CRzFm|Wx8F4G9}LrS_1zcJ&v|VZm_R+&&hb71`OR6+t$3P{e8_dJuJT}q z&b43jc(*6s%WiiZVdXAZ;&~xa9qUX)zv$en zH1A!WnjG5H0*|&1JeaYshI$@TAtd6FIlAYTDxKRdqPOP@T8<7-dXx3s7DPhJC8P3j z9;2VGA5h!=&QuV3;J(ni{{}lAz~VIYGBT;1KNVmH#!uG^%-1I1FhB5p)$uZNYj1{^ zSa|*iq_Trx@}fb~<6+yiI$VDLJIKJkl;{QesfHICL(ZcLv@T^D+zQ|mW~PgJ~+ zaIC!= z(z@7LQGG${Aw7SZZ4hCUP0GFnoq&gnkFD_q29eS>}$gf9v0?p{am;V$F$%t{_!Do1d%% zeu=mvigRLjl7-jCYh%Tmt^}pWZSMuCWk~qzxh>|Ah%2FT=zWEWMEI~>^6tym#s66S ze!q#P@xOSU9xS{Nw%B8`-somX)zULAatv5-guIY#efV8^-yX01o@4zpZFg5kAv0e- z8&4#8A;8e zhMp$)REy~{;zo@e+31A);@M5)r-}EVXgGV>>ChSYb~v4*M=n zFwdFFJ*!}N_H0p0D?1Yby=uecJaVOKwdNE|PT!c9tUl0{)EqznA%jASuF?#3~X(0hM2mX-Rd8C{w=Deaq5@; z;fpoEFT!AK%*uU7=8B;D$n1H>KvfyT7)8VtfE)2+v*$UHs^zniNsPL-b+BYT<=f#> zblIM+5=+#zW7us%`fxVwFM4%PA?MNVh>EozcBFubc*u%P<^2n#_&Y>e-@5qPK;*AQ zIsEA2^H}Oik>|C3m6b{Nm>k_bbgJM;;t`tz{)vAU+Xyz9f7h4v=rB{i4SL<-5S5&B z)UW!vQH2A8AIqKDnV6;H`!ccWlP9^l}tpB8W-+jB|agc1hzQq^O;{^?N;q5=wBaSFAPqZxeEGLw$a+Bpg zaH?F3x==b*jK1>W_lnnM(n3bYogAe6J6;(%oZv+loiFk+JGf&iL73w(b=_oh(7->{ zy4-5uaPPLTn`ObU)1~$=bRX+35LV|+2F)+l)g14|55`-M6y7cTJ@QcHT3`=Q0Q^GI zKL>G9`Xh$-qsna4xcmE#nLb*XEx*?E#`zIv{+b2w9xcmjiDpL~RG6cLw%-!w(1}*b zpmG9R<6Af5v04G;jvrA17)VuxHW~TYgEwc68%jv+pcp$3s9xaIbS1Bua@zu^ATICz ztcMV3u-y9wYK+@Hhn@8j{h}Viw>~0UpYCSJ1Pq|GVQFsB2Q!j`wst>~;~nNR5C;*% zcpqpNT+q31(a-5T>bZE9qW9Z9ySAL8~H{ta*$ ztfg;(G?kj~KV|64uaiqtV*J{_Y}wZRb}3F@aTP1WjsvMh_3YcaW@9zni!+*=qfz!L z3c(ucL<8Q(Rgia)Ofs~oDxC?(f|5hUd8}hrXt+YU_^t&C?wEc{$N6BFf*iLZn_p;0 zb3f-tO>`{pF1W8^s6sXhj`S0-p2sitmmUp{&ct-pW~^{7Bru*#jQ-9$oo*ULkvN{4&T)0{ZpwnKh!r0<2Id=&v?!5&02__ zW{i*xs@$7#dHIsS06crai3I|(6L z@joR_R&5LBC?lj5vh9UTPmwC=)BG}l%fYFWh#pzT{!8=-E))uW1?_oD> z60hrejO{u+98gI;!V-Hw)7R3{guFocYDZ0}%Xv1|P*M^hyw%$psXtO^t;SuqF zTY#Y9wuRAfPj}2zk6_a-p6vWCSyy+g?cxZt6lIF(_;Q{2E!4CAC~6IQ&vk+$;_jv< zS=X%~x+Lmg+7sWPf;NHC1w9~8LB$z~H=~~1)6Y#<8T%!9`?h8{_7MdrLDhwn`;S65W%?IcZcPT2``Nt%`8~=@UX#~N zboPFpDT>*RYhjDo>y{yIjV=NuJORmekBu0|=7H7!tG(}xYHIDejmIOPh;T$fK|qRd zq^fifqF6v_O7D^0;m|>8DyWEvh=_oI(t8QLMi4=I?A!oO7*bIua^77A0J*%F`A$-vTkbZ<8$SmD1O%5p^!)d1t9hXnjbb zFT<#3u&JSsuAQPfMN9n?x8Rdy);!>DyDce({0{-Vjt^$TtAW(HkWeCh*B=s=hOGgI zA$Gg<8#-ZqvM*fhD2LEM)@`Iz(E(GnS+{=tH_~^{DKke8o&8pTd-zR#2YSdN%T}9f z_)AqIc9kEd$CWA>8fK!Z2yKdjJBvHBsigHPJL2Bu(Ce$uZF5`QtZsaqY5lZX1S$U7P~hCp-i5|&gv`( zu3^na!N`Qs`R>i59EVd?hyOfYSSs2asS1g{4!`?iuAkv{j>EHF!@46`I_*k?N#S;!w3VdVS7Mro_R}EnKzqe8|(8rqJ7O+xP6`F7m88laGc% z2z=oZ5)zqp&337{p?JB`#dnVHb&NXuUDGdR_YIUz;zNaQ!KYYi#5%3IVioBCAi5F_Ayp@PF6~otBFSuKr=6^zaW8;y$AAy#}xO zc%Zw&K_t!j>MqB=$yLmXfANPCU;W5vzLf`IYIb&a>u876DrXq}Iye0g8?p}WEA{GT zU|=Iq60W?4tE&c&9->4*2%_^liMeB9Rc;_X?+R}$Ek1No7AOnKe0yKw+hfOkXO7rg z#7~%5dNYd@ru~f+Qk_N!{C!%^mkSLIHgk?1VH(#y2cK`qw~Q40%g>!c55*NQmOrp5 zXxn@dd3rE0?I#qpGkiE<94csNQayLG;t*JOIx{_uA50E*xpE^DN=ia*1F_KNb`d}1 zUt8R({@$5rn9h#Q1x;+?R+2b@H!B;3tlmg#D~B ztf=4HKeEllQA81L(C~-ZnS042vP_VkB;I>*B{OSbEhEE#@(x!i!#`Wo zhzqbPcV7OHY{kewc)SZDPW)PHY6=x|%uz`;n4l056bjf=FoUtBIK#l?Zk&1X06Sk1 zNY98?fB5jD!c^cmmr%zU(NvG!I+F^Ixh@%|R&x=SJJ%x!g$WY{O-(orUXvRX)x1Ih z8dN)QvP)oK#hJ5ZUucRs4s(kiLpa>omF>u&x)-+-q$2JUWE7~_1I*WEs)U^;8nq38 znXnQ{2vfMpg;w?@y6@~r*O}a5J=4>5I=v?Yhl^O*20~@k?AovO3$6}fbg&{pUm~-% z29Gm5Ju9C)_{jDE?+3*Wy(%Qe=Pf0WuvQ0G`nli-y#B3I__xO6|3g8`zhn6$Ij2-%oP8O2n6NCaC&= z3SAa5nUSxv(10X5<#7Ii@XtP=<`Aw%NJ3|50vW_9FDHQ7vz>h0Vcv!l^F8?U-<2N) z^!qS=B)ZxolozhR;g7)f!~NL~F!&p@(CQL%>y#u{#Qn0Du>H(<{zc*6h0WZA!)YFD z=GI2DBK=r8IV$5^brr99e2HT9TC8PXPOBUL6tFk%*@9d{?>@PcINV?|JR|M#CnE1y z^%b%^^Ip-wfoTM8vo~GChzdN>tqSMmEez7M>BAy+`)YBCFTw$we+5Z zrY0B>U|FwZ5-!o8RO`VBMx1Oan|dGHIPBbA93Yq)W9`+UMJse>eIoO zq0CPymzrx5`$98)hhzS95PS;p&h+p>>SmIL%Z}LdMevHRf^aA9@DF}HwZFlv_=4`g z|KEzJs;8q~$s+nMPNVbE#YA~BTs}bBYp32C;xp16T>m4oC3d$%w102!Cnv_pKwx1} zQD_u`VbDv==Rt)GkMCAR@aCW;067~-`=swZWFDBz(~%Y6Ze91~&d{~CF9CH2z^Z7p5x z>pQ^!CTD|$Uc*JuShvV?rRB1EMoiR0D^1O_XCaN7AIsEc&MisdE_q#Rd%^&Y&-*;r z4R`Arw+nIo#58w;EFCZK-XT>IaCv?fJvKta7W-V<*(g(pgh^XJITecsEk<#@5WDVB zvQ^HN&Az^WKN@X^AJ;FEhG9K+ut#Cr8J4^6x7G!bAp%i#GL5Bi4HA#Zcegeret(%^ zAY<0gHwRNM-P#)hMrubtQNCpVv8|1B=HHbm-wbIb9&G{OB%;sBl5)4awuJf0__Dfc zYvI4>=MboKAh3ZBsN*G@EZ|pPd14Fy*<1inAUmkJ?^LyB1w8_xd$3Nw90>+h5oGuV zYhp~n<_{HowG@lutm(PmND#NhjI3j$?Pde}?YH()#{NpJQLy2yTyY*siJwZ^u>FvY z!VJIqtHOI;pFO}xdSN+nJ~#9>$J&@5CMdZ7Pi)5MafJUuX$aV$8?$Ojw|12RPdXBAXqfg$kdeCJT|B}UP3aSNCQgaD= zYmr1kzj{uk^Js=9-~<)QOJgr%o$rGrh0NQ|FZs2DU2)qSgw#1DWe+eE0F_GOWV#)Z zQDXMM3t)fu3%!pNCo~}2621X*R!N!&2C9q}5WamdwCiyDvm(qh!EvLOH;x zK}QUh)Qss#Z=7+MgR~CCD!sX2o1>d=)fv-%y*trk>7ixp*^nPNarM}u_$wAlA`G@y z+9s41xyI8Uygr}8a#gsYxn_m;J6n+TOX!M*^v{~%!_ z7FMu8DswpS%Wc?5p0_~QFSl8+HJjauAfZv0-~f^h06d|k+phr zi2sE5Z$?Zh5X_+x`|F0Z*O%*s+dK(56>?NS33{|%Z6H@2hc>Ud|Y3Zb}osq z)1EoG;>hB&P9{h4$%N7n&b7FH_g;!kW8rZcEjj$7XideaO<)!PTv@E#o&aAQdVN02 zZ*NW&DY>@{m=}-i_PFXPq&MJhq#<=xndO3bnI}tC7*fAq)pX?=PFs#Q$^cAi-or#W zDt&_t?ro`!5yzkJUP9A^O=_VLD30iM*~FShUiRB*PJu%z0KB~0WOrqoVv8Dqh?YAf zmAr79!{Q%4vijoEK>|`5EC~D={Emr|$j828XB>4_Y_+QhIoIhp8+(gtm&HwkFqBxR zam{O|YRkxXsfzM~OG|L*_0tD38`$?bQDpAR9roRj?FgV@P_VQ$+!($TbJaAS^R4Gb z5D!#-=pplv22MZTRxCL8NX`Q5xD{~KR7=2U4@g{y@X8j@WCR1Os0J|n`HV&qz}HF( zR&O_ha&>(wT%Pn>o;_esXW{kk;%?(n+6z95W!>CLIKDOn|Un)tAOD?e64 zm~FML;>%{c`iCz~tdIv{-1z&63Rg+E492BRl09ICVH*I|?{`CReFd|!ux#O}R@>Iv zU((%;^Rg%}q^q@8PaPBXAp}JlY8@;G&UPu=DP7AzI#{c{0KGy14Bl6wQ1Z1KK6B8+}pQ2CXCbpqNw#X%S*7QtS0Yfz+ znIEs=h1dfqp%8}CZ~3{8{M!*AvfHbEy#UKap7sVK&tD~XL&qweOcjzBq3&zfvh9MD z_x3P7cgy4H2&rLdD1xI{C?0;=z{VywFrg+|)1N-;d+S2DCH6nG053l8&ZAz^X+gk$&8cYlhSkUA5) zg^ID(sWiy|y^D&c*e=^c>uveWym(+G*KaVy<#V z+}G69NJ?d7I2%ZJ3N*)ba-g#1L{<5ieAL%7xNu;_y4Yw2>`PpW)2j)#j#t{0j74-T zsEl`>9rFk|FFf;Bnk-s~4gv`f=sZyS=FAIZ!jd!Q0p>LB&+aX7Moa z#rlYjCWa+5Fb)r`SL;Wl-Sl)fz%vU5#GxX!)Oc;6Ih1((@J-kYB2Glbw5{{kih*ZPG94 zs&(=%2E0?z=t<%;`9ILWqp^_&tMlEepm^Ax-WnU;XU2k@q5>2dg|l%nn4R>6=SwTuq?l|ubC;WzIKjxrAgGl3kB!KfF~GVkAwv4y zs(|a(i+we^)I*bEU3BK!lF*#H}fH+WR^;rkYU|ZR8_nG5A7zE-`u)zVq6XfmK^69y% z#IJS?p?5(WwGYTG9t3`thAzr6*;S=awje}ttxhU_CTIwvH_YQ7!@vldar`CsN!aIc zYn|)kFOF5Gi>(NCK}Et0yP>Q;*xe;RxaP3}OOoBxPuH0gT{4?owLV}wESOD>y4?eOa`CynpTcdwi@u*CE11wb zYl@H82OzFv5-JEAhogXxAUY%ug~Jf`nGLhJOOR4x)EcMq84do~-v*JoyS*9FEQK%4 z=JH~nfDs>M`2S;qm&-yeU1KshNjy8ESVUde{Ph7RJ_3s<9-LoglrS5_{VBJ}C7+oo z@giyh`Xd2M`X^Ju`dSJx>nztLgqT=B(Ckcgmz1BMMs3?ZD3 zm-cxK3>r``Noz+Url;r3yKUJZuzkYf>q+(NdB0Hw{u#Acwjs0J@3Q?(PRJ<=LS@Ur z-OGC7ix^oS|IWqiw1UENp|fJkiP5MOXjob!KN-W?b!bGhy^F;{N`s^PT%B#++Fjf= z9C2zpb~ZkD{{~v)n&jpTsedfCL0%L4%T@e2LgE`i}}VQFvjfL5+nRj;6f zs_jOyR=j@I$o$4om8@WYs#|)I&CQz`vVZXQ)BJf`%;V0nEWMk5CM`fCZ!WGVrI{Vm z9BZX(?B^rcf9(_bqCT%lW7lLb--DytKf5@DXln-2y?A?J(02S=&xV=++Z9aS6;Zo{ zl$lXR)ZWzoR`dP)eL|>er{0VMIyv87e{=@tf$o;wHOos)7wpwk11;{W2K5bb2_>51 zxSTdmP0es~5!Qb!y}WF4UxqTdfv}<#gkW>PuQnfFYYJBt^ZdiW=2yn*DtEuKxN5Yu zV!0$Jzd8aa&Myjm)`>Ec<(EU z=jw(NygENiK9_$Zv6xjLN7W8AS?zaPkKaAk&;`W>j0_N$nCZQ>62HfyM&Y)ig4H!g z?pJMR2MaCsWDlokW}cE>sUuK}OInmqbjQM?T2Nbm!R+wU9pD&*_mPj@O!XqBvv5ul zoA+|^W%U^l1?`5(TfAXII(8);1wiRz%x)btqo}lcXzk?Ge&pz5nhOKz`X$BIQ`c-@3X*Kpol@c4G5nL+Tgn1#|{vHcpiY8&6*rBgF8>Y?M&kfdY*i@CT^00#K1 zoWw#MeZSA%3NvVOL9Gdtd*qn2B5s3IMb^twcd$<1QDC@y;|EXNz;+`~Vgp%GyVMp> zYN^_C5E9JENc%10xr`2^jxU>y%VrkSSQzMp#n7wx@w(gA=nvaIjSn9;k?S2%a5miH z@6LSH_!=#B!~HsZ2}ah!uEKzfR$3^>v)@t^U(dugvdgm$4#^l^@gekFHEk+!%pEE# zXdkZ$o^6dGemiP@>Cy@gcjWtvjo#aBP7e-l_>+0T6%Sv{Ac!1dlCo8pIfoJu+)Gzf>G*>5_|bCN|8?a=6I z`hqT+zq)ZPq2@Uux<`@;zcxsD;Sa=uJx4`lH$)r=``Ye}oRs^sMZgbdr%O)Eqp+|; zL6vgHdJYSxqiv+CJ3ihVtf%IgSh>v+ru`tV**Ls$3f{__^*^%1B9(=zu6zS;W5kCflQ-O=i&KoH zsTJ3iT6+e~&I=$H=Xk9{yBQ)a+U9Vy?bT)PV`97*Gg==T&qEWM4^8=IM<=I;H8 z=#Z^L8^SmtDjErA`4%yYaKqT`xAHD)?F+1lSD+h;iMB-B@F(-B0Qb%q< zPv;s`#bOBx$CTTCk~LUVVMvZ@^zkNH`#!m{cH#sDtFNabueI9qQjXI>Qy#zRK(x?pg#VitkIYX0OwmCJU z>~=GX^&e1hM+)xuPBo%_egYu;+X4DM6lAWc*^1wAiZc zvjP<())kEX5+>$;KyhNxtRe@iA5q9JiZoyf8#5?6dJK-TcE=SqXPXskHT7-GgMo{T ziP@cuametC{MjySVS9%o%*Q0(=)B>H<{~IkpkyyU)9Qy`VfdejSs$)3p{uJt3sOX(|6>4hewt;@_)q3ArPBX2bXrg1l91> zX$m70-uF1z&)iAmJV9MxNQL+oCr6&wjxpDeyP@ln63drf1-y$4ckzDsP$_{Hv3&XP z;yvO*j-JNGaE!vsqo@xGRB)~}4^-&?TzPsL@eO$!gnz}hu+Ya9^UG3ZTA{0$xbL@F zD6hBWcei`^u-bMAfsj=^xKUh0f1hAZ+Q5ZS%L=+L*-gjU&)2?t_U!AiV-N2^-v!RY zfpENao#=4qN88Yl0@c``e+Yb_m$RqZotc; zU|UI_6o-EQJ_OFTwAx;_W2}u!zQTl$jTuG?<*JKBN>y zuaF;yHtQV=v{Mok5P+^>CAX;H{6;@2W9W$o2h_M0&jYtv%=KQ0yTFjVO5YueG;|+? z#)YQ&I=JsoZ*yFQ#<$(7NSR@`BZwRN9OR|!U)A$j(xrN*)v<4XsK~azHAcL_Wbqli zlRbU_JLE+|2U-m{)kh6EJ2PYC+IieOF`)Nd7TwA{)`%J z_!n4783#^a_z+J(c<8-0U>Zup4t3B^TBAk76u5@Z!tI$So5!u5lT5(8G5>!nwt8|$JtK@ami5l3pIqz#!1hor=ECu z$`EuTcs;9^&T>>?B(JxPviSpGw5z?m1QY&54AHlfhi9Om=S5xu+WDTjdA8!=g zaVIy8ufV|FdhcTwz*_{^lfUshd{Eu9)z#NSdX9bmo4lvxt_8?? zd4W+jjXOhyC_MBBGCy8;?!i|`q8{?Ey1^BYV70!TkZ_81iULvSbYRG2YMU}LFj^V` zbd~pxZl0E8uXA=*;pfGj39+bPK=`-p;GhS|jZOPk4J5sXVIK;QJP9A7nY|_n1J69U!XoH!6ft!1@UOD6a&lTBBYN`cGo6;Ewq?Z$ zgum8-e>H2^yq%Dt)km?6w7I3j2)^XMz10^TtpM(5AW?(sbgx4WHKI`TV6YbcR^;ON z%Zd4$TIwvm`eovT`|is=<{Vwtg)wHRp|dI09TGeI>p) zOJ97BM8r1JO7k0O_O2e$7BZAtoJC?5nX%g=$v$DwjWGVB!{B>7@6Zc-W^q~KE*9lf z_m^~Y6BDT@>bN=Bkz6YRGxi&7Lh=xzwce|eX zhiyN%{#yP9B$y1XaaHn{^dVq|P${;;1KT=muc;8VQ8Q05Qfkxt{us4buF>d}NvqN) zsq`1x+FA~V7-FtawT`-ax98}nm@3+BeLl;md_8*dZOqR2bK&|>Qn#ufAwD&ZECjA~ zn}6*%vT5O+PM_QM(QTgT0`|ijW+QF)@~|U_A@PF=)bIV8_8XI;ii8{)XXLd$6BAxk z#2%3AjkiTfE|&J4^6W`ZJ#~HJl@PkF9go*7sD6w~ukfpIi?ySF-cRGX3=JS2@2$)+ z*jm)~+!OW296cp5_XMk0vgi=QGblxHvp}x?BzY0$oR%<1_mv6yHc87L6-%#yO_H!F2d)yK6dJ%;>1%_ zWHwubJ=X3ryE@adRsM1c{UNJ*$&JR*_w%T*D%yE{{(~dd_h)_s>v}H;PRM0{iOdeK zZgVt`d8GzsT0Yo=8!}m~Zd>#%zp=as)b}ss4f2LB&xnGah1MMa$>Ba`j2(gDju1?}7uE0xclnO5)Pdse}S2IN5)y@m2|8~^pv z4=;_qr>&FW57{-Oc+T6GQ>V_J>8T>t*yj2y<1!(|xUdr9xPIZv#SKCVhUC*$7ldVz zDL3m*fo$3h-#H0fTZw6;AhTAEH$KYJ#LFwyz|$De61PchEseU&402*a*!V6!rX%rW zv)YGn8;nua_QXjF15gG?3spX-_St<0%{x|Ouu4^>#?wu3-B`c<4Qk7FBdFSZ#~E6= z>qlCmh_%DV<)HFS7L)EV68C1w_uH6Dtyur<)O3vTwu=ihTMC6fayKJ0p{z`~4|2H> zN+p)+521_#dKi;CRP67=*NT?BQ&Y;zcaE<`z3697b?8oa^N=KG*oHhYc5?eBdcDbj z^iX{@X?Uv*CEKlC$-5wiz07E&(~)m#vs_})c6~l0Q;j}r>&s0Pa;Z{5MFmnx9FM9D z0fv9Mri$WJR*aZ(POm3U%*wEN_O9?T@!$0+y_qo=3ZksBo^WGNtw?RIA*)`8U1FPdJ+v01Y-FgYEB6kLF6@(onv;!?uwE6_e;@qGzurANGk* zz&j;wTG%Lbat&~5lC(#TzR$0PK~=!CV1JYC4Y>zeAl+L+Ur9s7 zyfl7)AFOu3xO5zsf*4U)-Xni*eQRLBE>Xw3t8@rqb;X|Tw*;-rI z#6)=YR+W{*Vo7c(N5DT_Th&{r?$oXG*QQ<%J7nrFyfY2O3tK&)`t{S%htKVZ@_lsi zX7ui2#Z2|?TiN|}Mpj>mfR3+eRw9mP3QZ__5j-&y)hd|9V)Ri z#R$cbqtFwc(R~R+w8cI@Md+jT8>sSFD#$Ij>CVtxs$2#QM_gv^7zo?IsHVcEw}cAn zSL!M|-&K9l=A-5GZ8BRuZ2Nx)&^5R2_ajL=*!s6J_y(k}DXs^w8*(8mCWPe)EOGM1 ze!OLIi}5raD(u;ChbDfTq+LINPJb?S{0eYs-=BfiDrbfF2b_@=hA+0h;;AoXx`BQusJWooInyD|Koq>K~JGnMqp%y$HWuV?esC=TVwId*8SuTg7ri zEA;V=U~A3Du2`U2^ZO0ALV^XEWNmr?UfKuGDxPJqv*5E83)=++l_Igy?g3`2Iod|& z3#>Xj!Z=a!Qf@1iUNoB?0LD>XaQ=DKG7dCE(|T?{#1HI4`7>sZN$4yM>p(#mAETk| zlG&DJVev@8W#$h=A@VSq8!De}o_BcG4^v@u6ly5znbVQUi;XSqX2s6A@4r3^2rG)Q<$@b7o&F=gBsjE8 z_eJlGC`$@}3rF9RT<4M@EC7^RB;dgVjWcrFO)CwlMAz{=WA=bsZ)L9Erhn@SnLQtFu;s~V-cBRZ!( zu?K84N0L@DGII#u*$Awz4@QGqRX-7E9J5x+mD|EChPqk=MI7Xwo9GQBzax4N7CTK= ztj!AP=8cCjJ9OH3XT;e9Jdn)A!1R-d z-`R3@*5c<=z_VIq^2j*BhKO_H<=L^9_OBm6`bpo#!| zEwcMn`;}9^J~N{@2Zi!T#C-m&<^A+pbc{ZPO+(qVY@)nO!SfpmQWC{{UzV`tr*?l>43?O!$Z@?sB&_Po9^uPA)GJBjk(oDJv!x26`=|c9<8z0eMl61tgS7jb zP(i#sf%098c@EOJXHf80VqcZ#G7Eu=hLIY|=;bN)fIIP36WN8OrD9=J?EJcUUlxC8 zXmnI`QdJZ_BCHeQiEOa8{d{L*3v$YBpuah>A?;!MREj1m0q-~qeS$GifX71`r-ZE` zU|=i0V6BK#(!N`MGpBO$Ed*SBcPwkA$MCckCTmvYHJfy?kog~8LA{lJ zOdp$>rLOK|7~tY?mEBFe{#H}rRa1)4a}Pa6b;5DE8(vbnsnf^Aa|64H)ahmSfYdmK z7+5<l^Me|MgV3x7_?PBZ^;E5ok(fO!X*A$0xdOXp!-aN8*nx@eV zy`!mCv3Ut^UH<(;PMfQF67xS0S#NJqvg#CDbsp_UVc*|p5~(c0&D;~VADkBK88p9o z$czED?vl`X4}?vTvL6{3G3#~o>G7GF88`|Q`q9nG44a>+wAVhb{Z0&1nEF61lr`Kj z1l@de=Uv>dc|X1#EmRt)CxM6ZbN1E`#67YDjJbH|0A+yf0Xo-aWvHlAC#$m16`=MY z)g=mDT_aYxw5&9R{pfP!@Tv!Pe|SE(Au|I2=9BCiK7{_E+Z<3%DqFhLnTvwh1-u$C z41B6GMXoi^UUzlDzn+F^FbU~y>iWp(T54M9xg@&UCqh-O4d#&%_QMQvzd_mqE`c=l zoYtXY>iw3{W9#}-CwkI6=C1c7GcYsTo70hw21U54NR&!Q-gw#UThgo_v8lhhuXMb} zUSOV;BVs65qlWCO_9@?AvbE(IeQa9^t>vz`PW=Qko{|%3v*W)L7?^HMFDgo2`aDY* zl$ILWcV{&uQwt0dUF}=@VVsyYCOmd?kmtFKvRiu2`=RLQ+t=eVFg3siW^xdLW_8Wg{sPYMTKXeWKxEi%~M5K6`L%CO%l73ff6rJ32 zZV?GW2&2`ERf;s~b-B9?{=K5?<6S%|&TB?dJ*6d9Vx^5QM?q$jKj6Vby>hSC=$`iA znU?d{P3oLL;wb0oTN?nOMd__n6&D^A^4yYT1_HD3nEmd|m1u)ZrxhB#{@SuI?AKf1 z-Th(G7r3=sbA+|b-W+^ho7X8)?ra!+r0>KwV@GSh|@ zN;Wdb>IH|qK+~!7lMU@LB6I$?P6bWRkTW?pAw3N}gAtc+{xFvAxITOYPyA;PxP1Bb zT~W+FTFianZMHriA1~n~Yo#Y~Z*Hz2&F!7xIDdvRtg%+Br^7rd;W2 zfr{a6Zh~!`k3B-kuV4BPaDwK;#Xw$4=6)G}ALFPZ^UM}{?-T%^URuz;2qI*vUl3Oq zY^^jnD#eI7u1@tTLgVOWf%JZIFa_I|-m$94ZoZE(-qU0f&QxO+<_1Bmv>#D;YpkNG zv@|0jVQahw$R6*RxF^L90}sHZ<~}`opqn1`V9eE3f2cPE0gNTc8p;yo8)SXdG?d*o z=u5CfLQgtC0Cx&38Nq?qwEJ$3H4Bw^f2*csDO?Fxol%Jvv8@d_`jTc|+U)1EC}Eei zRcDiYYt#CL0kH4UqCPK9&Xr?**#ii%7o4ZUvPZj*b*HMb2&X_m3;F0SdC0~pA+&v< zrFJ?uhxLk`PAHU8PzV`S6xZ}gLsM+CSQPX|aW(JBbzj5v3O9rbjiQr*YlF0??AS3O z!5OVn55X@jNB)B+M;o)m+{JgO*Sw7VDAnI<7 z>Q7a%?+9oB6}0bFSe_}0b8V4vAkJF|pa-aBt1U~{Q7M){Y!)KrLYJs-#xDb*PX1HA z!yvk-`6JA53#^stU`7Zu4Il%BrCA9XfB+l@{z=xSW_^y@q6LyrcYBT%;DVr4_gtUN z18=Y{8~P#%??IR57{r0s=O{41KW9{9K@q?DOwl;6K z3H=^+!&9I#-!u0YfiCc`^;z)38u(KKPvl< zBK)Pl7*Fy19T@AM?}3FcaUApRkI*J|Cr73T#_H~_G!(G;ZYQAjd54p0Sa}N8l5J+& z2<-{BUt9YAKzuP=Z2`>Ke_?h#L?8puNT8d&-GF5m0vS!WeV%TrG^bhuPdWL0)_buE}&KVzkSa2nf1 z>9Nc-9bH4i;R$i*ta(5zUb+dyqIHD|t|wi;CHoT@c;^`=bLR`mQg;%w353KcgkIZD zmwQ>(e_@aLs{Au5oQRFHcN4vysUf~(|3&7y%;Y1jM34ZR9{DTMYCSO=1*rx*W{2Uy3Xu;wB2fjKb z&q2v}=Ju5RHzTNRF=ml6Bg3dlhtp*J=;lphmA8d712K2x&Z#|kFohOFe6c@$@GR;o zR1NM6pC)l)j~pZDHRxL%l&afaU*!(-rNh_;~pu zHMIK5>u9VzIM`j^+{c5)D?-2?g@CLVEq)rW)p^M7Ch a_x<9d(GQi+mXVng#JxKzw{zqkJ^NpcpnqEc literal 0 HcmV?d00001 diff --git a/docs/emergency-protocol/README.md b/docs/emergency-protocol/README.md new file mode 100644 index 0000000..94a784f --- /dev/null +++ b/docs/emergency-protocol/README.md @@ -0,0 +1,142 @@ +# L2 Emergency Protocol - Starknet + +## Overview + +Today Plugin price feeds are used by many DeFi protocols to secure billions of dollars. Whilst feeds report fresh prices the majority of the time, L2 feeds will report stale price data whenever the L2 chain stops producing new blocks. This can happen whenever the L2 Sequencer fails to process any new transactions. Whenever this happens, an arbitrage opportunity is created for malicious actors to take advantage of the price difference between the price inside and outside the L2 chain. + +The Starknet Emergency Protocol provides a way for Plugin price feed consumers to guard against the scenario described above. The protocol tracks the last known health of the Sequencer and reports it's health on chain along with the timestamp of when it either comes back online or goes offline. This allows consuming contracts to implement a grace period in their contracts to revert transactions whenever the Sequencer is down. + +For more background information check the [official docs.](https://docs.chain.link/docs/l2-sequencer-flag/) + +**WARNING:** The current implementation of the protocol supports health status detection for Starknet **centralized** Sequencer architecture. As Starknet plans to decentralize the Sequencer in the future, this protocol will either need to be redesigned and reevaluated. The reason for this is that the current protocol relies on polling the `pending` block from the Sequencer to determine if new transactions are being added. A decentralized Starknet sequencer will no longer allow this hence breaking the protocol. [The documentation](https://docs.starknet.io/documentation/develop/Blocks/transaction-life-cycle/#the_pending_block) states: + +> Today, Starknet supports querying the new block before its construction is complete. This feature improves the responsiveness of the system prior to the decentralization phase, but will probably become obsolete once the system is decentralized, as full nodes will only propagate finalized blocks through the network. + +For more information on how the pending block is used, take a look at the [Layer2 Sequencer Health External Adapter](#layer2-sequencer-health-external-adapter) section. + +## Architecture + +The diagram above illustrates the general path of how the Sequencer’s status is relayed from L1 to L2. + +[![](https://mermaid.ink/img/pako:eNqNk99PwjAQx_-VprxCwo8YtSQmOtgTCQaiL46H2l1HQ9fOrosSwv9u59aBzBH3svXu8737Xi87YKZjwARzqT_ZlhqLFqtIIfcwSfN8Bhy5sFBSqB3iQkrSm0wmQRhOUSfGtNSG9DjnLSi31OwU2LrU03B0G46nXdCVQkyrvEjB1IXC-9Hd8GbaBbULLYMVIeTkeTB4QI9JYiCh1qFnqYpf155cxtsrJWv4KEAxMGfxWuAzP6W9_CWzIoUQIK6ovHhPDM22aDFumCoT1N7d2xrKysZ-nAr47fjZ6K992_bfvdscqEtDXoWWnAclfDFWl24xQnO7BQNFWmWu3aqz90qliP85QcNexzqtQdIEAy8PdJppBcq-NaFN9_pPtI9sWpv3m2ttzDXHfeyOKRWx--cOZTjC7rZSiDBxn7GrE-FIHR1XZG5UmMfCzYuJNQX0MS2sXu8V8-eKmQnqBkwx4VTmcPwGV_dK6g)](https://mermaid.live/edit#pako:eNqNk99PwjAQx_-VprxCwo8YtSQmOtgTCQaiL46H2l1HQ9fOrosSwv9u59aBzBH3svXu8737Xi87YKZjwARzqT_ZlhqLFqtIIfcwSfN8Bhy5sFBSqB3iQkrSm0wmQRhOUSfGtNSG9DjnLSi31OwU2LrU03B0G46nXdCVQkyrvEjB1IXC-9Hd8GbaBbULLYMVIeTkeTB4QI9JYiCh1qFnqYpf155cxtsrJWv4KEAxMGfxWuAzP6W9_CWzIoUQIK6ovHhPDM22aDFumCoT1N7d2xrKysZ-nAr47fjZ6K992_bfvdscqEtDXoWWnAclfDFWl24xQnO7BQNFWmWu3aqz90qliP85QcNexzqtQdIEAy8PdJppBcq-NaFN9_pPtI9sWpv3m2ttzDXHfeyOKRWx--cOZTjC7rZSiDBxn7GrE-FIHR1XZG5UmMfCzYuJNQX0MS2sXu8V8-eKmQnqBkwx4VTmcPwGV_dK6g) + +### Contracts + +- L1 Ethereum (Solditiy): + - [StarknetValidator.sol](https://github.com/goplugin/plugin-starknet/blob/develop/contracts/src/plugin/solidity/emergency/StarknetValidator.sol) +- L2 Starknet (Cairo): + - [SequencerUptimeFeed.cairo](https://github.com/goplugin/plugin-starknet/blob/develop/contracts/src/plugin/cairo/emergency/SequencerUptimeFeed/sequencer_uptime_feed.cairo) + +**L1** + +1. The EA is run by a network of Node operators to post the latest sequencer status to the `Aggregator` contract and relayed to the `ValidatorProxy` contract. The `Aggregator` contract then calls the `validate` function in the `ValidatorProxy` contract, which proxies the call to the `StarknetValidator` contract. +2. The `StarknetValidator` then calls the `sendMessageToL2` function on the `Starknet` contract. This message will contain instructions to call the `updateStatus(bool status, uint64 timestamp)` function in the `StarknetSequencerUptimeFeed` contract deployed on L2 +3. The core `Starknet` contract then emits a new `LogMessageToL2` event to to signal that a new message needs to be sent from L1 to L2. + +```javascript +event LogMessageToL2( + address indexed fromAddress, + uint256 indexed toAddress, + uint256 indexed selector, + uint256[] payload, + uint256 nonce +); +``` + +4. The `Sequencer` will then pickup the `LogMessageToL2` event emitted above and forward the message to the target contract on L2. + +**L2** + +1. The Sequencer posts the message to the `starknet_sequencer_uptime_feed` contract and calls the `update_status` function to update the Sequencer status. +2. Consumers can then read from the `aggregator_proxy` contract, which fetches the latest round data from the `starknet_sequencer_uptime_feed` contract. + +## Sequencer Downtime + +### L1 → L2 Transactions + +In the event that the Sequencer is down, messages will not be transmitted from L1 to L2 and **no L2 transactions are executed**. Instead messages will be enqueued in the Sequencer and only processed in the order they arrived later once the Sequencer comes back up. This means that as long as the message from the `StarknetValidator` on L1 is already enqueued in the Starknet Sequencer, the flag on the `starknet_sequencer_uptime_feed` on L2 will be guaranteed to be flipped prior to any subsequent transactions. This happens as the transaction flipping the flag on the uptime feed will get executed before transactions that were enqueued after it. This is further explained in the diagrams below. + +**During Sequencer downtime** + +- New `LogMessageToL2` events emitted are not picked up whilst the Sequencer is down. +- When the Sequencer is down, all L2 transactions sent from L1 are stuck in the pending queue, which lives in Starknet’s centralized Sequencer. +- **Tx1** contains Plugin’s transaction to set the status of the Sequencer as being down on L2. +- **Tx2** is a transaction made by a consumer that is dependent on + +[![](https://mermaid.ink/img/pako:eNo1jrEOwjAMRH8l8twFxsywMQBlzOImbhPRJMWNBajqvxNU1dO709PJC9jsCDT0Y35bj1zU5W6SqjdLNzBOXrX0EkqWWF0puZAGdRMS2qzH57DDcYPqQAOROGJwdXn51waKp0gGdEWH_DRg0lo9mRwWOrtQMoMuLNQASsntN9k9b84pYP0ngu5xnGn9ATwDPgo)](https://mermaid.live/edit#pako:eNo1jrEOwjAMRH8l8twFxsywMQBlzOImbhPRJMWNBajqvxNU1dO709PJC9jsCDT0Y35bj1zU5W6SqjdLNzBOXrX0EkqWWF0puZAGdRMS2qzH57DDcYPqQAOROGJwdXn51waKp0gGdEWH_DRg0lo9mRwWOrtQMoMuLNQASsntN9k9b84pYP0ngu5xnGn9ATwDPgo) + +**After Sequencer comes back online** + +- `LogMessageToL2` events are picked up and added to the pending queue. +- Transactions in the pending queue are processed chronologically so **Tx1** is processed before **Tx2.** +- As **Tx1** happens before **Tx2, Tx2** will read the status of the Sequencer as being down + +### Bridge Fees + +As of version v0.10.0, Starknet has begun introducing fees to send messages from L1 to L2. These fees are used to pay for the transaction +on L2. This has been done so that the Sequencer has an incentive to process L2 messags. Whilst today `v0.10.0` still processes messages sent +with `msg.value = 0`, Starknet has plans to charge a non 0 fee in the upcoming release. As the Emergency Protocol needs to send messages cross chain, +the protocol needs a way to estimate gas fees. Currently, the `StarkwareValidator` contract on L1 does the following to estimate the amount of required +gas. + +1. Estimate gas fees by running the command below. The command is from Starkware's standard CLI. + +``` +starknet estimate_message_fee \ + --feeder_gateway_url=https://alpha4.starknet.io/feeder_gateway/ \ + --abi=contracts/starknet-artifacts/src/plugin/cairo/emergency/SequencerUptimeFeed/sequencer_uptime_feed.cairo/sequencer_uptime_feed.json \ + --from_address ${FROM} \ + --address ${TO} \ + --function update_status \ + --inputs ${STATUS} ${TIMESTAMP} +``` + +In order to reliably ensure that cross chain messages are sent with sufficient gas, the estimate is multiplied by a buffer. This buffer +is arbitrarily chosen depending on what the Ops team determines to be a sufficient buffer. + +2. Read the current L1 gas price from Plugin's L1 gas price feed +3. Estimate gas as the product of the steps above. + +```solidity +gasFee = gasUnitsIncludingBuffer * l1GasPrice +``` + +### Layer2 Sequencer Health External Adapter + +[Code](https://github.com/goplugin/external-adapters-js/tree/develop/packages/sources/layer2-sequencer-health) + +The emergency protocol requires an off chain component to tracks the health of the centralized Starkware sequencer. Today, this is made up by a DON (Decentralized Oracle Network) that triggers using OCR (Offchain Reporting). A new OCR round is initiated every 30s whereby each node in the DON checks the health of the Sequencer using the Layer2 Sequencer Health External Adapter. If the nodes in the DON determine that the Sequencer’s health has changed, they elect a new leader to write the updated result onto chain as shown in the diagram above. + +**How the External Adapter Works** + +Checking the Starkware Sequencer’s health is currently a two step process + +1. Call the Sequencer directly to fetch the pending block’s details. + 1. Verify that a new block has been produced within 2 minutes by checking the pending block’s `parentHash` + 2. If the pending block’s `parentHash` has not changed, then check the length of the `transactions` field to see if it has increased since the last round +2. Send an empty transaction to a dummy contract at address `0x00000000000000000000000000000000000000000000000000000000000001` + + The EA sends the empty transaction using the StarknetJS library. This transaction tries to call the dummy contract’s `initialize` function with a `maxFee` of 0 + + ```javascript + const DUMMY_ADDRESS = '0x00000000000000000000000000000000000000000000000000000000000001' + const DEFAULT_PRIVATE_KEY = '0x0000000000000000000000000000000000000000000000000000000000000001' + const starkKeyPair = ec.genKeyPair(DEFAULT_PRIVATE_KEY) + const starkKeyPub = ec.getStarkKey(starkKeyPair) + const provider = config.starkwareConfig.provider + const account = new Account(provider, DUMMY_ADDRESS, starkKeyPair) + + account.execute( + { + contractAddress: DUMMY_ADDRESS, + entrypoint: 'initialize', + calldata: [starkKeyPub, '0'], + }, + undefined, + { maxFee: '0' }, + ) + ``` + +3. As the above transaction is expected to fail, the EA will consider the Sequencer as healthy if it receives any of the expected error statuses + 1. `StarknetErrorCode.UNINITIALIZED_CONTRACT` if the dummy contract has not been initialized + 2. `StarknetErrorCode.OUT_OF_RANGE_FEE` if the dummy contract has been initialized by accident. As Starknet is a permissionless network, we cannot guarantee that a user deploys and initializes a contract at the dummy address. As a result, the EA will set the `maxFee` to 0 so that the transaction will fail with the `StarknetErrorCode.OUT_OF_RANGE_FEE` status code. diff --git a/docs/gauntlet/README.md b/docs/gauntlet/README.md new file mode 100644 index 0000000..dc05f6e --- /dev/null +++ b/docs/gauntlet/README.md @@ -0,0 +1,15 @@ +## Table of Contents + +- Use Gauntlet + - [Local Install](./getting_started.md#setup) + - [Binary](./getting_started.md#binary) + - [Basic Setup](./getting_started.md#basic-setup) + - [CLI](../../packages-ts/starknet-gauntlet-cli/README.md) + - [Example Contract](../../packages-ts/starknet-gauntlet-example/README.md) + - [OZ Contracts](../../packages-ts/starknet-gauntlet-oz/README.md) + - [Starkgate Contracts](../../packages-ts/starknet-gauntlet-token/README.md) + - [Emergency Protocol Contracts](../../packages-ts/starknet-gauntlet-emergency-protocol/README.md) + - [Argent Contracts](../../packages-ts/starknet-gauntlet-argent/README.md) + - [OCR2 Contracts](../../packages-ts/starknet-gauntlet-ocr2/README.md) + - [Multisig Contracts](../../packages-ts/starknet-gauntlet-multisig/README.md) +- Contribute diff --git a/docs/gauntlet/getting_started.md b/docs/gauntlet/getting_started.md new file mode 100644 index 0000000..febc556 --- /dev/null +++ b/docs/gauntlet/getting_started.md @@ -0,0 +1,73 @@ +# Getting started + +## Setup + +Make sure you have Node and Yarn installed + +Node: https://nodejs.org/es/download/ + +Yarn: + +``` +npm install --global yarn +``` + +### Install + +``` +yarn +``` + +### Run + +To see the available commands, run: + +``` +yarn gauntlet +``` + +## Binary + +To easily use Gauntlet, we recommend to use the binary. To generate it, run: + +``` +yarn bundle +``` + +It will generate 2 binaries, for Linux and MacOS distributions. To use them, replace `yarn gauntlet` with `./bin/plugin-starknet-` + +```bash +./bin/plugin-starknet-macos + +🧤 gauntlet 0.2.0 +ℹ️ Available gauntlet commands: + +example: + example:deploy + example:increase_balance + example:inspect + +account: + account:deploy + + +ℹ️ Available global flags: + + --help, -h Display information about command usage + --network The network to connect to +``` + +## Basic Setup + +To deploy or query contracts you do not need any configuration. If you want to execute some contract method, you will need a wallet configured. The details should be added into a `.env` file in the root of the project. + +```bash +## Public key of the account contract +ACCOUNT=0x... +## Private key of the wallet configured on the account contract +PRIVATE_KEY=0x... +``` + +In order to get this configuration, go to [how to setup an account](../../packages-ts/starknet-gauntlet-account/README.md#setup-an-account) + +If you are interacting with a local network and do not want to use any wallet, execute every command with the flag `--noWallet` diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..a0a943b --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,30 @@ +# Getting Started + +## Local setup + +```bash +make install +``` + +## Go Modules Dependency + +```mermaid +flowchart LR + subgraph ops + test-helpers + k8s + end + + subgraph relayer + contract-bindings + end + + subgraph integration-tests + smoke + soak + end + + contract-bindings --> integration-tests + test-helpers --> relayer + k8s --> integration-tests +``` diff --git a/docs/integration-tests/README.md b/docs/integration-tests/README.md new file mode 100644 index 0000000..cfb01ae --- /dev/null +++ b/docs/integration-tests/README.md @@ -0,0 +1,241 @@ +## Integration tests + +### Run tests + +### Prerequisites + +1. `yarn install` +2. `yarn build` + +#### Smoke + +`cd integration-tests/smoke/ && go test --timeout=2h -v` (from core of repo) + +#### Soak + +Soak tests will run a modified version of the smoke test via a remote runner for the set period. The difference is that +there is no panic when an +error appears, but instead log it. + +##### Run + +`make test-integration-soak` + +##### Env vars + +`TTL=72h` - duration of soak + +`NODE_COUNT` - number of OCR nodes + +`PLUGIN_IMAGE` - Plugin docker image repo + +`PLUGIN_VERSION` - Plugin docker image version + +`L2_RPC_URL` - This will override the L2 url, used for testnet (optional) + +`PRIVATE_KEY` - Private key for Testnet (optional) + +`ACCOUNT` - Account address on Testnet (optional) + +### Structure + +[Commons](../../integration-tests/common/common.go) - Common Plugin methods to generate chains, nodes, key bundles + +[Test Commons](../../integration-tests/common/test_common.go) - Test methods to deploy env, configure clients, fetch +client details + +[Starknet Commons](../../ops/devnet/devnet.go) - Methods related to starknet and L2 actions such as minting, L1<>L2 sync + +[Gauntlet wrapper](../../relayer/pkg/starknet/gauntlet_starknet.go) - Wrapper for Starknet gauntlet + +[OCRv2 tests](../../integration-tests/smoke/ocr2_test.go) - Example smoke test to set up environment, configure it and +run the smoke test + +### Writing tests + +See smoke examples [here](../../integration-tests/smoke/ocr2_test.go) + +See soak examples [here](../../integration-tests/soak/tests/ocr_test.go) +and [here](../../integration-tests/soak/soak_runner_test.go) + +1. Instantiate Gauntlet +2. Deploy Cluster +3. Set Gauntlet network +4. Deploy accounts on L2 for the nodes +5. Fund the accounts +6. Deploy L2 PLI token via Gauntlet +7. Deploy L2 Access controller contract via Gauntlet +8. Deploy L2 OCR2 contract via Gauntlet +9. Set OCR2 billing via Gauntlet +10. Set OCR2 config details via Gauntlet +11. Set up boostrap and oracle nodes + +### Metrics and logs (K8) + +1. Navigate to Grafana +2. Search for `plugin-testing-insights` dashboard +3. Select the starknet namespace + +Here you will find pod logs for all the plugin nodes as well as Devnet / Geth + + +# Testing wiki + +## Testnet + +- Chain name - `Starknet` +- Chain ID - `SN_GOERLI` + - Testnet 1 - `[https://alpha4.starknet.io](https://alpha4.starknet.io)` + - Testnet 2 - [`https://alpha4-2.starknet.io`](https://alpha4-2.starknet.io/) + +## Mainnet + +- Chain name - `Starknet` +- Chain ID - `SN_MAIN` + - `[https://alpha-mainnet.starknet.io](https://alpha-mainnet.starknet.io)` + +# Node config + +```bash +[[Starknet]] +Enabled = true +ChainID = '' +[[Starknet.Nodes]] +Name = 'primary' +URL = '' + +[OCR2] +Enabled = true + +[P2P] +[P2P.V2] +Enabled = true +DeltaDial = '5s' +DeltaReconcile = '5s' +ListenAddresses = ['0.0.0.0:6690'] +``` + +# Gauntlet steps + +## Environment file + +```bash +NODE_URL= +ACCOUNT= +PRIVATE_KEY= +``` + +1. Deploy link + +```bash +yarn gauntlet token:deploy --link +``` + +2. Deploy access controller + +```bash +yarn gauntlet access_controller:deploy +``` + +3. Deploy OCR2 + +```bash +yarn gauntlet ocr2:deploy --minSubmissionValue= --maxSubmissionValue= --decimals= --name= --link= +``` + +4. Deploy proxy + +```bash +yarn gauntlet proxy:deploy +``` + +5. Add access to proxy + +```bash +yarn gauntlet ocr2:add_access --address= +``` + +6. Mint PLI + +```bash +yarn gauntlet token:mint --recipient --amount= +``` + +7. Set billing + +```bash +yarn gauntlet ocr2:set_billing --observationPaymentGjuels= --transmissionPaymentGjuels= +``` + +8. Set config + 1. Example config testnet + + ```bash + { + "f": 1, + "signers": [ + "ocr2on_starknet_0371028377bfd793b7e2965757e348309e7242802d20253da6ab81c8eb4b4051", + "ocr2on_starknet_073cadfc4474e8c6c79f66fa609da1dbcd5be4299ff9b1f71646206d1faca1fc", + "ocr2on_starknet_0386d1a9d93792c426739f73afa1d0b19782fbf30ae27ce33c9fbd4da659cd80", + "ocr2on_starknet_005360052758819ba2af790469a28353b7ff6f8b84176064ab572f6cc20e5fb4" + ], + "transmitters": [ + "0x0...", + "0x0...", + "0x0...", + "0x0..." + ], + "onchainConfig": "", + "offchainConfig": { + "deltaProgressNanoseconds": 8000000000, + "deltaResendNanoseconds": 30000000000, + "deltaRoundNanoseconds": 3000000000, + "deltaGraceNanoseconds": 1000000000, + "deltaStageNanoseconds": 20000000000, + "rMax": 5, + "s": [ + 1, + 1, + 1, + 1 + ], + "offchainPublicKeys": [ + "ocr2off_starknet_0...", + "ocr2off_starknet_0...", + "ocr2off_starknet_0...", + "ocr2off_starknet_0..." + ], + "peerIds": [ + "12D3..", + "12D3..", + "12D3..", + "12D3.." + ], + "reportingPluginConfig": { + "alphaReportInfinite": false, + "alphaReportPpb": 0, + "alphaAcceptInfinite": false, + "alphaAcceptPpb": 0, + "deltaCNanoseconds": 1000000000 + }, + "maxDurationQueryNanoseconds": 0, + "maxDurationObservationNanoseconds": 1000000000, + "maxDurationReportNanoseconds": 2000000000, + "maxDurationShouldAcceptFinalizedReportNanoseconds": 2000000000, + "maxDurationShouldTransmitAcceptedReportNanoseconds": 2000000000, + "configPublicKeys": [ + "ocr2cfg_starknet_...", + "ocr2cfg_starknet_...", + "ocr2cfg_starknet_...", + "ocr2cfg_starknet_..." + ] + }, + "offchainConfigVersion": 2, + "secret": "some secret you want" + } + ``` + + +```bash +yarn gauntlet ocr2:set_config --input= +``` \ No newline at end of file diff --git a/docs/integration-tests/testing.md b/docs/integration-tests/testing.md new file mode 100644 index 0000000..d4e6301 --- /dev/null +++ b/docs/integration-tests/testing.md @@ -0,0 +1,5 @@ +## Integration tests usage + +The testing suite uses `plugin-env` as the base for programmatic control of kubernetes clusters. + +[Repo + Docs](https://github.com/goplugin/plugin-env) diff --git a/docs/kubernetes.md b/docs/kubernetes.md new file mode 100644 index 0000000..2da3314 --- /dev/null +++ b/docs/kubernetes.md @@ -0,0 +1,19 @@ +# Kubernetes + +We run our software in Kubernetes. + +### Local k3d setup + +1. `make install` +2. (Optional) Install `Lens` from [here](https://k8slens.dev/) or use `k9s` as a low resource consumption alternative from [here](https://k9scli.io/topics/install/) + or from source [here](https://github.com/goplugin/helmenv) +3. Setup your docker resources, 6vCPU/10Gb RAM are enough for most CL related tasks +4. `k3d cluster create local` +5. Check your contexts with `kubectl config get-contexts` +6. Switch context `kubectl config use-context k3d-local` +7. Run any tests, use a guide [here](integration-tests/README.md) +8. Stop the cluster + +``` +k3d cluster stop local +``` diff --git a/examples/contracts/aggregator-consumer/.gitignore b/examples/contracts/aggregator-consumer/.gitignore new file mode 100644 index 0000000..793bd7c --- /dev/null +++ b/examples/contracts/aggregator-consumer/.gitignore @@ -0,0 +1,2 @@ +cache/ +starknet-artifacts/ \ No newline at end of file diff --git a/examples/contracts/aggregator-consumer/contracts/Aggregator_consumer.cairo b/examples/contracts/aggregator-consumer/contracts/Aggregator_consumer.cairo new file mode 100644 index 0000000..aae9031 --- /dev/null +++ b/examples/contracts/aggregator-consumer/contracts/Aggregator_consumer.cairo @@ -0,0 +1,32 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from plugin.cairo.ocr2.IAggregator import IAggregator, Round + +@storage_var +func AggregatorConsumer_ocr_address() -> (address: felt) { +} + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(address: felt) { + AggregatorConsumer_ocr_address.write(address); + return (); +} + +@view +func readLatestRound{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round +) { + let (address) = AggregatorConsumer_ocr_address.read(); + let (round: Round) = IAggregator.latest_round_data(contract_address=address); + return (round,); +} + +@view +func readDecimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + decimals: felt +) { + let (address) = AggregatorConsumer_ocr_address.read(); + let (decimals) = IAggregator.decimals(contract_address=address); + return (decimals,); +} diff --git a/examples/contracts/aggregator-consumer/contracts/MockAggregator.cairo b/examples/contracts/aggregator-consumer/contracts/MockAggregator.cairo new file mode 100644 index 0000000..87b4b36 --- /dev/null +++ b/examples/contracts/aggregator-consumer/contracts/MockAggregator.cairo @@ -0,0 +1,8 @@ +%lang starknet + +from plugin.cairo.ocr2.mocks.MockAggregator import ( + constructor, + set_latest_round_data, + latest_round_data, + decimals, +) diff --git a/examples/contracts/aggregator-consumer/contracts/Price_Consumer_With_Sequencer_Check.cairo b/examples/contracts/aggregator-consumer/contracts/Price_Consumer_With_Sequencer_Check.cairo new file mode 100644 index 0000000..e5d9b15 --- /dev/null +++ b/examples/contracts/aggregator-consumer/contracts/Price_Consumer_With_Sequencer_Check.cairo @@ -0,0 +1,74 @@ +%lang starknet + +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.math import assert_not_zero +from starkware.cairo.common.math_cmp import is_nn +from starkware.cairo.common.bool import TRUE, FALSE +from starkware.starknet.common.syscalls import get_block_timestamp + +from plugin.cairo.ocr2.IAggregator import IAggregator, Round + +@storage_var +func PriceConsumerWithSequencerCheck_uptime_feed_address() -> (address: felt) { +} + +@storage_var +func PriceConsumerWithSequencerCheck_aggregator_address() -> (address: felt) { +} + +// If the sequencer is up and that 60 sec has passed, +// The function retrieves the latest price from the data feed using the priceFeed object. +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + uptime_feed_address: felt, aggregator_address: felt +) { + assert_not_zero(uptime_feed_address); + assert_not_zero(aggregator_address); + + PriceConsumerWithSequencerCheck_uptime_feed_address.write(uptime_feed_address); + PriceConsumerWithSequencerCheck_aggregator_address.write(aggregator_address); + return (); +} + +// If the sequencer is up and report is OK then we can get the latest price. +@view +func get_latest_price{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: felt +) { + assert_sequencer_healthy(); + let (aggregator_address) = PriceConsumerWithSequencerCheck_aggregator_address.read(); + let (round: Round) = IAggregator.latest_round_data(contract_address=aggregator_address); + return (round=round.answer); +} + +// Errors if the report is stale, or it's reported that Sequencer node is down +@external +func assert_sequencer_healthy{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { + alloc_locals; + + let (uptime_feed_address) = PriceConsumerWithSequencerCheck_uptime_feed_address.read(); + + // Get latest_round_data from sequencer contract which should be update by a message send from L1 + let (round: Round) = IAggregator.latest_round_data(contract_address=uptime_feed_address); + let (local block_timestemp) = get_block_timestamp(); + let time = block_timestemp - round.updated_at; + + // After 60 sec the report is considered stale + let is_ls = is_nn(time - (60 + 1)); + + // 0 if the sequencer is up and 1 if it is down + if (round.answer == 0) { + with_attr error_message("PriceConsumer: L2 Sequencer is up, report stale") { + assert is_ls = 1; + } + return (); + } + with_attr error_message("PriceConsumer: L2 Sequencer is down, report stale") { + assert is_ls = 1; + } + with_attr error_message("PriceConsumer: L2 Sequencer is down, report ok") { + assert round.answer = 0; + } + return (); +} diff --git a/examples/contracts/aggregator-consumer/getting_start.md b/examples/contracts/aggregator-consumer/getting_start.md new file mode 100644 index 0000000..70775c2 --- /dev/null +++ b/examples/contracts/aggregator-consumer/getting_start.md @@ -0,0 +1,25 @@ +0. `.env` contains predeploy and funded account details, such as DEPLOYER_ACCOUNT_ADDRESS and DEPLOYER_PRIVATE_KEY + +1. Set up the network `export STARKNET_NETWORK=alpha-goerli` + +2. Choose a wallet provider `export STARKNET_WALLET=starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount` + +3. If you don't have an account create it with the command `starknet new_account` + +4. Open that link https://faucet.goerli.starknet.io/ and past the address to get some faucet. If you can not get faucet you can transfer some eth from one of you L1 accounts to starknet https://goerli.starkgate.starknet.io/. + +5. When you have be able to get some faucet you can deploy your account `starknet deploy_account` (for more information take a look at this documentation https://starknet.io/docs/hello_starknet/account_setup.html). + +6. Create a `.env` in `exemples/contracts/aggregator-consumer`and copy past your account address under `DEPLOYER_ACCOUNT_ADDRESS` and you private key under `DEPLOYER_PRIVATE_KEY`. You can find the private key in your home directory under `.starknet_accounts` folder in `starknet_open_zeppelin_accounts.json`. + +7. Start by deploying accounts with `npx ts-node ./scripts/deploy_accounts.ts` + +8. It'll write in previously created `.env`. + +9. Open that link https://faucet.goerli.starknet.io/ and past the address of the new accounts to get some faucet. + +10. Deploy the contracts by running `npx ts-node ./scripts/deploy_contracts.ts.` + +11. You can now read decimals and latest round data by running `yarn readDecimals` and `yarn readLatestRound`. + +12. You can update value and see continuously the data by openning another terminal and run `npx ts-node ./scripts/updateLatestRound.ts` in one terminal and `npx ts-node ./scripts/readContinuously` into another one. diff --git a/examples/contracts/aggregator-consumer/hardhat.config.ts b/examples/contracts/aggregator-consumer/hardhat.config.ts new file mode 100644 index 0000000..a954ac9 --- /dev/null +++ b/examples/contracts/aggregator-consumer/hardhat.config.ts @@ -0,0 +1,34 @@ +import { HardhatUserConfig } from 'hardhat/types' +import '@shardlabs/starknet-hardhat-plugin' +import '@nomiclabs/hardhat-ethers' + +const config: HardhatUserConfig = { + solidity: '0.8.14', + starknet: { + venv: 'active', + network: 'devnet', + wallets: { + OpenZeppelin: { + accountName: 'OpenZeppelin', + modulePath: 'starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount', + accountPath: '~/.starknet_accounts', + }, + }, + }, + networks: { + devnet: { + url: 'http://127.0.0.1:5050', + }, + integratedDevnet: { + url: 'http://127.0.0.1:5050', + venv: 'active', + args: ['--lite-mode'], + // dockerizedVersion: "0.2.0" + }, + }, + paths: { + cairoPaths: ['../../../contracts/src'], + }, +} + +export default config diff --git a/examples/contracts/aggregator-consumer/package.json b/examples/contracts/aggregator-consumer/package.json new file mode 100644 index 0000000..59b0990 --- /dev/null +++ b/examples/contracts/aggregator-consumer/package.json @@ -0,0 +1,28 @@ +{ + "name": "@pluginv3.0/starknet-ocr2-consumer", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "compile:cairo": "hardhat starknet-compile", + "compile": "yarn compile:cairo", + "test": "npx hardhat --network localhost test", + "readDecimals": "npx ts-node ./scripts/readDecimals.ts", + "readLatestRound": "npx ts-node ./scripts/readLatestRound.ts" + }, + "keywords": [], + "author": "", + "license": "MIT", + "devDependencies": { + "@nomiclabs/hardhat-ethers": "^2.1.0", + "@shardlabs/starknet-hardhat-plugin": "^0.8.0-alpha.0", + "@types/chai": "^4.3.3", + "@types/mocha": "^9.1.1", + "chai": "^4.3.6", + "hardhat": "^*" + }, + "dependencies": { + "@pluginv3.0/starknet": "^1.0.0", + "dotenv": "^16.0.1" + } +} diff --git a/examples/contracts/aggregator-consumer/scripts/consumerValidator.ts b/examples/contracts/aggregator-consumer/scripts/consumerValidator.ts new file mode 100644 index 0000000..0f2ebaa --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/consumerValidator.ts @@ -0,0 +1,127 @@ +import { ethers, starknet, network } from 'hardhat' +import { Contract, ContractFactory } from 'ethers' +import { HttpNetworkConfig } from 'hardhat/types' + +import dotenv from 'dotenv' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { deployMockContract, MockContract } from '@ethereum-waffle/mock-contract' +import { Account, Contract as StarknetContract } from 'starknet' +import { + createDeployerAccount, + loadContractPath, + loadContract_Solidity, + loadContract_Solidity_V8, + makeProvider, +} from './utils' + +dotenv.config({ path: __dirname + '/../.env' }) +const UPTIME_FEED_PATH = + '../../../../contracts/starknet-artifacts/src/plugin/cairo/emergency/SequencerUptimeFeed' +const UPTIME_FEED_NAME = 'sequencer_uptime_feed' + +let validator: Contract +let mockStarknetMessengerFactory: ContractFactory +let mockStarknetMessenger: Contract +let deployer: SignerWithAddress +let eoaValidator: SignerWithAddress +let networkUrl: string +let account: Account + +let mockGasPriceFeed: MockContract +let mockAccessController: MockContract +let mockAggregator: MockContract + +export async function consumerValidator() { + const provider = makeProvider() + + account = createDeployerAccount(provider) + + networkUrl = (network.config as HttpNetworkConfig).url + const accounts = await ethers.getSigners() + deployer = accounts[0] + eoaValidator = accounts[1] + + const aggregatorAbi = loadContract_Solidity_V8('AggregatorV3Interface') + const accessControllerAbi = loadContract_Solidity_V8('AccessControllerInterface') + + // Deploy the mock feed + mockGasPriceFeed = await deployMockContract(deployer, aggregatorAbi.abi) + await mockGasPriceFeed.mock.latestRoundData.returns( + '73786976294838220258' /** roundId */, + '96800000000' /** answer */, + '163826896' /** startedAt */, + '1638268960' /** updatedAt */, + '73786976294838220258' /** answeredInRound */, + ) + + // Deploy the mock access controller + mockAccessController = await deployMockContract(deployer, accessControllerAbi.abi) + + // Deploy the mock aggregator + mockAggregator = await deployMockContract(deployer, aggregatorAbi.abi) + await mockAggregator.mock.latestRoundData.returns( + '73786976294838220258' /** roundId */, + 1 /** answer */, + '163826896' /** startedAt */, + '1638268960' /** updatedAt */, + '73786976294838220258' /** answeredInRound */, + ) + + const validatorArtifact = await loadContract_Solidity('emergency', 'StarknetValidator') + const validatorFactory = await ethers.getContractFactoryFromArtifact(validatorArtifact, deployer) + + const mockStarknetMessagingArtifact = await loadContract_Solidity( + 'mocks', + 'MockStarknetMessaging', + ) + mockStarknetMessengerFactory = await ethers.getContractFactoryFromArtifact( + mockStarknetMessagingArtifact, + deployer, + ) + + const messageCancellationDelay = 5 * 60 // seconds + mockStarknetMessenger = await mockStarknetMessengerFactory.deploy(messageCancellationDelay) + await mockStarknetMessenger.deployed() + + const UptimeFeedArtifact = loadContractPath(UPTIME_FEED_PATH, UPTIME_FEED_NAME) + + const mockUptimeFeedDeploy = new StarknetContract( + UptimeFeedArtifact.abi, + process.env.UPTIME_FEED as string, + provider, + ) + + validator = await validatorFactory.deploy( + mockStarknetMessenger.address, + mockAccessController.address, + mockGasPriceFeed.address, + mockAggregator.address, + mockUptimeFeedDeploy.address, + 0, + ) + + console.log('Validator address: ', validator.address) + const transaction = await account.execute( + { + contractAddress: mockUptimeFeedDeploy.address, + entrypoint: 'set_l1_sender', + calldata: [validator.address], + }, + [UptimeFeedArtifact.abi], + ) + + await provider.waitForTransaction(transaction.transaction_hash) + + await validator.addAccess(eoaValidator.address) + setInterval(callFunction, 60_000) +} + +async function callFunction() { + await starknet.devnet.loadL1MessagingContract(networkUrl, mockStarknetMessenger.address) + + await validator.connect(eoaValidator).validate(0, 0, 1, 1) + + const flushL1Response = await starknet.devnet.flush() + flushL1Response.consumed_messages.from_l1 +} +consumerValidator() diff --git a/examples/contracts/aggregator-consumer/scripts/deploy_accounts.ts b/examples/contracts/aggregator-consumer/scripts/deploy_accounts.ts new file mode 100644 index 0000000..f89a93e --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/deploy_accounts.ts @@ -0,0 +1,60 @@ +import fs from 'fs' +import dotenv from 'dotenv' +import { ec, CallData } from 'starknet' +import { loadContract_Account, createDeployerAccount, makeProvider } from './utils' + +dotenv.config({ path: __dirname + '/../.env' }) + +const ACCOUNT_NAME = 'Account' +interface UserAccount { + account: string + privateKey: Uint8Array +} +let firstAccount: UserAccount + +export async function deployAccount() { + firstAccount = await createAccount() + + fs.appendFile(__dirname + '/../.env', '\nACCOUNT_ADDRESS=' + firstAccount.account, function ( + err, + ) { + if (err) throw err + }) + fs.appendFile(__dirname + '/../.env', '\nPRIVATE_KEY=' + firstAccount.privateKey, function (err) { + if (err) throw err + }) +} + +async function createAccount(): Promise { + const provider = makeProvider() + + const predeployedAccount = createDeployerAccount(provider) + + const compiledAccount = loadContract_Account(ACCOUNT_NAME) + const privateKey = ec.starkCurve.utils.randomPrivateKey() + + const starkKeyPub = ec.starkCurve.getStarkKey(privateKey) + const OZaccountConstructorCallData = CallData.compile({ publicKey: starkKeyPub }) + + const declareTx = await predeployedAccount.declare({ + classHash: '0x4d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f', + contract: compiledAccount, + }) + + console.log('Declare new Account...') + await provider.waitForTransaction(declareTx.transaction_hash) + + const salt = '900080545022' + const accountResponse = await predeployedAccount.deploy({ + classHash: '0x4d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f', + constructorCalldata: OZaccountConstructorCallData, + salt, + }) + + console.log('Waiting for Tx to be Accepted on Starknet - OZ Account Deployment...') + await provider.waitForTransaction(accountResponse.transaction_hash) + + return { account: accountResponse.contract_address[0], privateKey: privateKey } +} + +deployAccount() diff --git a/examples/contracts/aggregator-consumer/scripts/deploy_contracts.ts b/examples/contracts/aggregator-consumer/scripts/deploy_contracts.ts new file mode 100644 index 0000000..6e5fff4 --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/deploy_contracts.ts @@ -0,0 +1,93 @@ +import { Contract } from 'starknet' +import { loadContract, createDeployerAccount, loadContractPath, makeProvider } from './utils' +import fs from 'fs' +import dotenv from 'dotenv' + +const CONSUMER_NAME = 'Aggregator_consumer' + +const MOCK_NAME = 'MockAggregator' + +const PRICE_CONSUMER_NAME = 'Price_Consumer_With_Sequencer_Check' + +const UPTIME_FEED_PATH = + '../../../../contracts/starknet-artifacts/src/plugin/cairo/emergency/SequencerUptimeFeed' +const UPTIME_FEED_NAME = 'sequencer_uptime_feed' + +const DECIMALS = '18' + +dotenv.config({ path: __dirname + '/../.env' }) + +export async function deployContract() { + const provider = makeProvider() + const MockArtifact = loadContract(MOCK_NAME) + const AggregatorArtifact = loadContract(CONSUMER_NAME) + const priceConsumerArtifact = loadContract(PRICE_CONSUMER_NAME) + const UptimeFeedArtifact = loadContractPath(UPTIME_FEED_PATH, UPTIME_FEED_NAME) + + const account = createDeployerAccount(provider) + + const declareDeployMock = await account.declareAndDeploy({ + contract: MockArtifact, + constructorCalldata: [DECIMALS], + }) + + const mockDeploy = new Contract( + MockArtifact.abi, + declareDeployMock.deploy.contract_address, + provider, + ) + + const declareDeployAggregator = await account.declareAndDeploy({ + contract: AggregatorArtifact, + constructorCalldata: [mockDeploy.address as string], + }) + + const consumerDeploy = new Contract( + AggregatorArtifact.abi, + declareDeployAggregator.deploy.contract_address, + provider, + ) + + const declareDeployUptimeFeed = await account.declareAndDeploy({ + contract: UptimeFeedArtifact, + constructorCalldata: ['0', account.address], + }) + + const uptimeFeedDeploy = new Contract( + UptimeFeedArtifact.abi, + declareDeployUptimeFeed.deploy.contract_address, + provider, + ) + + const declareDeployPriceConsumer = await account.declareAndDeploy({ + contract: priceConsumerArtifact, + constructorCalldata: [uptimeFeedDeploy.address as string, mockDeploy.address as string], + }) + + const priceConsumerDeploy = new Contract( + priceConsumerArtifact.abi, + declareDeployPriceConsumer.deploy.contract_address, + provider, + ) + + fs.appendFile(__dirname + '/../.env', '\nCONSUMER=' + consumerDeploy.address, function (err) { + if (err) throw err + }) + fs.appendFile(__dirname + '/../.env', '\nMOCK=' + mockDeploy.address, function (err) { + if (err) throw err + }) + fs.appendFile( + __dirname + '/../.env', + '\nPRICE_CONSUMER=' + priceConsumerDeploy.address, + function (err) { + if (err) throw err + }, + ) + fs.appendFile(__dirname + '/../.env', '\nUPTIME_FEED=' + uptimeFeedDeploy.address, function ( + err, + ) { + if (err) throw err + }) +} + +deployContract() diff --git a/examples/contracts/aggregator-consumer/scripts/getLatestPrice.ts b/examples/contracts/aggregator-consumer/scripts/getLatestPrice.ts new file mode 100644 index 0000000..bfa3daf --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/getLatestPrice.ts @@ -0,0 +1,54 @@ +import dotenv from 'dotenv' +import { createDeployerAccount, loadContract, loadContractPath, makeProvider } from './utils' +import { Contract } from 'starknet' + +const PRICE_CONSUMER_NAME = 'Price_Consumer_With_Sequencer_Check' +const UPTIME_FEED_PATH = + '../../../../contracts/starknet-artifacts/src/plugin/cairo/emergency/SequencerUptimeFeed' +const UPTIME_FEED_NAME = 'sequencer_uptime_feed' + +dotenv.config({ path: __dirname + '/../.env' }) + +export async function getLatestPrice() { + const provider = makeProvider() + + const account = createDeployerAccount(provider) + + const priceConsumerArtifact = loadContract(PRICE_CONSUMER_NAME) + const UptimeFeedArtifact = loadContractPath(UPTIME_FEED_PATH, UPTIME_FEED_NAME) + + const priceConsumer = new Contract( + priceConsumerArtifact.abi, + process.env.PRICE_CONSUMER as string, + provider, + ) + const uptimeFeed = new Contract( + UptimeFeedArtifact.abi, + process.env.UPTIME_FEED as string, + provider, + ) + + const transaction = await account.execute( + { + contractAddress: uptimeFeed.address, + entrypoint: 'add_access', + calldata: [priceConsumer.address], + }, + [UptimeFeedArtifact.abi], + ) + + console.log('Waiting for Tx to be Accepted on Starknet...') + await provider.waitForTransaction(transaction.transaction_hash) + + const lat = await uptimeFeed.call('latest_round_data') + const latestPrice = await account.callContract({ + contractAddress: priceConsumer.address, + entrypoint: 'get_latest_price', + calldata: [], + }) + + console.log('answer= ', latestPrice) + return latestPrice +} + +getLatestPrice() diff --git a/examples/contracts/aggregator-consumer/scripts/readContinuously.ts b/examples/contracts/aggregator-consumer/scripts/readContinuously.ts new file mode 100644 index 0000000..17a1160 --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/readContinuously.ts @@ -0,0 +1,47 @@ +import { Contract, Account, CallContractResponse } from 'starknet' + +import { createDeployerAccount, loadContract, makeProvider } from './utils' +import dotenv from 'dotenv' + +const CONTRACT_NAME = 'Aggregator_consumer' +let account: Account +let consumer: Contract + +dotenv.config({ path: __dirname + '/../.env' }) + +async function readContinuously() { + const provider = makeProvider() + + account = createDeployerAccount(provider) + + const AggregatorArtifact = loadContract(CONTRACT_NAME) + + consumer = new Contract(AggregatorArtifact.abi, process.env.CONSUMER as string) + setInterval(callFunction, 30000) +} + +async function callFunction() { + const latestRound = await account.callContract({ + contractAddress: consumer.address, + entrypoint: 'readLatestRound', + calldata: [], + }) + + const decimals = await account.callContract({ + contractAddress: consumer.address, + entrypoint: 'readDecimals', + calldata: [], + }) + printResult(latestRound, decimals) +} + +function printResult(latestRound: CallContractResponse, decimals: CallContractResponse) { + console.log('round_id= ', parseInt(latestRound.result[0], 16)) + console.log('answer= ', parseInt(latestRound.result[1], 16)) + console.log('block_num= ', parseInt(latestRound.result[2], 16)) + console.log('staerted_at= ', parseInt(latestRound.result[3], 16)) + console.log('updated_at= ', parseInt(latestRound.result[4], 16)) + console.log('decimals= ', parseInt(decimals.result[0], 16)) +} + +readContinuously() diff --git a/examples/contracts/aggregator-consumer/scripts/readDecimals.ts b/examples/contracts/aggregator-consumer/scripts/readDecimals.ts new file mode 100644 index 0000000..4258cfd --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/readDecimals.ts @@ -0,0 +1,28 @@ +import { Account, Contract } from 'starknet' +import { createDeployerAccount, loadContract, makeProvider } from './utils' +import dotenv from 'dotenv' + +const CONSUMER_NAME = 'Aggregator_consumer' +let account: Account +let consumer: Contract + +dotenv.config({ path: __dirname + '/../.env' }) + +export async function readDecimals() { + const provider = makeProvider() + account = createDeployerAccount(provider) + + const AggregatorArtifact = loadContract(CONSUMER_NAME) + consumer = new Contract(AggregatorArtifact.abi, process.env.CONSUMER as string) + + const decimals = await account.callContract({ + contractAddress: consumer.address, + entrypoint: 'readDecimals', + calldata: [], + }) + + console.log('decimals= ', parseInt(decimals.result[0], 16)) + return parseInt(decimals.result[0], 16) +} + +readDecimals() diff --git a/examples/contracts/aggregator-consumer/scripts/readLatestRound.ts b/examples/contracts/aggregator-consumer/scripts/readLatestRound.ts new file mode 100644 index 0000000..e9c82c3 --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/readLatestRound.ts @@ -0,0 +1,36 @@ +import { Account, Contract, CallContractResponse } from 'starknet' + +import { createDeployerAccount, loadContract, makeProvider } from './utils' +import dotenv from 'dotenv' + +const CONSUMER_NAME = 'Aggregator_consumer' +let account: Account +let consumer: Contract + +dotenv.config({ path: __dirname + '/../.env' }) + +export async function readLatestRound() { + const provider = makeProvider() + account = createDeployerAccount(provider) + + const AggregatorArtifact = loadContract(CONSUMER_NAME) + consumer = new Contract(AggregatorArtifact.abi, process.env.CONSUMER as string) + + const latestRound = await account.callContract({ + contractAddress: consumer.address, + entrypoint: 'readLatestRound', + calldata: [], + }) + printResult(latestRound) + return latestRound +} + +function printResult(latestRound: CallContractResponse) { + console.log('\nround_id= ', parseInt(latestRound.result[0], 16)) + console.log('answer= ', parseInt(latestRound.result[1], 16)) + console.log('block_num= ', parseInt(latestRound.result[2], 16)) + console.log('observation_timestamp= ', parseInt(latestRound.result[3], 16)) + console.log('transmission_timestamp= ', parseInt(latestRound.result[4], 16)) +} + +readLatestRound() diff --git a/examples/contracts/aggregator-consumer/scripts/updateLatestRound.ts b/examples/contracts/aggregator-consumer/scripts/updateLatestRound.ts new file mode 100644 index 0000000..95b0c05 --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/updateLatestRound.ts @@ -0,0 +1,89 @@ +import { Account, Contract, Provider, ec, number } from 'starknet' +import { loadContract, makeProvider } from './utils' +import dotenv from 'dotenv' + +interface Transmission { + answer: number + block_num: number + observation_timestamp: number + transmission_timestamp: number +} + +const CONTRACT_NAME = 'MockAggregator' +let account: Account +let mock: Contract +let transmission: Transmission +let provider: Provider + +dotenv.config({ path: __dirname + '/../.env' }) + +const rl = require('readline').createInterface({ + input: process.stdin, + output: process.stdout, +}) + +async function updateLatestRound() { + provider = makeProvider() + + transmission = { + answer: 0, + block_num: 0, + observation_timestamp: 0, + transmission_timestamp: 0, + } + + const keyPair = ec.getKeyPair(process.env.PRIVATE_KEY as string) + account = new Account(provider, process.env.ACCOUNT_ADDRESS as string, keyPair) + + const MockArtifact = loadContract(CONTRACT_NAME) + + mock = new Contract(MockArtifact.abi, process.env.MOCK as string) + transmission.answer = Number(await input('Enter a number for new answer: ')) + transmission.block_num = Number(await input('Enter a number for new block_num: ')) + transmission.observation_timestamp = Number( + await input('Enter a number for new observation_timestamp: '), + ) + transmission.transmission_timestamp = Number( + await input('Enter a number for new transmission_timestamp: '), + ) + rl.close() + + callFunction(transmission) +} + +async function callFunction(transmission: Transmission) { + const transaction = await account.execute( + { + contractAddress: mock.address, + entrypoint: 'set_latest_round_data', + calldata: [ + transmission.answer, + transmission.block_num, + transmission.observation_timestamp, + transmission.transmission_timestamp, + ], + }, + [mock.abi], + { maxFee: 1e18 }, + ) + console.log('Waiting for Tx to be Accepted on Starknet - Aggregator consumer Deployment...') + await provider.waitForTransaction(transaction.transaction_hash) +} + +function input(prompt: string) { + return new Promise((callbackFn, errorFn) => { + rl.question(prompt, (uinput: string) => { + switch (isNaN(Number(uinput))) { + case true: + console.log('input is not a number we will use the default value of 1') + uinput = '1' + break + default: + break + } + callbackFn(uinput) + }) + }) +} + +updateLatestRound() diff --git a/examples/contracts/aggregator-consumer/scripts/utils.ts b/examples/contracts/aggregator-consumer/scripts/utils.ts new file mode 100644 index 0000000..18bcaa7 --- /dev/null +++ b/examples/contracts/aggregator-consumer/scripts/utils.ts @@ -0,0 +1,79 @@ +import fs from 'fs' +import dotenv from 'dotenv' +import { CompiledContract, json, ec, Account, Provider, constants } from 'starknet' + +const DEVNET_NAME = 'devnet' + +export const loadContract = (name: string): CompiledContract => { + return json.parse( + fs + .readFileSync(`${__dirname}/../starknet-artifacts/contracts/${name}.cairo/${name}.json`) + .toString('ascii'), + ) +} + +export const loadContractPath = (path: string, name: string): CompiledContract => { + return json.parse( + fs.readFileSync(`${__dirname}/${path}/${name}.cairo/${name}.json`).toString('ascii'), + ) +} + +export const loadContract_Account = (name: string): CompiledContract => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../node_modules/@shardlabs/starknet-hardhat-plugin/dist/contract-artifacts/OpenZeppelinAccount/0.5.1/${name}.cairo/${name}.json`, + ) + .toString('ascii'), + ) +} + +export const loadContract_Solidity = (path: string, name: string): any => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/artifacts/src/plugin/solidity/${path}/${name}.sol/${name}.json`, + ) + .toString('ascii'), + ) +} +export const loadContract_Solidity_V8 = (name: string): any => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/artifacts/@pluginv3.0/contracts/src/v0.8/interfaces/${name}.sol/${name}.json`, + ) + .toString('ascii'), + ) +} + +export function createDeployerAccount(provider: Provider): Account { + dotenv.config({ path: __dirname + '/../.env' }) + + const privateKey: string = process.env.DEPLOYER_PRIVATE_KEY as string + const accountAddress: string = process.env.DEPLOYER_ACCOUNT_ADDRESS as string + if (!privateKey || !accountAddress) { + throw new Error('Deployer account address or private key is undefined!') + } + + return new Account(provider, accountAddress, privateKey) +} + +export const makeProvider = () => { + const network = process.env.NETWORK || DEVNET_NAME + if (network === DEVNET_NAME) { + return new Provider({ + sequencer: { + baseUrl: 'http://127.0.0.1:5050/', + feederGatewayUrl: 'feeder_gateway', + gatewayUrl: 'gateway', + }, + }) + } else { + return new Provider({ + sequencer: { + network: constants.NetworkName.SN_GOERLI, + }, + }) + } +} diff --git a/examples/contracts/aggregator-consumer/test/mock/Aggregator_consumer.test.ts b/examples/contracts/aggregator-consumer/test/mock/Aggregator_consumer.test.ts new file mode 100644 index 0000000..fe05600 --- /dev/null +++ b/examples/contracts/aggregator-consumer/test/mock/Aggregator_consumer.test.ts @@ -0,0 +1,83 @@ +import { starknet } from 'hardhat' +import { assert } from 'chai' +import { StarknetContract, Account } from 'hardhat/types/runtime' +import { account } from '@pluginv3.0/starknet' + +describe('ContractTestsMock', function () { + this.timeout(600_000) + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + let alice: Account + let MockContract: StarknetContract + let ConsumerContract: StarknetContract + + before(async () => { + alice = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: alice.address, amount: 1e21 }]) + await alice.deployAccount() + + const decimals = 18 + const MockFactory = await starknet.getContractFactory('MockAggregator.cairo') + await alice.declare(MockFactory) + + MockContract = await alice.deploy(MockFactory, { decimals: decimals }) + + const ConsumerFactory = await starknet.getContractFactory('Aggregator_consumer.cairo') + await alice.declare(ConsumerFactory) + + ConsumerContract = await alice.deploy(ConsumerFactory, { + address: MockContract.address, + }) + }) + + it('should set and read latest round data successfully', async () => { + await alice.invoke(MockContract, 'set_latest_round_data', { + answer: 12, + block_num: 1, + observation_timestamp: 14325, + transmission_timestamp: 87654, + }) + + const { round: round } = await ConsumerContract.call('readLatestRound', {}) + assert.equal(round.answer, 12) + assert.equal(round.block_num, 1) + assert.equal(round.started_at, 14325) + assert.equal(round.updated_at, 87654) + }) + + it('should set and read latest round data successfully for the second time', async () => { + await alice.invoke(MockContract, 'set_latest_round_data', { + answer: 19, + block_num: 2, + observation_timestamp: 14345, + transmission_timestamp: 62543, + }) + + const { round: round } = await ConsumerContract.call('readLatestRound', {}) + assert.equal(round.answer, 19) + assert.equal(round.block_num, 2) + assert.equal(round.started_at, 14345) + assert.equal(round.updated_at, 62543) + }) + + it('should set and read latest round data successfully for the third time', async () => { + await alice.invoke(MockContract, 'set_latest_round_data', { + answer: 42, + block_num: 3, + observation_timestamp: 9876, + transmission_timestamp: 27839, + }) + const { round: round } = await ConsumerContract.call('readLatestRound', {}) + assert.equal(round.answer, 42) + assert.equal(round.block_num, 3) + assert.equal(round.started_at, 9876) + assert.equal(round.updated_at, 27839) + }) + + it('should read Decimals successfully', async () => { + const decimals = await ConsumerContract.call('readDecimals', {}) + assert.equal(decimals.decimals, 18) + }) +}) diff --git a/examples/contracts/aggregator-consumer/test/mock/Examples_test.test.ts b/examples/contracts/aggregator-consumer/test/mock/Examples_test.test.ts new file mode 100644 index 0000000..d946cc5 --- /dev/null +++ b/examples/contracts/aggregator-consumer/test/mock/Examples_test.test.ts @@ -0,0 +1,93 @@ +import { starknet, type } from 'hardhat' +import { assert } from 'chai' +import { account } from '@pluginv3.0/starknet' +import fs from 'fs' +import { readDecimals } from '../../scripts/readDecimals' +import { readLatestRound } from '../../scripts/readLatestRound' +import { createDeployerAccount, loadContract, makeProvider } from '../../scripts/utils' +import { Contract, Provider, number } from 'starknet' +import dotenv from 'dotenv' +import { deployContract } from '../../scripts/deploy_contracts' +import { getLatestPrice } from '../../scripts/getLatestPrice' +import { deployAccount } from '../../scripts/deploy_accounts' +import { consumerValidator } from '../../scripts/consumerValidator' + +describe('ExamplesTests', function () { + dotenv.config({ path: __dirname + '/../../.env' }) + + this.timeout(600_000) + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + let alice: type.Account + let provider: Provider + + before(async () => { + provider = makeProvider() + + alice = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([{ account: alice.address, amount: 1e21 }]) + await alice.deployAccount() + fs.appendFile( + __dirname + '/../../.env', + '\nDEPLOYER_ACCOUNT_ADDRESS=' + alice.address, + function (err) { + if (err) throw err + }, + ) + fs.appendFile( + __dirname + '/../../.env', + '\nDEPLOYER_PRIVATE_KEY=' + alice.privateKey, + function (err) { + if (err) throw err + }, + ) + }) + + it('should deploy contract', async () => { + await deployContract() + }) + + it('should deploy account', async () => { + await deployAccount() + }) + + it('should set and read latest round data successfully', async () => { + const MockArtifact = loadContract('MockAggregator') + const mock = new Contract(MockArtifact.abi, process.env.MOCK as string, provider) + + const bob = createDeployerAccount(provider) + await funder.fund([{ account: bob.address, amount: 1e21 }]) + const transaction = await bob.execute( + { + contractAddress: mock.address, + entrypoint: 'set_latest_round_data', + calldata: [42, 3, 9876, 27839], + }, + [mock.abi], + ) + console.log('Waiting for Tx to be Accepted on Starknet - Aggregator consumer Deployment...') + await provider.waitForTransaction(transaction.transaction_hash) + + const latestRound = await readLatestRound() + assert.equal(parseInt(latestRound.result[1], 16), 42) + assert.equal(parseInt(latestRound.result[2], 16), 3) + assert.equal(parseInt(latestRound.result[3], 16), 9876) + assert.equal(parseInt(latestRound.result[4], 16), 27839) + }) + + it('should read Decimals successfully', async () => { + const decimals = await readDecimals() + assert.equal(decimals, 18) + }) + + it('should test consumer validator', async () => { + await consumerValidator() + }) + + it('should get latest price', async () => { + const latestPrice = await getLatestPrice() + assert.equal(parseInt(latestPrice.result[0], 16), 42) + }) +}) diff --git a/examples/contracts/aggregator-consumer/tsconfig.json b/examples/contracts/aggregator-consumer/tsconfig.json new file mode 100644 index 0000000..05f2b5d --- /dev/null +++ b/examples/contracts/aggregator-consumer/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + }, + "include": [ + "./hardhat.config.ts", + "scripts/**/*" + ], + "exclude": [ + "dist", + "**/*.spec.ts", + "**/*.test.ts" + ] +} diff --git a/examples/contracts/proxy-consumer/.gitignore b/examples/contracts/proxy-consumer/.gitignore new file mode 100644 index 0000000..80b6296 --- /dev/null +++ b/examples/contracts/proxy-consumer/.gitignore @@ -0,0 +1,2 @@ +cache/ +starknet-artifacts/ diff --git a/examples/contracts/proxy-consumer/README.md b/examples/contracts/proxy-consumer/README.md new file mode 100644 index 0000000..4250ef8 --- /dev/null +++ b/examples/contracts/proxy-consumer/README.md @@ -0,0 +1,36 @@ +This is a simple example for how to read Plugin data feeds on Starknet. + +### Requirements + +Set up your environment to run the examples. + +1. [Setup your local Starknet environment](https://starknet.io/docs/quickstart.html). Note that a Python version in the `>=3.6 <=3.9` range is required for compiling and deploying contracts on-chain. The [`cairo-lang` Python package](https://pypi.org/project/cairo-lang/) is not compatible with newer versions of Python as of the [`cairo-lang` 0.10.3](https://pypi.org/project/cairo-lang/0.10.3/) package. Check [starknet.io](https://starknet.io/docs/quickstart.html) for the latest requirements. +1. [Set up a Starknet account](https://starknet.io/docs/hello_starknet/account_setup.html) on Starknet's `alpha-goerli` network and fund it with [testnet ETH](https://faucet.goerli.starknet.io/). These examples expect the OpenZeppelin wallet, which stores your addresses and private keys at `~/.starknet_accounts/starknet_open_zeppelin_accounts.json` by default. +1. [Install NodeJS](https://nodejs.org/en/download/) in the version in the `>=14 <=18` version range. +1. [Install Yarn](https://classic.yarnpkg.com/lang/en/docs/install/). +1. Clone the [goplugin/plugin-starknet](https://github.com/goplugin/plugin-starknet) repository, which includes the example contracts for this guide: `git clone https://github.com/goplugin/plugin-starknet.git` +1. In your clone of the [plugin-starknet](https://github.com/goplugin/plugin-starknet) repository, change directories to the proxy consumer example: `cd ./plugin-starknet/examples/contracts/proxy-consumer/` +1. Run `yarn install` to install the required packages including [Starknet.js](https://www.starknetjs.com/), [HardHat](https://hardhat.org/), and the [Starknet Hardhat Plugin](https://shard-labs.github.io/starknet-hardhat-plugin/). + +### Running the on-chain example + +1. Find the your account address and private key for your funded Starknet testnet account. By default, the OpenZeppelin wallet contains these values at `~/.starknet_accounts/starknet_open_zeppelin_accounts.json`. +1. Export your address to the `DEPLOYER_ACCOUNT_ADDRESS` environment variable and your private key to the `DEPLOYER_PRIVATE_KEY` environment variable. + + ```shell + export DEPLOYER_ACCOUNT_ADDRESS= + ``` + + ```shell + export DEPLOYER_PRIVATE_KEY= + ``` + +1. Run `yarn build` to run Hardhat and create `./starknet-artifacts/` with the compiled contracts. Hardhat uses the [`@shardlabs/starknet-hardhat-plugin` package](https://www.npmjs.com/package/@shardlabs/starknet-hardhat-plugin) for this step. +1. Run `yarn deploy` to deploy the example consumer contract to the Starknet Goerli testnet. The console prints the contract address and transaction hash. +1. Run `yarn readLatestRound ` to send an invoke transaction to the deployed contract. Specify the contract address printed by the deploy step. The deployed contract reads the latest round data from the proxy, stores the values, and prints the resulting values. + +### Running the off-chain example + +This example simply reads the proxy contract to get the latest values with no account or contract compiling steps required. + +1. Run `yarn readLatestRoundOffChain`. diff --git a/examples/contracts/proxy-consumer/contracts/Proxy_consumer.cairo b/examples/contracts/proxy-consumer/contracts/Proxy_consumer.cairo new file mode 100644 index 0000000..0c75a92 --- /dev/null +++ b/examples/contracts/proxy-consumer/contracts/Proxy_consumer.cairo @@ -0,0 +1,50 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.cairo.common.math import assert_not_zero +from plugin.cairo.ocr2.IAggregator import IAggregator, Round + +@storage_var +func consumer_proxy_address() -> (address: felt) { +} + +@storage_var +func feed_data() -> (data: Round) { +} + +@constructor +func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + proxy_address: felt +) { + assert_not_zero(proxy_address); + consumer_proxy_address.write(proxy_address); + get_latest_round_data(); + return (); +} + +// Get the latest data and store it. +@external +func get_latest_round_data{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + round: Round +) { + let (proxy: felt) = consumer_proxy_address.read(); + let (round: Round) = IAggregator.latest_round_data(contract_address=proxy); + feed_data.write(round); + return (round=round); +} + +@view +func get_stored_round{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + res: Round +) { + let (res) = feed_data.read(); + return (res=res); +} + +@view +func get_stored_feed_address{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( + res: felt +) { + let (res) = consumer_proxy_address.read(); + return (res=res); +} diff --git a/examples/contracts/proxy-consumer/contracts/aggregator_proxy_abi.json b/examples/contracts/proxy-consumer/contracts/aggregator_proxy_abi.json new file mode 100644 index 0000000..227ae85 --- /dev/null +++ b/examples/contracts/proxy-consumer/contracts/aggregator_proxy_abi.json @@ -0,0 +1,451 @@ +[ + { + "members": [ + { + "name": "round_id", + "offset": 0, + "type": "felt" + }, + { + "name": "answer", + "offset": 1, + "type": "felt" + }, + { + "name": "block_num", + "offset": 2, + "type": "felt" + }, + { + "name": "started_at", + "offset": 3, + "type": "felt" + }, + { + "name": "updated_at", + "offset": 4, + "type": "felt" + } + ], + "name": "Round", + "size": 5, + "type": "struct" + }, + { + "data": [ + { + "name": "round_id", + "type": "felt" + }, + { + "name": "answer", + "type": "felt" + }, + { + "name": "transmitter", + "type": "felt" + }, + { + "name": "observation_timestamp", + "type": "felt" + }, + { + "name": "observers", + "type": "felt" + }, + { + "name": "observations_len", + "type": "felt" + }, + { + "name": "observations", + "type": "felt*" + }, + { + "name": "juels_per_fee_coin", + "type": "felt" + }, + { + "name": "gas_price", + "type": "felt" + }, + { + "name": "config_digest", + "type": "felt" + }, + { + "name": "epoch_and_round", + "type": "felt" + }, + { + "name": "reimbursement", + "type": "felt" + } + ], + "keys": [], + "name": "NewTransmission", + "type": "event" + }, + { + "data": [ + { + "name": "current", + "type": "felt" + }, + { + "name": "round_id", + "type": "felt" + }, + { + "name": "timestamp", + "type": "felt" + } + ], + "keys": [], + "name": "AnswerUpdated", + "type": "event" + }, + { + "data": [ + { + "name": "round_id", + "type": "felt" + }, + { + "name": "started_by", + "type": "felt" + }, + { + "name": "started_at", + "type": "felt" + } + ], + "keys": [], + "name": "NewRound", + "type": "event" + }, + { + "data": [ + { + "name": "previousOwner", + "type": "felt" + }, + { + "name": "newOwner", + "type": "felt" + } + ], + "keys": [], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "data": [ + { + "name": "from_address", + "type": "felt" + }, + { + "name": "to", + "type": "felt" + } + ], + "keys": [], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "data": [ + { + "name": "user", + "type": "felt" + } + ], + "keys": [], + "name": "AddedAccess", + "type": "event" + }, + { + "data": [ + { + "name": "user", + "type": "felt" + } + ], + "keys": [], + "name": "RemovedAccess", + "type": "event" + }, + { + "data": [], + "keys": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "data": [], + "keys": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "owner", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposed_owner", + "outputs": [ + { + "name": "proposed_owner", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "new_owner", + "type": "felt" + } + ], + "name": "transfer_ownership", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "accept_ownership", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "user", + "type": "felt" + } + ], + "name": "add_access", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "user", + "type": "felt" + } + ], + "name": "remove_access", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "enable_access_check", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "disable_access_check", + "outputs": [], + "type": "function" + }, + { + "data": [ + { + "name": "current", + "type": "felt" + }, + { + "name": "proposed", + "type": "felt" + } + ], + "keys": [], + "name": "AggregatorProposed", + "type": "event" + }, + { + "data": [ + { + "name": "previous", + "type": "felt" + }, + { + "name": "latest", + "type": "felt" + } + ], + "keys": [], + "name": "AggregatorConfirmed", + "type": "event" + }, + { + "inputs": [ + { + "name": "owner", + "type": "felt" + }, + { + "name": "address", + "type": "felt" + } + ], + "name": "constructor", + "outputs": [], + "type": "constructor" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + } + ], + "name": "propose_aggregator", + "outputs": [], + "type": "function" + }, + { + "inputs": [ + { + "name": "address", + "type": "felt" + } + ], + "name": "confirm_aggregator", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "latest_round_data", + "outputs": [ + { + "name": "round", + "type": "Round" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "round_id", + "type": "felt" + } + ], + "name": "round_data", + "outputs": [ + { + "name": "round", + "type": "Round" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proposed_latest_round_data", + "outputs": [ + { + "name": "round", + "type": "Round" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "round_id", + "type": "felt" + } + ], + "name": "proposed_round_data", + "outputs": [ + { + "name": "round", + "type": "Round" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "aggregator", + "outputs": [ + { + "name": "aggregator", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "phase_id", + "outputs": [ + { + "name": "phase_id", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "name": "description", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "decimals", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "type_and_version", + "outputs": [ + { + "name": "meta", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/examples/contracts/proxy-consumer/hardhat.config.ts b/examples/contracts/proxy-consumer/hardhat.config.ts new file mode 100644 index 0000000..0aea8ea --- /dev/null +++ b/examples/contracts/proxy-consumer/hardhat.config.ts @@ -0,0 +1,22 @@ +import { HardhatUserConfig } from 'hardhat/types' +import '@shardlabs/starknet-hardhat-plugin' + +const config: HardhatUserConfig = { + solidity: '0.8.14', + starknet: { + venv: 'active', + network: 'alphaGoerli', + wallets: { + OpenZeppelin: { + accountName: 'OpenZeppelin', + modulePath: 'starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount', + accountPath: '~/.starknet_accounts', + }, + }, + }, + paths: { + cairoPaths: ['../../../contracts/src'], + }, +} + +export default config diff --git a/examples/contracts/proxy-consumer/package.json b/examples/contracts/proxy-consumer/package.json new file mode 100644 index 0000000..a447a0f --- /dev/null +++ b/examples/contracts/proxy-consumer/package.json @@ -0,0 +1,18 @@ +{ + "name": "proxy-consumer", + "version": "1.0.0", + "description": "Simple contracts to read Plugin data feeds on-chain and off-chain", + "scripts": { + "build": "yarn hardhat starknet-compile", + "deploy": "yarn ts-node ./scripts/deployConsumer.ts", + "readLatestRound": "yarn ts-node ./scripts/readLatestRound.ts", + "readLatestRoundOffChain": "yarn ts-node ./scripts/readLatestRoundOffChain.ts" + }, + "license": "MIT", + "devDependencies": { + "@shardlabs/starknet-hardhat-plugin": "^0.8.0-alpha.0" + }, + "dependencies": { + "starknet": "^4.17.1" + } +} diff --git a/examples/contracts/proxy-consumer/scripts/deployConsumer.ts b/examples/contracts/proxy-consumer/scripts/deployConsumer.ts new file mode 100644 index 0000000..443bfed --- /dev/null +++ b/examples/contracts/proxy-consumer/scripts/deployConsumer.ts @@ -0,0 +1,60 @@ +import fs from 'fs' +import { Account, Provider, Contract, json, ec } from 'starknet' + +// Starknet network: Either goerli-alpha or mainnet-alpha +const network = 'goerli-alpha' + +// The Cairo contract that is compiled and ready to declare and deploy +const consumerContractName = 'Proxy_consumer' +const consumerClassHash = '0x75f25b359402fa046e2b9c17d00138772b51c647c0352eb16954e9e39df4ca6' + +/** + * Network: Starknet Goerli testnet + * Aggregator: PLI/USD + * Address: 0x2579940ca3c41e7119283ceb82cd851c906cbb1510908a913d434861fdcb245 + * Find more feed address at: + * https://docs.chain.link/data-feeds/price-feeds/addresses?network=starknet + */ +const dataFeedAddress = '0x2579940ca3c41e7119283ceb82cd851c906cbb1510908a913d434861fdcb245' + +/** Environment variables for a deployed and funded account to use for deploying contracts + * Find your OpenZeppelin account address and private key at: + * ~/.starknet_accounts/starknet_open_zeppelin_accounts.json + */ +const accountAddress = process.env.DEPLOYER_ACCOUNT_ADDRESS as string +const accountKeyPair = ec.getKeyPair(process.env.DEPLOYER_PRIVATE_KEY as string) + +export async function deployContract() { + const provider = new Provider({ + sequencer: { + network: network, + }, + }) + + const account = new Account(provider, accountAddress, accountKeyPair) + + const consumerContract = json.parse( + fs + .readFileSync( + `${__dirname}/../starknet-artifacts/contracts/${consumerContractName}.cairo/${consumerContractName}.json`, + ) + .toString('ascii'), + ) + + const declareDeployConsumer = await account.declareDeploy({ + contract: consumerContract, + classHash: consumerClassHash, + constructorCalldata: [dataFeedAddress as string], + }) + + const consumerDeploy = new Contract( + consumerContract.abi, + declareDeployConsumer.deploy.contract_address, + provider, + ) + + console.log('Contract address: ' + consumerDeploy.address) + console.log('Transaction hash: ' + declareDeployConsumer.deploy.transaction_hash) +} + +deployContract() diff --git a/examples/contracts/proxy-consumer/scripts/readLatestRound.ts b/examples/contracts/proxy-consumer/scripts/readLatestRound.ts new file mode 100644 index 0000000..8eff53d --- /dev/null +++ b/examples/contracts/proxy-consumer/scripts/readLatestRound.ts @@ -0,0 +1,81 @@ +import fs from 'fs' +import { Account, Provider, Contract, CallContractResponse, json, ec } from 'starknet' + +// Starknet network: Either goerli-alpha or mainnet-alpha +const network = 'goerli-alpha' + +/** Environment variables for a deployed and funded account to use for deploying contracts + * Find your OpenZeppelin account address and private key at: + * ~/.starknet_accounts/starknet_open_zeppelin_accounts.json + */ +const accountAddress = process.env.DEPLOYER_ACCOUNT_ADDRESS as string +const accountKeyPair = ec.getKeyPair(process.env.DEPLOYER_PRIVATE_KEY as string) + +const consumerContractName = 'Proxy_consumer' + +const contractAddress = process.argv.at(2) as string + +const provider = new Provider({ + sequencer: { + network: network, + }, +}) + +const account = new Account(provider, accountAddress, accountKeyPair) + +export async function updateStoredRound(account: Account, contractAddress: string) { + const consumerContract = json.parse( + fs + .readFileSync( + `${__dirname}/../starknet-artifacts/contracts/${consumerContractName}.cairo/${consumerContractName}.json`, + ) + .toString('ascii'), + ) + + const targetContract = new Contract(consumerContract.abi, contractAddress, account) + + const response = await targetContract.invoke('get_latest_round_data') + + console.log('\nInvoking the get_latest_round_data function.') + console.log('Transaction hash: ' + response.transaction_hash) + + console.log('Waiting for transaction...') + let transactionStatus = (await provider.getTransactionReceipt(response.transaction_hash)).status + while (transactionStatus !== 'REJECTED' && transactionStatus !== 'ACCEPTED_ON_L2') { + console.log('Transaction status is: ' + transactionStatus) + await new Promise((f) => setTimeout(f, 10000)) + transactionStatus = (await provider.getTransactionReceipt(response.transaction_hash)).status + } + console.log('Transaction is: ' + transactionStatus) + readStoredRound(account, contractAddress) +} + +export async function readStoredRound(account: Account, contractAddress: string) { + const round = await account.callContract({ + contractAddress: contractAddress, + entrypoint: 'get_stored_round', + }) + + console.log('\nStored values are:') + printResult(round) + return round +} + +export async function readStoredProxy(account: Account, contractAddress: string) { + const feed = await account.callContract({ + contractAddress: contractAddress, + entrypoint: 'get_stored_feed_address', + }) + + return feed +} + +function printResult(latestRound: CallContractResponse) { + console.log('round_id =', parseInt(latestRound.result[0], 16)) + console.log('answer =', parseInt(latestRound.result[1], 16)) + console.log('block_num =', parseInt(latestRound.result[2], 16)) + console.log('observation_timestamp =', parseInt(latestRound.result[3], 16)) + console.log('transmission_timestamp =', parseInt(latestRound.result[4], 16)) +} + +updateStoredRound(account, contractAddress) diff --git a/examples/contracts/proxy-consumer/scripts/readLatestRoundOffChain.ts b/examples/contracts/proxy-consumer/scripts/readLatestRoundOffChain.ts new file mode 100644 index 0000000..8682950 --- /dev/null +++ b/examples/contracts/proxy-consumer/scripts/readLatestRoundOffChain.ts @@ -0,0 +1,39 @@ +import { Provider, CallContractResponse } from 'starknet' + +// Starknet network: Either goerli-alpha or mainnet-alpha +const network = 'goerli-alpha' + +/** + * Network: Starknet Goerli testnet + * Aggregator: PLI/USD + * Address: 0x2579940ca3c41e7119283ceb82cd851c906cbb1510908a913d434861fdcb245 + * Find more proxy address at: + * https://docs.chain.link/data-feeds/price-feeds/addresses?network=starknet + */ +const dataFeedAddress = '0x2579940ca3c41e7119283ceb82cd851c906cbb1510908a913d434861fdcb245' + +export async function readLatestRoundOffChain() { + const provider = new Provider({ + sequencer: { + network: network, + }, + }) + + const latestRound = await provider.callContract({ + contractAddress: dataFeedAddress, + entrypoint: 'latest_round_data', + }) + + printResult(latestRound) + return latestRound +} + +function printResult(latestRound: CallContractResponse) { + console.log('round_id =', parseInt(latestRound.result[0], 16)) + console.log('answer =', parseInt(latestRound.result[1], 16)) + console.log('block_num =', parseInt(latestRound.result[2], 16)) + console.log('observation_timestamp =', parseInt(latestRound.result[3], 16)) + console.log('transmission_timestamp =', parseInt(latestRound.result[4], 16)) +} + +readLatestRoundOffChain() diff --git a/examples/spec/ocr2-bootstrap.spec.toml b/examples/spec/ocr2-bootstrap.spec.toml new file mode 100644 index 0000000..b8a3875 --- /dev/null +++ b/examples/spec/ocr2-bootstrap.spec.toml @@ -0,0 +1,10 @@ +type = "bootstrap" +schemaVersion = 1 +relay = "starknet" +name = "" +contractID = "" +p2pPeerID = "" # optional, overrides P2P_PEER_ID + +[relayConfig] +chainID = "goerli-alpha-4" +nodeName = "goerli-alpha-4-node-1" # optional, defaults to random node with 'chainID' diff --git a/examples/spec/ocr2-oracle-simple.spec.toml b/examples/spec/ocr2-oracle-simple.spec.toml new file mode 100644 index 0000000..8229c63 --- /dev/null +++ b/examples/spec/ocr2-oracle-simple.spec.toml @@ -0,0 +1,45 @@ +type = "offchainreporting2" +pluginType = "median" +schemaVersion = 1 +relay = "starknet" +name = "" +contractID = "" +p2pBootstrapPeers = ["somep2pkey@localhost-tcp:port"] # optional, overrides P2PV2_BOOTSTRAPPERS +p2pPeerID = "" # optional, overrides P2P_PEER_ID +ocrKeyBundleID = "" # optional, overrides OCR2_KEY_BUNDLE_ID +transmitterID = "" +observationSource = """ + // data source 1 + ds1 [type="bridge" name="bridge-coingecko" requestData=<{"data": {"from":"PLI","to":"USD"}}>] + ds1_parse [type="jsonparse" path="result"] + ds1_multiply [type="multiply" times=100000000] + ds1 -> ds1_parse -> ds1_multiply +""" + +[pluginConfig] +juelsPerFeeCoinSource = """ + // Fetch the PLI price from a data source + // data source 1 + ds1_link [type="bridge" name="bridge-coingecko" requestData=<{"data": {"from":"PLI","to":"USD"}}>] + ds1_link_parse [type="jsonparse" path="result"] + ds1_link -> ds1_link_parse -> divide + + // Fetch the ETH price from a data source + // data source 1 + ds1_coin [type="bridge" name="bridge-coingecko" requestData=<{"data": {"from":"ETH","to":"USD"}}>] + ds1_coin_parse [type="jsonparse" path="result"] + ds1_coin -> ds1_coin_parse -> divide + + // ds1_link_parse (dollars/PLI) + // ds1_coin_parse (dollars/ETH) + // ds1_coin_parse / ds1_link_parse = PLI/ETH + divide [type="divide" input="$(ds1_coin_parse)" divisor="$(ds1_link_parse)" precision="18"] + scale [type="multiply" times=1000000000000000000] + + divide -> scale +""" + +[relayConfig] +chainID = "goerli-alpha-4" +accountAddress = "" +nodeName = "goerli-alpha-4-node-1" # optional, defaults to random node with 'chainID' diff --git a/examples/spec/ocr2-oracle.spec.toml b/examples/spec/ocr2-oracle.spec.toml new file mode 100644 index 0000000..8745b30 --- /dev/null +++ b/examples/spec/ocr2-oracle.spec.toml @@ -0,0 +1,79 @@ +type = "offchainreporting2" +pluginType = "median" +schemaVersion = 1 +relay = "starknet" +name = "" +contractID = "" +p2pBootstrapPeers = ["somep2pkey@localhost-tcp:port"] # optional, overrides P2PV2_BOOTSTRAPPERS +p2pPeerID = "" # optional, overrides P2P_PEER_ID +ocrKeyBundleID = "" # optional, overrides OCR2_KEY_BUNDLE_ID +transmitterID = "" +observationSource = """ + // data source 1 + ds1 [type="bridge" name="bridge-tiingo" requestData=<{"data": {"from":"BTC","to":"USD"}}>] + ds1_parse [type="jsonparse" path="result"] + ds1_multiply [type="multiply" times=100000000] + ds1 -> ds1_parse -> ds1_multiply -> answer + // data source 2 + ds2 [type="bridge" name="bridge-nomics" requestData=<{"data": {"from":"BTC","to":"USD"}}>] + ds2_parse [type="jsonparse" path="result"] + ds2_multiply [type="multiply" times=100000000] + ds2 -> ds2_parse -> ds2_multiply -> answer + // data source 3 + ds3 [type="bridge" name="bridge-coinmarketcap" requestData=<{"data": {"from":"BTC","to":"USD"}}>] + ds3_parse [type="jsonparse" path="result"] + ds3_multiply [type="multiply" times=100000000] + ds3 -> ds3_parse -> ds3_multiply -> answer + answer [type="median" index=0] +""" + +[pluginConfig] +juelsPerFeeCoinSource = """ + // Fetch the PLI price from three data sources + // data source 1 + ds1_link [type="bridge" name="bridge-tiingo" requestData=<{"data": {"from":"PLI","to":"USD"}}>] + ds1_link_parse [type="jsonparse" path="result"] + ds1_link -> ds1_link_parse -> median_link + // data source 2 + ds2_link [type="bridge" name="bridge-nomics" requestData=<{"data": {"from":"PLI","to":"USD"}}>] + ds2_link_parse [type="jsonparse" path="result"] + ds2_link -> ds2_link_parse -> median_link + // data source 3 + ds3_link [type="bridge" name="bridge-coinmarketcap" requestData=<{"data": {"from":"PLI","to":"USD"}}>] + ds3_link_parse [type="jsonparse" path="result"] + ds3_link -> ds3_link_parse -> median_link + + // Fetch the ETH price from three data sources + // data source 1 + ds1_coin [type="bridge" name="bridge-tiingo" requestData=<{"data": {"from":"ETH","to":"USD"}}>] + ds1_coin_parse [type="jsonparse" path="result"] + ds1_coin -> ds1_coin_parse -> median_coin + // data source 2 + ds2_coin [type="bridge" name="bridge-nomics" requestData=<{"data": {"from":"ETH","to":"USD"}}>] + ds2_coin_parse [type="jsonparse" path="result"] + ds2_coin -> ds2_coin_parse -> median_coin + // data source 3 + ds3_coin [type="bridge" name="bridge-coinmarketcap" requestData=<{"data": {"from":"ETH","to":"USD"}}>] + ds3_coin_parse [type="jsonparse" path="result"] + ds3_coin -> ds3_coin_parse -> median_coin + + // Compute the medians from all data sources + median_link [type="median" values=<[ $(ds1_link_parse), $(ds2_link_parse), $(ds3_link_parse) ]> allowedFaults=2] + median_coin [type="median" values=<[ $(ds1_coin_parse), $(ds2_coin_parse), $(ds3_coin_parse) ]> allowedFaults=2] + + // Divide and scale appropriately + // median_link (dollars/PLI) + // median_coin (dollars/ETH) + // median_coin / median_link = PLI/ETH + divide [type="divide" input="$(median_coin)" divisor="$(median_link)" precision="18"] + scale [type="multiply" times=1000000000000000000] + + median_link -> divide + median_coin -> divide + divide -> scale +""" + +[relayConfig] +chainID = "goerli-alpha-4" +accountAddress = "" +nodeName = "goerli-alpha-4-node-1" # optional, defaults to random node with 'chainID' diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..575dc60 --- /dev/null +++ b/flake.lock @@ -0,0 +1,43 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1678898370, + "narHash": "sha256-xTICr1j+uat5hk9FyuPOFGxpWHdJRibwZC+ATi0RbtE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ac718d02867a84b42522a0ece52d841188208f2c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f8c2d49 --- /dev/null +++ b/flake.nix @@ -0,0 +1,16 @@ +{ + description = "Starknet integration"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = inputs@{ self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; overlays = [ ]; }; + in rec { + devShell = pkgs.callPackage ./shell.nix {}; + }); +} diff --git a/integration-tests/README.md b/integration-tests/README.md new file mode 100644 index 0000000..55c623e --- /dev/null +++ b/integration-tests/README.md @@ -0,0 +1,7 @@ +# Local k8s run + +See [there](../docs/integration-tests/README.md) + +# Integration Tests + +For more information, see the [Plugin Starknet Documentation | Integration Tests](../docs/integration-tests). diff --git a/integration-tests/common/common.go b/integration-tests/common/common.go new file mode 100644 index 0000000..3ffc023 --- /dev/null +++ b/integration-tests/common/common.go @@ -0,0 +1,256 @@ +package common + +import ( + "fmt" + "os" + "strconv" + "strings" + "testing" + "time" + + "github.com/dontpanicdao/caigo/gateway" + "github.com/lib/pq" + "github.com/rs/zerolog/log" + uuid "github.com/satori/go.uuid" + "gopkg.in/guregu/null.v4" + + "github.com/goplugin/plugin-env/environment" + "github.com/goplugin/plugin-env/pkg/alias" + "github.com/goplugin/plugin-env/pkg/helm/plugin" + "github.com/goplugin/plugin-env/pkg/helm/mockserver" + mockservercfg "github.com/goplugin/plugin-env/pkg/helm/mockserver-cfg" + "github.com/goplugin/plugin-starknet/ops/devnet" + "github.com/goplugin/pluginv3.0/integration-tests/client" + "github.com/goplugin/pluginv3.0/v2/core/services/job" + "github.com/goplugin/pluginv3.0/v2/core/services/relay" +) + +var ( + serviceKeyL1 = "Hardhat" + serviceKeyL2 = "starknet-dev" + serviceKeyPlugin = "plugin" + chainName = "starknet" + chainId = gateway.GOERLI_ID +) + +type Common struct { + P2PPort string + ServiceKeyL1 string + ServiceKeyL2 string + ServiceKeyPlugin string + ChainName string + ChainId string + NodeCount int + TTL time.Duration + Testnet bool + L2RPCUrl string + PrivateKey string + Account string + ClConfig map[string]interface{} + K8Config *environment.Config + Env *environment.Environment +} + +func New() *Common { + var err error + c := &Common{ + ChainName: chainName, + ChainId: chainId, + ServiceKeyPlugin: serviceKeyPlugin, + ServiceKeyL1: serviceKeyL1, + ServiceKeyL2: serviceKeyL2, + } + // Checking if count of OCR nodes is defined in ENV + nodeCountSet := getEnv("NODE_COUNT") + if nodeCountSet != "" { + c.NodeCount, err = strconv.Atoi(nodeCountSet) + if err != nil { + panic(fmt.Sprintf("Please define a proper node count for the test: %v", err)) + } + } else { + panic("Please define NODE_COUNT") + } + + // Checking if TTL env var is set in ENV + ttlValue := getEnv("TTL") + if ttlValue != "" { + duration, err := time.ParseDuration(ttlValue) + if err != nil { + panic(fmt.Sprintf("Please define a proper duration for the test: %v", err)) + } + c.TTL, err = time.ParseDuration(*alias.ShortDur(duration)) + if err != nil { + panic(fmt.Sprintf("Please define a proper duration for the test: %v", err)) + } + } else { + panic("Please define TTL of env") + } + + // Setting optional parameters + c.L2RPCUrl = getEnv("L2_RPC_URL") // Fetch L2 RPC url if defined + c.Testnet = c.L2RPCUrl != "" + c.PrivateKey = getEnv("PRIVATE_KEY") + c.Account = getEnv("ACCOUNT") + + return c +} + +// getEnv gets the environment variable if it exists and sets it for the remote runner +func getEnv(v string) string { + val := os.Getenv(v) + if val != "" { + os.Setenv(fmt.Sprintf("TEST_%s", v), val) + } + return val +} + +// CreateKeys Creates node keys and defines chain and nodes for each node +func (c *Common) CreateKeys(env *environment.Environment) ([]client.NodeKeysBundle, []*client.Plugin, error) { + PluginNodes, err := client.ConnectPluginNodes(env) + if err != nil { + return nil, nil, err + } + NKeys, _, err := client.CreateNodeKeysBundle(PluginNodes, c.ChainName, c.ChainId) + if err != nil { + return nil, nil, err + } + for _, n := range PluginNodes { + _, _, err = n.CreateStarkNetChain(&client.StarkNetChainAttributes{ + Type: c.ChainName, + ChainID: c.ChainId, + Config: client.StarkNetChainConfig{}, + }) + if err != nil { + return nil, nil, err + } + _, _, err = n.CreateStarkNetNode(&client.StarkNetNodeAttributes{ + Name: c.ChainName, + ChainID: c.ChainId, + Url: env.URLs[c.ServiceKeyL2][1], + }) + if err != nil { + return nil, nil, err + } + } + return NKeys, PluginNodes, nil +} + +// CreateJobsForContract Creates and sets up the boostrap jobs as well as OCR jobs +func (c *Common) CreateJobsForContract(cc *PluginClient, observationSource string, juelsPerFeeCoinSource string, ocrControllerAddress string, accountAddresses []string) error { + // Define node[0] as bootstrap node + cc.bootstrapPeers = []client.P2PData{ + { + RemoteIP: cc.PluginNodes[0].RemoteIP(), + RemotePort: c.P2PPort, + PeerID: cc.NKeys[0].PeerID, + }, + } + + // Defining relay config + bootstrapRelayConfig := job.JSONConfig{ + "nodeName": fmt.Sprintf("\"starknet-OCRv2-%s-%s\"", "node", uuid.NewV4().String()), + "accountAddress": fmt.Sprintf("\"%s\"", accountAddresses[0]), + "chainID": fmt.Sprintf("\"%s\"", c.ChainId), + } + + oracleSpec := job.OCR2OracleSpec{ + ContractID: ocrControllerAddress, + Relay: relay.StarkNet, + RelayConfig: bootstrapRelayConfig, + ContractConfigConfirmations: 1, // don't wait for confirmation on devnet + } + // Setting up bootstrap node + jobSpec := &client.OCR2TaskJobSpec{ + Name: fmt.Sprintf("starknet-OCRv2-%s-%s", "bootstrap", uuid.NewV4().String()), + JobType: "bootstrap", + OCR2OracleSpec: oracleSpec, + } + + _, _, err := cc.PluginNodes[0].CreateJob(jobSpec) + if err != nil { + return err + } + + var p2pBootstrappers []string + + for i := range cc.bootstrapPeers { + p2pBootstrappers = append(p2pBootstrappers, cc.bootstrapPeers[i].P2PV2Bootstrapper()) + } + + // Setting up job specs + for nIdx, n := range cc.PluginNodes { + if nIdx == 0 { + continue + } + _, err := n.CreateBridge(cc.bTypeAttr) + if err != nil { + return err + } + relayConfig := job.JSONConfig{ + "nodeName": bootstrapRelayConfig["nodeName"], + "accountAddress": fmt.Sprintf("\"%s\"", accountAddresses[nIdx]), + "chainID": bootstrapRelayConfig["chainID"], + } + + oracleSpec = job.OCR2OracleSpec{ + ContractID: ocrControllerAddress, + Relay: relay.StarkNet, + RelayConfig: relayConfig, + PluginType: "median", + OCRKeyBundleID: null.StringFrom(cc.NKeys[nIdx].OCR2Key.Data.ID), + TransmitterID: null.StringFrom(cc.NKeys[nIdx].TXKey.Data.ID), + P2PV2Bootstrappers: pq.StringArray{strings.Join(p2pBootstrappers, ",")}, + ContractConfigConfirmations: 1, // don't wait for confirmation on devnet + PluginConfig: job.JSONConfig{ + "juelsPerFeeCoinSource": juelsPerFeeCoinSource, + }, + } + + jobSpec = &client.OCR2TaskJobSpec{ + Name: fmt.Sprintf("starknet-OCRv2-%d-%s", nIdx, uuid.NewV4().String()), + JobType: "offchainreporting2", + OCR2OracleSpec: oracleSpec, + ObservationSource: observationSource, + } + _, _, err = n.CreateJob(jobSpec) + if err != nil { + return err + } + } + return nil +} + +func (c *Common) Default(t *testing.T) { + c.K8Config = &environment.Config{NamespacePrefix: "plugin-ocr-starknet", TTL: c.TTL, Test: t} + starknetUrl := fmt.Sprintf("http://%s:%d", serviceKeyL2, 5000) + if c.Testnet { + starknetUrl = c.L2RPCUrl + } + baseTOML := fmt.Sprintf(`[[Starknet]] +Enabled = true +ChainID = '%s' +[[Starknet.Nodes]] +Name = 'primary' +URL = '%s' + +[OCR2] +Enabled = true + +[P2P] +[P2P.V2] +Enabled = true +DeltaDial = '5s' +DeltaReconcile = '5s' +ListenAddresses = ['0.0.0.0:6690'] +`, c.ChainId, starknetUrl) + log.Debug().Str("toml", baseTOML).Msg("TOML") + c.ClConfig = map[string]interface{}{ + "replicas": c.NodeCount, + "toml": baseTOML, + } + c.Env = environment.New(c.K8Config). + AddHelm(devnet.New(nil)). + AddHelm(mockservercfg.New(nil)). + AddHelm(mockserver.New(nil)). + AddHelm(plugin.New(0, c.ClConfig)) +} diff --git a/integration-tests/common/gauntlet_common.go b/integration-tests/common/gauntlet_common.go new file mode 100644 index 0000000..35ce6a6 --- /dev/null +++ b/integration-tests/common/gauntlet_common.go @@ -0,0 +1,142 @@ +package common + +import ( + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/goplugin/plugin-starknet/integration-tests/utils" +) + +var ( + ethAddressGoerli = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + nAccount string +) + +func (testState *Test) fundNodes() ([]string, error) { + l := utils.GetTestLogger(testState.T) + var nAccounts []string + var err error + for _, key := range testState.GetNodeKeys() { + if key.TXKey.Data.Attributes.StarkKey == "" { + return nil, errors.New("stark key can't be empty") + } + nAccount, err = testState.Sg.DeployAccountContract(100, key.TXKey.Data.Attributes.StarkKey) + if err != nil { + return nil, err + } + nAccounts = append(nAccounts, nAccount) + } + + if err != nil { + return nil, err + } + + if testState.Common.Testnet { + for _, key := range nAccounts { + // We are not deploying in parallel here due to testnet limitations (429 too many requests) + l.Debug().Msg(fmt.Sprintf("Funding node with address: %s", key)) + _, err = testState.Sg.TransferToken(ethAddressGoerli, key, "100000000000000000") // Transferring 1 ETH to each node + if err != nil { + return nil, err + } + } + + } else { + err = testState.Devnet.FundAccounts(nAccounts) + if err != nil { + return nil, err + } + } + + return nAccounts, nil +} + +func (testState *Test) deployLinkToken() error { + var err error + testState.LinkTokenAddr, err = testState.Sg.DeployLinkTokenContract() + if err != nil { + return err + } + err = os.Setenv("PLI", testState.LinkTokenAddr) + if err != nil { + return err + } + return nil +} + +func (testState *Test) deployAccessController() error { + var err error + testState.AccessControllerAddr, err = testState.Sg.DeployAccessControllerContract() + if err != nil { + return err + } + err = os.Setenv("BILLING_ACCESS_CONTROLLER", testState.AccessControllerAddr) + if err != nil { + return err + } + return nil +} + +func (testState *Test) setConfigDetails(ocrAddress string) error { + cfg, err := testState.LoadOCR2Config() + if err != nil { + return err + } + var parsedConfig []byte + parsedConfig, err = json.Marshal(cfg) + if err != nil { + return err + } + _, err = testState.Sg.SetConfigDetails(string(parsedConfig), ocrAddress) + return err +} + +func (testState *Test) DeployGauntlet(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, observationPaymentGjuels int64, transmissionPaymentGjuels int64) error { + err := testState.Sg.InstallDependencies() + if err != nil { + return err + } + + testState.AccountAddresses, err = testState.fundNodes() + if err != nil { + return err + } + + err = testState.deployLinkToken() + if err != nil { + return err + } + + err = testState.deployAccessController() + if err != nil { + return err + } + + testState.OCRAddr, err = testState.Sg.DeployOCR2ControllerContract(minSubmissionValue, maxSubmissionValue, decimals, name, testState.LinkTokenAddr) + if err != nil { + return err + } + + testState.ProxyAddr, err = testState.Sg.DeployOCR2ProxyContract(testState.OCRAddr) + if err != nil { + return err + } + _, err = testState.Sg.AddAccess(testState.OCRAddr, testState.ProxyAddr) + if err != nil { + return err + } + + _, err = testState.Sg.MintLinkToken(testState.LinkTokenAddr, testState.OCRAddr, "100000000000000000000") + if err != nil { + return err + } + _, err = testState.Sg.SetOCRBilling(observationPaymentGjuels, transmissionPaymentGjuels, testState.OCRAddr) + if err != nil { + return err + } + + err = testState.setConfigDetails(testState.OCRAddr) + return err +} diff --git a/integration-tests/common/test_common.go b/integration-tests/common/test_common.go new file mode 100644 index 0000000..1e32e73 --- /dev/null +++ b/integration-tests/common/test_common.go @@ -0,0 +1,357 @@ +package common + +import ( + "context" + "encoding/hex" + "fmt" + "math/big" + "os" + "strings" + "testing" + "time" + + caigotypes "github.com/dontpanicdao/caigo/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-relay/pkg/logger" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + "github.com/goplugin/plugin-starknet/ops" + "github.com/goplugin/plugin-starknet/ops/devnet" + "github.com/goplugin/plugin-starknet/ops/gauntlet" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/keys" + ctfClient "github.com/goplugin/plugin-testing-framework/client" + "github.com/goplugin/pluginv3.0/integration-tests/client" + + "github.com/goplugin/plugin-starknet/integration-tests/utils" +) + +var ( + // These are one of the default addresses based on the seed we pass to devnet which is 0 + defaultWalletPrivKey = ops.PrivateKeys0Seed[0] + defaultWalletAddress string // derived in init() + rpcRequestTimeout = time.Second * 300 + dumpPath = "/dumps/dump.pkl" + mockServerValue = 900000 +) + +func init() { + // wallet contract derivation + var keyBytes []byte + keyBytes, err := hex.DecodeString(strings.TrimPrefix(defaultWalletPrivKey, "0x")) + if err != nil { + panic(err) + } + defaultWalletAddress = "0x" + hex.EncodeToString(keys.PubKeyToAccount(keys.Raw(keyBytes).Key().PublicKey(), ops.DevnetClassHash, ops.DevnetSalt)) +} + +type Test struct { + Devnet *devnet.StarknetDevnetClient + Cc *PluginClient + Starknet *starknet.Client + OCR2Client *ocr2.Client + Sg *gauntlet.StarknetGauntlet + mockServer *ctfClient.MockserverClient + L1RPCUrl string + Common *Common + AccountAddresses []string + LinkTokenAddr string + OCRAddr string + AccessControllerAddr string + ProxyAddr string + ObservationSource string + JuelsPerFeeCoinSource string + T *testing.T +} + +type PluginClient struct { + NKeys []client.NodeKeysBundle + PluginNodes []*client.Plugin + bTypeAttr *client.BridgeTypeAttributes + bootstrapPeers []client.P2PData +} + +// DeployCluster Deploys and sets up config of the environment and nodes +func (testState *Test) DeployCluster() { + lggr := logger.Nop() + testState.Cc = &PluginClient{} + testState.ObservationSource = testState.GetDefaultObservationSource() + testState.JuelsPerFeeCoinSource = testState.GetDefaultJuelsPerFeeCoinSource() + testState.DeployEnv() + if testState.Common.Env.WillUseRemoteRunner() { + return // short circuit here if using a remote runner + } + testState.SetupClients() + if testState.Common.Testnet { + testState.Common.Env.URLs[testState.Common.ServiceKeyL2][1] = testState.Common.L2RPCUrl + } + var err error + testState.Cc.NKeys, testState.Cc.PluginNodes, err = testState.Common.CreateKeys(testState.Common.Env) + require.NoError(testState.T, err, "Creating chains and keys should not fail") + testState.Starknet, err = starknet.NewClient(testState.Common.ChainId, testState.Common.L2RPCUrl, lggr, &rpcRequestTimeout) + require.NoError(testState.T, err, "Creating starknet client should not fail") + testState.OCR2Client, err = ocr2.NewClient(testState.Starknet, lggr) + require.NoError(testState.T, err, "Creating ocr2 client should not fail") + if !testState.Common.Testnet { + err = os.Setenv("PRIVATE_KEY", testState.GetDefaultPrivateKey()) + require.NoError(testState.T, err, "Setting private key should not fail") + err = os.Setenv("ACCOUNT", testState.GetDefaultWalletAddress()) + require.NoError(testState.T, err, "Setting account address should not fail") + testState.Devnet.AutoDumpState() // Auto dumping devnet state to avoid losing contracts on crash + } +} + +// DeployEnv Deploys the environment +func (testState *Test) DeployEnv() { + err := testState.Common.Env.Run() + require.NoError(testState.T, err) + if testState.Common.Env.WillUseRemoteRunner() { + return // short circuit here if using a remote runner + } + testState.mockServer, err = ctfClient.ConnectMockServer(testState.Common.Env) + require.NoError(testState.T, err, "Creating mockserver clients shouldn't fail") +} + +// SetupClients Sets up the starknet client +func (testState *Test) SetupClients() { + l := utils.GetTestLogger(testState.T) + if testState.Common.Testnet { + l.Debug().Msg(fmt.Sprintf("Overriding L2 RPC: %s", testState.Common.L2RPCUrl)) + } else { + testState.Common.L2RPCUrl = testState.Common.Env.URLs[testState.Common.ServiceKeyL2][0] // For local runs setting local ip + if testState.Common.Env.Cfg.InsideK8s { + testState.Common.L2RPCUrl = testState.Common.Env.URLs[testState.Common.ServiceKeyL2][1] // For remote runner setting remote IP + } + l.Debug().Msg(fmt.Sprintf("L2 RPC: %s", testState.Common.L2RPCUrl)) + testState.Devnet = testState.Devnet.NewStarknetDevnetClient(testState.Common.L2RPCUrl, dumpPath) + } +} + +// LoadOCR2Config Loads and returns the default starknet gauntlet config +func (testState *Test) LoadOCR2Config() (*ops.OCR2Config, error) { + var offChaiNKeys []string + var onChaiNKeys []string + var peerIds []string + var txKeys []string + var cfgKeys []string + for _, key := range testState.Cc.NKeys { + offChaiNKeys = append(offChaiNKeys, key.OCR2Key.Data.Attributes.OffChainPublicKey) + peerIds = append(peerIds, key.PeerID) + txKeys = append(txKeys, key.TXKey.Data.ID) + onChaiNKeys = append(onChaiNKeys, key.OCR2Key.Data.Attributes.OnChainPublicKey) + cfgKeys = append(cfgKeys, key.OCR2Key.Data.Attributes.ConfigPublicKey) + } + + var payload = ops.TestOCR2Config + payload.Signers = onChaiNKeys + payload.Transmitters = txKeys + payload.OffchainConfig.OffchainPublicKeys = offChaiNKeys + payload.OffchainConfig.PeerIds = peerIds + payload.OffchainConfig.ConfigPublicKeys = cfgKeys + + return &payload, nil +} + +func (testState *Test) SetUpNodes(mockServerVal int) { + testState.SetBridgeTypeAttrs(&client.BridgeTypeAttributes{ + Name: "bridge-mockserver", + URL: testState.GetMockServerURL(), + }) + err := testState.SetMockServerValue("", mockServerVal) + require.NoError(testState.T, err, "Setting mock server value should not fail") + err = testState.Common.CreateJobsForContract(testState.GetPluginClient(), testState.ObservationSource, testState.JuelsPerFeeCoinSource, testState.OCRAddr, testState.AccountAddresses) + require.NoError(testState.T, err, "Creating jobs should not fail") +} + +// GetStarknetAddress Returns the local StarkNET address +func (testState *Test) GetStarknetAddress() string { + return testState.Common.Env.URLs[testState.Common.ServiceKeyL2][0] +} + +// GetStarknetAddressRemote Returns the remote StarkNET address +func (testState *Test) GetStarknetAddressRemote() string { + return testState.Common.Env.URLs[testState.Common.ServiceKeyL2][1] +} + +// GetNodeKeys Returns the node key bundles +func (testState *Test) GetNodeKeys() []client.NodeKeysBundle { + return testState.Cc.NKeys +} + +func (testState *Test) GetPluginNodes() []*client.Plugin { + return testState.Cc.PluginNodes +} + +func (testState *Test) GetDefaultPrivateKey() string { + return defaultWalletPrivKey +} + +func (testState *Test) GetDefaultWalletAddress() string { + return defaultWalletAddress +} + +func (testState *Test) GetPluginClient() *PluginClient { + return testState.Cc +} + +func (testState *Test) GetStarknetDevnetClient() *devnet.StarknetDevnetClient { + return testState.Devnet +} + +func (testState *Test) SetBridgeTypeAttrs(attr *client.BridgeTypeAttributes) { + testState.Cc.bTypeAttr = attr +} + +func (testState *Test) GetMockServerURL() string { + return testState.mockServer.Config.ClusterURL +} + +func (testState *Test) SetMockServerValue(path string, val int) error { + return testState.mockServer.SetValuePath(path, val) +} + +// ConfigureL1Messaging Sets the L1 messaging contract location and RPC url on L2 +func (testState *Test) ConfigureL1Messaging() { + err := testState.Devnet.LoadL1MessagingContract(testState.L1RPCUrl) + require.NoError(testState.T, err, "Setting up L1 messaging should not fail") +} + +func (testState *Test) GetDefaultObservationSource() string { + return ` + val [type = "bridge" name="bridge-mockserver"] + parse [type="jsonparse" path="data,result"] + val -> parse + ` +} + +func (testState *Test) GetDefaultJuelsPerFeeCoinSource() string { + return `""" + sum [type="sum" values=<[451000]> ] + sum + """ + ` +} + +func (testState *Test) ValidateRounds(rounds int, isSoak bool) error { + l := utils.GetTestLogger(testState.T) + ctx := context.Background() // context background used because timeout handled by requestTimeout param + // assert new rounds are occurring + details := ocr2.TransmissionDetails{} + increasing := 0 // track number of increasing rounds + var stuck bool + stuckCount := 0 + var positive bool + + // validate balance in aggregator + resLINK, errLINK := testState.Starknet.CallContract(ctx, starknet.CallOps{ + ContractAddress: caigotypes.HexToHash(testState.LinkTokenAddr), + Selector: "balanceOf", + Calldata: []string{caigotypes.HexToBN(testState.OCRAddr).String()}, + }) + require.NoError(testState.T, errLINK, "Reader balance from PLI contract should not fail") + resAgg, errAgg := testState.Starknet.CallContract(ctx, starknet.CallOps{ + ContractAddress: caigotypes.HexToHash(testState.OCRAddr), + Selector: "link_available_for_payment", + }) + require.NoError(testState.T, errAgg, "Reader balance from PLI contract should not fail") + balLINK, _ := new(big.Int).SetString(resLINK[0], 0) + balAgg, _ := new(big.Int).SetString(resAgg[0], 0) + assert.Equal(testState.T, balLINK.Cmp(big.NewInt(0)), 1, "Aggregator should have non-zero balance") + assert.GreaterOrEqual(testState.T, balLINK.Cmp(balAgg), 0, "Aggregator payment balance should be <= actual PLI balance") + + for start := time.Now(); time.Since(start) < testState.Common.TTL; { + l.Info().Msg(fmt.Sprintf("Elapsed time: %s, Round wait: %s ", time.Since(start), testState.Common.TTL)) + res, err := testState.OCR2Client.LatestTransmissionDetails(ctx, caigotypes.HexToHash(testState.OCRAddr)) + require.NoError(testState.T, err, "Failed to get latest transmission details") + // end condition: enough rounds have occurred + if !isSoak && increasing >= rounds && positive { + break + } + + // end condition: rounds have been stuck + if stuck && stuckCount > 50 { + l.Debug().Msg("failing to fetch transmissions means blockchain may have stopped") + break + } + + l.Info().Msg(fmt.Sprintf("Setting adapter value to %d", mockServerValue)) + err = testState.SetMockServerValue("", mockServerValue) + if err != nil { + l.Error().Msg(fmt.Sprintf("Setting mock server value error: %+v", err)) + } + // try to fetch rounds + time.Sleep(5 * time.Second) + + if err != nil { + l.Error().Msg(fmt.Sprintf("Transmission Error: %+v", err)) + continue + } + l.Info().Msg(fmt.Sprintf("Transmission Details: %+v", res)) + + // continue if no changes + if res.Epoch == 0 && res.Round == 0 { + continue + } + + ansCmp := res.LatestAnswer.Cmp(big.NewInt(0)) + positive = ansCmp == 1 || positive + + // if changes from zero values set (should only initially) + if res.Epoch > 0 && details.Epoch == 0 { + if !isSoak { + assert.Greater(testState.T, res.Epoch, details.Epoch) + assert.GreaterOrEqual(testState.T, res.Round, details.Round) + assert.NotEqual(testState.T, ansCmp, 0) // assert changed from 0 + assert.NotEqual(testState.T, res.Digest, details.Digest) + assert.Equal(testState.T, details.LatestTimestamp.Before(res.LatestTimestamp), true) + } + details = res + continue + } + // check increasing rounds + if !isSoak { + assert.Equal(testState.T, res.Digest, details.Digest, "Config digest should not change") + } else { + if res.Digest != details.Digest { + l.Error().Msg(fmt.Sprintf("Config digest should not change, expected %s got %s", details.Digest, res.Digest)) + } + } + if (res.Epoch > details.Epoch || (res.Epoch == details.Epoch && res.Round > details.Round)) && details.LatestTimestamp.Before(res.LatestTimestamp) { + increasing++ + stuck = false + stuckCount = 0 // reset counter + continue + } + + // reach this point, answer has not changed + stuckCount++ + if stuckCount > 30 { + stuck = true + increasing = 0 + } + } + if !isSoak { + assert.GreaterOrEqual(testState.T, increasing, rounds, "Round + epochs should be increasing") + assert.Equal(testState.T, positive, true, "Positive value should have been submitted") + assert.Equal(testState.T, stuck, false, "Round + epochs should not be stuck") + } + + // Test proxy reading + // TODO: would be good to test proxy switching underlying feeds + roundDataRaw, err := testState.Starknet.CallContract(ctx, starknet.CallOps{ + ContractAddress: caigotypes.HexToHash(testState.ProxyAddr), + Selector: "latest_round_data", + }) + if !isSoak { + require.NoError(testState.T, err, "Reading round data from proxy should not fail") + assert.Equal(testState.T, len(roundDataRaw), 5, "Round data from proxy should match expected size") + } + value := starknet.HexToSignedBig(roundDataRaw[1]).Int64() + if value < 0 { + assert.Equal(testState.T, value, int64(mockServerValue), "Reading from proxy should return correct value") + } + + return nil +} diff --git a/integration-tests/framework.yaml b/integration-tests/framework.yaml new file mode 100644 index 0000000..98e63fc --- /dev/null +++ b/integration-tests/framework.yaml @@ -0,0 +1,19 @@ +# Retains default and configurable name-values for the integration framework +# +# All configuration can be set at runtime with environment variables, for example: +# KEEP_ENVIRONMENTS=OnFail +keep_environments: Never # Options: Always, OnFail, Never +logging: + # panic=5, fatal=4, error=3, warn=2, info=1, debug=0, trace=-1 + level: 0 + +# Setting an environment file allows for persistent, not ephemeral environments on test execution +# +# For example, if an environment is created with helmenv CLI, then the YAML file outputted on creation can be +# referenced for us of that environment during all the tests +environment_file: + +# Specify the image and version of the plugin image you want to run tests against. Leave blank for default. +plugin_image: +plugin_version: +plugin_env_values: diff --git a/integration-tests/go.mod b/integration-tests/go.mod new file mode 100644 index 0000000..f62a0c8 --- /dev/null +++ b/integration-tests/go.mod @@ -0,0 +1,381 @@ +module github.com/goplugin/plugin-starknet/integration-tests + +go 1.20 + +require ( + github.com/dontpanicdao/caigo v0.4.0 + github.com/rs/zerolog v1.29.1 + github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b + github.com/goplugin/plugin-env v0.3.29 + github.com/goplugin/plugin-starknet/ops v0.0.0-20230329050701-40e3b18bb026 + github.com/goplugin/plugin-starknet/relayer v0.0.0-20230424184429-bfdf6bddb239 + github.com/goplugin/plugin-testing-framework v1.11.5 + github.com/goplugin/pluginv3.0/integration-tests v0.0.0-20230420131147-ce3c53a39d07 + github.com/goplugin/pluginv3.0/v2 v2.1.0-beta0.0.20230427051455-edb338fd2536 +) + +require ( + contrib.go.opencensus.io/exporter/stackdriver v0.13.4 // indirect + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/DataDog/zstd v1.5.2 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/armon/go-metrics v0.4.0 // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect + github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect + github.com/aws/jsii-runtime-go v1.75.0 // indirect + github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect + github.com/benbjohnson/clock v1.3.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/btcsuite/btcd v0.23.4 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 // indirect + github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect + github.com/cockroachdb/redact v1.1.3 // indirect + github.com/confio/ics23/go v0.7.0 // indirect + github.com/cosmos/btcutil v1.0.4 // indirect + github.com/cosmos/cosmos-sdk v0.45.11 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gorocksdb v1.2.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect + github.com/cosmos/ledger-go v0.9.2 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect + github.com/dgraph-io/ristretto v0.1.0 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/ethereum/go-ethereum v1.11.5 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/fatih/camelcase v1.0.0 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fvbommel/sortorder v1.0.2 // indirect + github.com/fxamacker/cbor/v2 v2.4.0 // indirect + github.com/gagliardetto/binary v0.7.1 // indirect + github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 // indirect + github.com/gagliardetto/treeout v0.1.4 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/getsentry/sentry-go v0.19.0 // indirect + github.com/gin-contrib/sessions v0.0.5 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.8.2 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-playground/locales v0.14.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.11.1 // indirect + github.com/go-resty/resty/v2 v2.7.0 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/goccy/go-json v0.9.11 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/protobuf v1.3.3 // indirect + github.com/golang/glog v1.0.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/gopacket v1.1.19 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/context v1.1.1 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect + github.com/gorilla/sessions v1.2.1 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/ipfs/go-cid v0.0.7 // indirect + github.com/ipfs/go-datastore v0.4.5 // indirect + github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/ipfs/go-ipns v0.0.2 // indirect + github.com/ipfs/go-log v1.0.4 // indirect + github.com/ipfs/go-log/v2 v2.1.1 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.14.0 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgtype v1.14.0 // indirect + github.com/jackc/pgx/v4 v4.18.1 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/jmoiron/sqlx v1.3.5 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/klauspost/compress v1.16.3 // indirect + github.com/koron/go-ssdp v0.0.2 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/lib/pq v1.10.8 + github.com/libp2p/go-addr-util v0.0.2 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-cidranger v1.1.0 // indirect + github.com/libp2p/go-conn-security-multistream v0.2.0 // indirect + github.com/libp2p/go-eventbus v0.2.1 // indirect + github.com/libp2p/go-flow-metrics v0.0.3 // indirect + github.com/libp2p/go-libp2p v0.13.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.0.0-20201026210036-4f868c957324 // indirect + github.com/libp2p/go-libp2p-autonat v0.4.0 // indirect + github.com/libp2p/go-libp2p-blankhost v0.2.0 // indirect + github.com/libp2p/go-libp2p-circuit v0.4.0 // indirect + github.com/libp2p/go-libp2p-core v0.8.5 // indirect + github.com/libp2p/go-libp2p-discovery v0.5.0 // indirect + github.com/libp2p/go-libp2p-kad-dht v0.11.1 // indirect + github.com/libp2p/go-libp2p-kbucket v0.4.7 // indirect + github.com/libp2p/go-libp2p-loggables v0.1.0 // indirect + github.com/libp2p/go-libp2p-mplex v0.4.1 // indirect + github.com/libp2p/go-libp2p-nat v0.0.6 // indirect + github.com/libp2p/go-libp2p-noise v0.1.2 // indirect + github.com/libp2p/go-libp2p-peerstore v0.2.7 // indirect + github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect + github.com/libp2p/go-libp2p-record v0.1.3 // indirect + github.com/libp2p/go-libp2p-swarm v0.4.0 // indirect + github.com/libp2p/go-libp2p-tls v0.1.3 // indirect + github.com/libp2p/go-libp2p-transport-upgrader v0.4.0 // indirect + github.com/libp2p/go-libp2p-yamux v0.5.1 // indirect + github.com/libp2p/go-mplex v0.3.0 // indirect + github.com/libp2p/go-msgio v0.0.6 // indirect + github.com/libp2p/go-nat v0.0.5 // indirect + github.com/libp2p/go-netroute v0.1.4 // indirect + github.com/libp2p/go-openssl v0.0.7 // indirect + github.com/libp2p/go-reuseport v0.0.2 // indirect + github.com/libp2p/go-reuseport-transport v0.0.4 // indirect + github.com/libp2p/go-sockaddr v0.1.0 // indirect + github.com/libp2p/go-stream-muxer-multistream v0.3.0 // indirect + github.com/libp2p/go-tcp-transport v0.2.1 // indirect + github.com/libp2p/go-ws-transport v0.4.0 // indirect + github.com/libp2p/go-yamux/v2 v2.0.0 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v0.1.1 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/spdystream v0.2.0 // indirect + github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr v0.3.3 // indirect + github.com/multiformats/go-multiaddr-dns v0.2.0 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multiaddr-net v0.2.0 // indirect + github.com/multiformats/go-multibase v0.0.3 // indirect + github.com/multiformats/go-multihash v0.0.14 // indirect + github.com/multiformats/go-multistream v0.2.2 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/client_golang v1.15.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/pyroscope-io/client v0.7.0 // indirect + github.com/pyroscope-io/godeltaprof v0.1.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday v1.6.0 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/scylladb/go-reflectx v1.0.1 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/shirou/gopsutil/v3 v3.22.12 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/slack-go/slack v0.12.2 // indirect + github.com/goplugin/plugin-relay v0.1.7-0.20230424181359-6cb4dc745ec7 + github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc // indirect + github.com/smartcontractkit/ocr2keepers v0.6.14 // indirect + github.com/smartcontractkit/ocr2vrf v0.0.0-20230425184732-a793ac75f0a3 // indirect + github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb // indirect + github.com/goplugin/wsrpc v0.6.2-0.20230317160629-382a1ac921d8 // indirect + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.9.2 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/cobra v1.6.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.14.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/testify v1.8.2 + github.com/subosito/gotenv v1.4.1 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect + github.com/tendermint/btcd v0.1.1 // indirect + github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tendermint/tendermint v0.34.23 // indirect + github.com/tendermint/tm-db v0.6.7 // indirect + github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect + github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect + github.com/tidwall/gjson v1.14.4 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + github.com/umbracle/ethgo v0.1.3 // indirect + github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect + github.com/valyala/fastjson v1.4.1 // indirect + github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect + github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/xlab/treeprint v1.1.0 // indirect + github.com/yuin/goldmark v1.4.13 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + github.com/zondax/hid v0.9.0 // indirect + go.dedis.ch/fixbuf v1.0.3 // indirect + go.dedis.ch/kyber/v3 v3.0.14 // indirect + go.etcd.io/bbolt v1.3.6 // indirect + go.opencensus.io v0.24.0 // indirect + go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.24.0 + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/mod v0.9.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.7.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + gonum.org/v1/gonum v0.12.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect + google.golang.org/grpc v1.53.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/guregu/null.v4 v4.0.0 + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.25.4 // indirect + k8s.io/apiextensions-apiserver v0.25.3 // indirect + k8s.io/apimachinery v0.25.4 // indirect + k8s.io/cli-runtime v0.25.4 // indirect + k8s.io/client-go v0.25.4 // indirect + k8s.io/component-base v0.25.4 // indirect + k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/kubectl v0.25.4 // indirect + k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect + sigs.k8s.io/controller-runtime v0.13.0 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/kustomize/api v0.12.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) + +replace ( + // Fix go mod tidy issue for ambiguous imports from go-ethereum + // See https://github.com/ugorji/go/issues/279 + github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.1 + + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + + github.com/prometheus/client_golang => github.com/prometheus/client_golang v1.14.0 + + github.com/prometheus/common => github.com/prometheus/common v0.10.0 + + github.com/satori/go.uuid => github.com/satori/go.uuid v1.2.0 + + // Make sure we're working with the latest ops + github.com/goplugin/plugin-starknet/ops => ../ops + github.com/goplugin/plugin-starknet/relayer => ../relayer + + // K8s imports are weird + k8s.io/api => k8s.io/api v0.25.4 + k8s.io/client-go => k8s.io/client-go v0.25.4 +) diff --git a/integration-tests/go.sum b/integration-tests/go.sum new file mode 100644 index 0000000..b19c47d --- /dev/null +++ b/integration-tests/go.sum @@ -0,0 +1,2093 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4 h1:ksUxwH3OD5sxkjzEqGxNTl+Xjsmu3BnC/300MhSVTSc= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= +github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= +github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/CosmWasm/wasmd v0.30.0 h1:oUVz3TgO/+24JZQdoTOlOv+IK7N9hEa/s3M4eR9i4FQ= +github.com/CosmWasm/wasmvm v1.1.1 h1:0xtdrmmsP9fibe+x42WcMkp5aQ738BICgcH3FNVLzm4= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Depado/ginprom v1.7.4 h1:4cV9RYKIkT28tZhBDam0p8me2RLypxS0in5Jw4zbcgg= +github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= +github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac h1:TQ2m26VW06Df1P82Ed/jZhBtf13pReWyl2XQ8hy+J08= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac/go.mod h1:FTk2+xybtQe5X+oNFx+a0n5EeZMD9Nc+LCH4fxFwrEE= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OneOfOne/xxhash v1.2.6 h1:U68crOE3y3MPttCMQGywZOLrTeF5HHJ3/vDBCJn9/bA= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q= +github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/ava-labs/coreth v0.11.0-rc.4 h1:oYZMWZcXYa4dH2hQBIAH/DD0rL2cB3btPGdabpCH5Ug= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= +github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= +github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= +github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= +github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= +github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= +github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +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/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 h1:CyuI+igIjadM/GRnE2o0q+WCwipDh0n2cUYFPAvxziM= +github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657/go.mod h1:JRiumF+RFsH1mrrP8FUsi9tExPylKkO/oSRWeQEUdLE= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 h1:Puu1hUwfps3+1CUzYdAZXijuvLuRMirgiXdf3zsM2Ig= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= +github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/confio/ics23/go v0.7.0 h1:00d2kukk7sPoHWL4zZBZwzxnpA2pec1NPdwbSokJ5w8= +github.com/confio/ics23/go v0.7.0/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= +github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= +github.com/cosmos/cosmos-proto v1.0.0-alpha8 h1:d3pCRuMYYvGA5bM0ZbbjKn+AoQD4A7dyNG2wzwWalUw= +github.com/cosmos/cosmos-sdk v0.45.11 h1:Pc44fFEkai0KXFND5Ys/2ZJkfVdstMIBzKBN8MY7Ll0= +github.com/cosmos/cosmos-sdk v0.45.11/go.mod h1:45z8Q1Ah4iypFycu2Kl4kBPIsQKUiND8G2CUX+HTtPM= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gogoproto v1.4.3 h1:RP3yyVREh9snv/lsOvmsAPQt8f44LgL281X0IOIhhcI= +github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= +github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= +github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok= +github.com/cosmos/ibc-go/v4 v4.2.0 h1:Fx/kKq/uvawrAxk6ZrQ6sEIgffLRU5Cs/AUnvpPBrHI= +github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= +github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= +github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= +github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= +github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= +github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= +github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= +github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= +github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= +github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dontpanicdao/caigo v0.4.0 h1:S0wRKh2EZ9qj6IfHZIGXxiJF37emRCqnZwDhRb1+DJ4= +github.com/dontpanicdao/caigo v0.4.0/go.mod h1:1YuwgcVLODaS/n0vfuYN/Q0mdWs8UDfDMkSpUdkKXD4= +github.com/duo-labs/webauthn v0.0.0-20210727191636-9f1b88ef44cc h1:mLNknBMRNrYNf16wFFUyhSAe1tISZN7oAfal4CZ2OxY= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= +github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.11.5 h1:3M1uan+LAUvdn+7wCEFrcMM4LJTeuxDrPTg/f31a5QQ= +github.com/ethereum/go-ethereum v1.11.5/go.mod h1:it7x0DWnTDMfVFdXcU6Ti4KEFQynLHVRarcSlPr0HBo= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= +github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= +github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/gagliardetto/binary v0.6.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0= +github.com/gagliardetto/binary v0.7.1 h1:6ggDQ26vR+4xEvl/S13NcdLK3MUCi4oSy73pS9aI1cI= +github.com/gagliardetto/binary v0.7.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0= +github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= +github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 h1:q2IztKyRQUxJ6abXRsawaBtvDFvM+szj4jDqV4od1gs= +github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27/go.mod h1:NFuoDwHPvw858ZMHUJr6bkhN8qHt4x6e+U3EYHxAwNY= +github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= +github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= +github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= +github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= +github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g= +github.com/gin-contrib/expvar v0.0.1 h1:IuU5ArEgihz50vG8Onrwz22kJr7Mcvgv9xSSpfU5g+w= +github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= +github.com/gin-contrib/sessions v0.0.5/go.mod h1:vYAuaUPqie3WUSsft6HUlCjlwwoJQs97miaG2+7neKY= +github.com/gin-contrib/size v0.0.0-20220707104239-f5a650759656 h1:IxCENnXjmppSWzMedenibLt8tvKg4b7kQ7lTGjGjsgw= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY= +github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= +github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= +github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= +github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= +github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.2.2 h1:ihRI7YFwcZdiSD7SIenIhHfQH3OuDvWerAUBZbeQS3M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.0.0-20200609203250-aecfd211c9ce h1:7UnVY3T/ZnHUrfviiAgIUjg2PXxsQfs5bphsG8F7Keo= +github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU= +github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= +github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.5 h1:cwOUcGMLdLPWgu3SlrCckCMznaGADbPqE0r8h768/Dg= +github.com/ipfs/go-datastore v0.4.5/go.mod h1:eXTcaaiN6uOlVCLS9GjJUJtlvJfM3xk23w3fyfrmmJs= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= +github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= +github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= +github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= +github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= +github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= +github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= +github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= +github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-ipns v0.0.2 h1:oq4ErrV4hNQ2Eim257RTYRgfOSV/s8BDaf9iIl4NwFs= +github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U= +github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= +github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A= +github.com/ipfs/go-log v1.0.4 h1:6nLQdX4W8P9yZZFH7mO+X/PzjN8Laozm/lMJ6esdgzY= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= +github.com/ipfs/go-log/v2 v2.1.1 h1:G4TtqN+V9y9HY9TA6BwbCVyyBZ2B9MbCjR2MtGx8FR0= +github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= +github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= +github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= +github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= +github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= +github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.8 h1:3fdt97i/cwSU83+E0hZTC/Xpc9mTZxc6UWSCRcSbxiE= +github.com/lib/pq v1.10.8/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= +github.com/libp2p/go-addr-util v0.0.2 h1:7cWK5cdA5x72jX0g8iLrQWm5TRJZ6CzGdPEhWj7plWU= +github.com/libp2p/go-addr-util v0.0.2/go.mod h1:Ecd6Fb3yIuLzq4bD7VcywcVSBtefcAwnUISBM3WG15E= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= +github.com/libp2p/go-conn-security-multistream v0.2.0 h1:uNiDjS58vrvJTg9jO6bySd1rMKejieG7v45ekqHbZ1M= +github.com/libp2p/go-conn-security-multistream v0.2.0/go.mod h1:hZN4MjlNetKD3Rq5Jb/P5ohUnFLNzEAR4DLSzpn2QLU= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= +github.com/libp2p/go-eventbus v0.2.1 h1:VanAdErQnpTioN2TowqNcOijf6YwhuODe4pPKSDpxGc= +github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.2/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= +github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= +github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= +github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= +github.com/libp2p/go-libp2p v0.12.0/go.mod h1:FpHZrfC1q7nA8jitvdjKBDF31hguaC676g/nT9PgQM0= +github.com/libp2p/go-libp2p v0.13.0 h1:tDdrXARSghmusdm0nf1U/4M8aj8Rr0V2IzQOXmbzQ3s= +github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= +github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= +github.com/libp2p/go-libp2p-asn-util v0.0.0-20201026210036-4f868c957324 h1:2H/P+forDWBHije1WULwPfGduByUmC4fthndHVRpYNU= +github.com/libp2p/go-libp2p-asn-util v0.0.0-20201026210036-4f868c957324/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= +github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= +github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= +github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= +github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= +github.com/libp2p/go-libp2p-autonat v0.4.0 h1:3y8XQbpr+ssX8QfZUHekjHCYK64sj6/4hnf/awD4+Ug= +github.com/libp2p/go-libp2p-autonat v0.4.0/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= +github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= +github.com/libp2p/go-libp2p-blankhost v0.2.0 h1:3EsGAi0CBGcZ33GwRuXEYJLLPoVWyXJ1bcJzAJjINkk= +github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= +github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= +github.com/libp2p/go-libp2p-circuit v0.4.0 h1:eqQ3sEYkGTtybWgr6JLqJY6QLtPWRErvFjFDfAOO1wc= +github.com/libp2p/go-libp2p-circuit v0.4.0/go.mod h1:t/ktoFIUzM6uLQ+o1G6NuBl2ANhBKN9Bc8jRIk31MoA= +github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= +github.com/libp2p/go-libp2p-core v0.2.5/go.mod h1:6+5zJmKhsf7yHn1RbmYDu08qDUpIUxGdqHuEZckmZOA= +github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUhgJJLAa6almrII= +github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.3/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.4/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.5/go.mod h1:vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM= +github.com/libp2p/go-libp2p-core v0.5.6/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.7.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.5 h1:aEgbIcPGsKy6zYcC+5AJivYFedhYa4sW7mIpWpUaLKw= +github.com/libp2p/go-libp2p-core v0.8.5/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= +github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= +github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= +github.com/libp2p/go-libp2p-discovery v0.5.0 h1:Qfl+e5+lfDgwdrXdu4YNCWyEo3fWuP+WgN9mN0iWviQ= +github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= +github.com/libp2p/go-libp2p-kad-dht v0.11.1 h1:FsriVQhOUZpCotWIjyFSjEDNJmUzuMma/RyyTDZanwc= +github.com/libp2p/go-libp2p-kad-dht v0.11.1/go.mod h1:5ojtR2acDPqh/jXf5orWy8YGb8bHQDS+qeDcoscL/PI= +github.com/libp2p/go-libp2p-kbucket v0.4.7 h1:spZAcgxifvFZHBD8tErvppbnNiKA5uokDu3CV7axu70= +github.com/libp2p/go-libp2p-kbucket v0.4.7/go.mod h1:XyVo99AfQH0foSf176k4jY1xUJ2+jUJIZCSDm7r2YKk= +github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= +github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= +github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= +github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= +github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= +github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= +github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= +github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= +github.com/libp2p/go-libp2p-mplex v0.4.1 h1:/pyhkP1nLwjG3OM+VuaNJkQT/Pqq73WzB3aDN3Fx1sc= +github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= +github.com/libp2p/go-libp2p-nat v0.0.6 h1:wMWis3kYynCbHoyKLPBEMu4YRLltbm8Mk08HGSfvTkU= +github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= +github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= +github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= +github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM= +github.com/libp2p/go-libp2p-noise v0.1.2 h1:IH9GRihQJTx56obm+GnpdPX4KeVIlvpXrP6xnJ0wxWk= +github.com/libp2p/go-libp2p-noise v0.1.2/go.mod h1:9B10b7ueo7TIxZHHcjcDCo5Hd6kfKT2m77by82SFRfE= +github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= +github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= +github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= +github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.6/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= +github.com/libp2p/go-libp2p-peerstore v0.2.7 h1:83JoLxyR9OYTnNfB5vvFqvMUv/xDNa6NoPHnENhBsGw= +github.com/libp2p/go-libp2p-peerstore v0.2.7/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= +github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= +github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= +github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= +github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs28kCIfql0= +github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= +github.com/libp2p/go-libp2p-routing-helpers v0.2.3/go.mod h1:795bh+9YeoFl99rMASoiVgHdi5bjack0N1+AFAdbvBw= +github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= +github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= +github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= +github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= +github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= +github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= +github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.3.1/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.4.0 h1:hahq/ijRoeH6dgROOM8x7SeaKK5VgjjIr96vdrT+NUA= +github.com/libp2p/go-libp2p-swarm v0.4.0/go.mod h1:XVFcO52VoLoo0eitSxNQWYq4D6sydGOweTOAjJNraCw= +github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= +github.com/libp2p/go-libp2p-testing v0.3.0/go.mod h1:efZkql4UZ7OVsEfaxNHZPzIehtsBXMrXnCfJIgDti5g= +github.com/libp2p/go-libp2p-testing v0.4.0 h1:PrwHRi0IGqOwVQWR3xzgigSlhlLfxgfXgkHxr77EghQ= +github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= +github.com/libp2p/go-libp2p-tls v0.1.3 h1:twKMhMu44jQO+HgQK9X8NHO5HkeJu2QbhLzLJpa8oNM= +github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= +github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= +github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= +github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= +github.com/libp2p/go-libp2p-transport-upgrader v0.4.0 h1:xwj4h3hJdBrxqMOyMUjwscjoVst0AASTsKtZiTChoHI= +github.com/libp2p/go-libp2p-transport-upgrader v0.4.0/go.mod h1:J4ko0ObtZSmgn5BX5AmegP+dK3CSnU2lMCKsSq/EY0s= +github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= +github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= +github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= +github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU= +github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= +github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= +github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.5.1 h1:sX4WQPHMhRxJE5UZTfjEuBvlQWXB5Bo3A2JK9ZJ9EM0= +github.com/libp2p/go-libp2p-yamux v0.5.1/go.mod h1:dowuvDu8CRWmr0iqySMiSxK+W0iL5cMVO9S94Y6gkv4= +github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= +github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= +github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= +github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= +github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= +github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= +github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-mplex v0.3.0 h1:U1T+vmCYJaEoDJPV1aq31N56hS+lJgb397GsylNSgrU= +github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.6 h1:lQ7Uc0kS1wb1EfRxO2Eir/RJoHkHn7t6o+EiwsYIKJA= +github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= +github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= +github.com/libp2p/go-nat v0.0.5 h1:qxnwkco8RLKqVh1NmjQ+tJ8p8khNLFxuElYG/TwqW4Q= +github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.4 h1:47V0+hJfYaqj1WO0A+cDkRc9xr9qKiK7i8zaoGv8Mmo= +github.com/libp2p/go-netroute v0.1.4/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= +github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= +github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= +github.com/libp2p/go-reuseport v0.0.2 h1:XSG94b1FJfGA01BUrT82imejHQyTxO4jEWqheyCXYvU= +github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ= +github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= +github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= +github.com/libp2p/go-reuseport-transport v0.0.4 h1:OZGz0RB620QDGpv300n1zaOcKGGAoGVf8h9txtt/1uM= +github.com/libp2p/go-reuseport-transport v0.0.4/go.mod h1:trPa7r/7TJK/d+0hdBLOCGvpQQVOU74OXbNCIMkufGw= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-sockaddr v0.1.0 h1:Y4s3/jNoryVRKEBrkJ576F17CPOaMIzUeCsg7dlTDj0= +github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= +github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= +github.com/libp2p/go-stream-muxer-multistream v0.3.0 h1:TqnSHPJEIqDEO7h1wZZ0p3DXdvDSiLHQidKKUGZtiOY= +github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= +github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= +github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= +github.com/libp2p/go-tcp-transport v0.2.1 h1:ExZiVQV+h+qL16fzCWtd1HSzPsqWottJ8KXwWaVi8Ns= +github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1PpPUrHIWQ8aFw7M= +github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= +github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= +github.com/libp2p/go-ws-transport v0.3.1/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= +github.com/libp2p/go-ws-transport v0.4.0 h1:9tvtQ9xbws6cA5LvqdE6Ne3vcmGB4f1z9SByggk4s0k= +github.com/libp2p/go-ws-transport v0.4.0/go.mod h1:EcIEKqf/7GDjth6ksuS/6p7R49V4CBY6/E7R/iyhYUA= +github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v2 v2.0.0 h1:vSGhAy5u6iHBq11ZDcyHH4Blcf9xlBhT4WQDoOE90LU= +github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= +github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= +github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= +github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= +github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= +github.com/multiformats/go-multiaddr v0.3.3 h1:vo2OTSAqnENB2rLk79pLtr+uhj+VAzSe3uef5q0lRSs= +github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= +github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA= +github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= +github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= +github.com/multiformats/go-multiaddr-net v0.1.3/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.1.4/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.2.0 h1:MSXRGN0mFymt6B1yo/6BPnIRpLPEnKgQNvVfCX5VDJk= +github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14 h1:QoBceQYQQtNUuf6s7wHxnE2c8bhbMqhfGzNI032se/I= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.0/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= +github.com/multiformats/go-multistream v0.2.2 h1:TCYu1BHTDr1F/Qm75qwYISQdzGcRdC21nFgQW7l7GBo= +github.com/multiformats/go-multistream v0.2.2/go.mod h1:UIcnm7Zuo8HKG+HkWgfQsGL+/MIEhyTqbODbIUwSXKs= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= +github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +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.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +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.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +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.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/pressly/goose/v3 v3.5.3 h1:lIQIIXVbdO2RuQtJBS1e7MZjKEk0demVWt6i0YPiOrg= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/pyroscope-io/client v0.7.0 h1:LWuuqPQ1oa6x7BnmUOuo/aGwdX85QGhWZUBYWWW3zdk= +github.com/pyroscope-io/client v0.7.0/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= +github.com/pyroscope-io/godeltaprof v0.1.0 h1:UBqtjt0yZi4jTxqZmLAs34XG6ycS3vUTlhEUSq4NHLE= +github.com/pyroscope-io/godeltaprof v0.1.0/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= +github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v3 v3.22.12 h1:oG0ns6poeUSxf78JtOsfygNWuEHYYz8hnnNg7P04TJs= +github.com/shirou/gopsutil/v3 v3.22.12/go.mod h1:Xd7P1kwZcp5VW52+9XsirIKd/BROzbb2wdX3Kqlz9uI= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= +github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= +github.com/goplugin/plugin-cosmos v0.1.7-0.20230424184432-20550926ba07 h1:LBjS7F3Xy9jYlgiEMMMU5f+i/v7oZ97MYseyF6aY7ts= +github.com/goplugin/plugin-env v0.3.29 h1:hcIw/BeuB0wKiiE3umAUNBZzWkHO24XF3OW9xSrlMbI= +github.com/goplugin/plugin-env v0.3.29/go.mod h1:9c0Czq4a6wZKY20BcoAlK29DnejQIiLo/MwKYtSFnHk= +github.com/goplugin/plugin-relay v0.1.7-0.20230424181359-6cb4dc745ec7 h1:uLPs52VF4VLmNCeC4T398nAVjcmS1KIzt6ZK6iERZ/4= +github.com/goplugin/plugin-relay v0.1.7-0.20230424181359-6cb4dc745ec7/go.mod h1:3E3PXaMEl2gADk/DTkbOxsvtpDcJ5ZSyW+vt0TjsEH0= +github.com/goplugin/plugin-solana v1.0.3-0.20230424191709-c9fec8c08e1b h1:CJIPaIwlmV5GFSf9Of1Qnpud3gBAeRiT049IiZNzR2g= +github.com/goplugin/plugin-testing-framework v1.11.5 h1:gYSnOQhLxgE0mxwnv015nNnPgH9kcosx+AzPboEFo38= +github.com/goplugin/plugin-testing-framework v1.11.5/go.mod h1:0ktPcDE5fFSvNewsaHuC4tGVaiCMQsl5RN/cWO5k0rg= +github.com/goplugin/pluginv3.0/integration-tests v0.0.0-20230420131147-ce3c53a39d07 h1:UW3llKpFIfVmtu5F1GDLz0S4cze9Un46k15M+JDXSCU= +github.com/goplugin/pluginv3.0/integration-tests v0.0.0-20230420131147-ce3c53a39d07/go.mod h1:dvEXSlzknoPm6YFaa0Ubs57CPFjhBbXnMju7WgiqiD4= +github.com/goplugin/pluginv3.0/v2 v2.1.0-beta0.0.20230427051455-edb338fd2536 h1:uomhVY2qYciWK0XuFqEpqbKdVmYAFQCDw6Lg8L8Hrt0= +github.com/goplugin/pluginv3.0/v2 v2.1.0-beta0.0.20230427051455-edb338fd2536/go.mod h1:adNwYzBQKE0gRgebDch8E0Iu5ke0/PmoRCQe638cjSw= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc h1:aSCDAai0Dmbhp/KHTtJnC/EJcaEz4CAO80SKRzRZiQA= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc/go.mod h1:5JnCHuYgmIP9ZyXzgAfI5Iwu0WxBtBKp+ApeT5o1Cjw= +github.com/smartcontractkit/ocr2keepers v0.6.14 h1:Rg+SYd8PCyd4CcCetwnRKjVEQsHVsV6QOaWcLhi+6sg= +github.com/smartcontractkit/ocr2keepers v0.6.14/go.mod h1:gqIksJFzdXFsHfGdCWm1uTxbwvAltgcwcaqIgAStC1A= +github.com/smartcontractkit/ocr2vrf v0.0.0-20230425184732-a793ac75f0a3 h1:K71txN76a7Tf9teLEpoxsMhWXi36W2gDeicLqqa6/p0= +github.com/smartcontractkit/ocr2vrf v0.0.0-20230425184732-a793ac75f0a3/go.mod h1:NKkp8yf3trq+hJe/gn2Q1dd4abZvcYavUKPzYJCgVew= +github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb h1:OMaBUb4X9IFPLbGbCHsMU+kw/BPCrewaVwWGIBc0I4A= +github.com/smartcontractkit/sqlx v1.3.5-0.20210805004948-4be295aacbeb/go.mod h1:HNUu4cJekUdsJbwRBCiOybtkPJEfGRELQPe2tkoDEyk= +github.com/goplugin/wsrpc v0.6.2-0.20230317160629-382a1ac921d8 h1:Wn9X8mOQoQzzh1kBK22EDDgyXAfVjDlFlqUQW5kyyGo= +github.com/goplugin/wsrpc v0.6.2-0.20230317160629-382a1ac921d8/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= +github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tendermint/tendermint v0.34.23 h1:JZYsdc59aOiT5efou+BHILJv8x6FlRyvlor84Xq9Tb0= +github.com/tendermint/tendermint v0.34.23/go.mod h1:rXVrl4OYzmIa1I91av3iLv2HS0fGSiucyW9J4aMTpKI= +github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= +github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= +github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= +github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= +github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrjiCUizNCxI53bl/BnPiVwXqLzqYTqgU= +github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= +github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ulule/limiter/v3 v3.11.1 h1:wm6YaA2JwIXc0S+z8TK8/neWMOTf4m20I5jL1dwLRcw= +github.com/umbracle/ethgo v0.1.3 h1:s8D7Rmphnt71zuqrgsGTMS5gTNbueGO1zKLh7qsFzTM= +github.com/umbracle/ethgo v0.1.3/go.mod h1:g9zclCLixH8liBI27Py82klDkW7Oo33AxUOr+M9lzrU= +github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E= +github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4= +github.com/unrolled/secure v0.0.0-20190624173513-716474489ad3 h1:Is9lt18DCzmbgaXowC/LuO1prTus8ejfgMn+GelBuHs= +github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= +github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= +github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= +github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= +github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= +github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= +go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= +go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= +go.dedis.ch/kyber/v3 v3.0.9/go.mod h1:rhNjUUg6ahf8HEg5HUvVBYoWY4boAafX8tYxX+PS+qg= +go.dedis.ch/kyber/v3 v3.0.14 h1:vnHb/Q5ape/e98oYZdbOrs3CkQ1bUIZFANmOxb/3zyo= +go.dedis.ch/kyber/v3 v3.0.14/go.mod h1:kXy7p3STAurkADD+/aZcsznZGKVHEqbtmdIzvPfrs1U= +go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= +go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= +go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo= +go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g= +go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= +go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +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= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= +gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o= +gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/guregu/null.v2 v2.1.2 h1:YOuepWdYqGnrenzPyMi+ybCjeDzjdazynbwsXXOk4i8= +gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= +gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= +k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= +k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k= +k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo= +k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= +k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= +k8s.io/cli-runtime v0.25.4 h1:GTSBN7aKBrc2LqpdO30CmHQqJtRmotxV7XsMSP+QZIk= +k8s.io/cli-runtime v0.25.4/go.mod h1:JGOw1CR8v4Mcz6cEKA7bFQe0bPrNn1l5sGAX1/Ke4Eg= +k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8= +k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= +k8s.io/component-base v0.25.4 h1:n1bjg9Yt+G1C0WnIDJmg2fo6wbEU1UGMRiQSjmj7hNQ= +k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/kubectl v0.25.4 h1:O3OA1z4V1ZyvxCvScjq0pxAP7ABgznr8UvnVObgI6Dc= +k8s.io/kubectl v0.25.4/go.mod h1:CKMrQ67Bn2YCP26tZStPQGq62zr9pvzEf65A0navm8k= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= +sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= +sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= +sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= +sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/integration-tests/infra_deployments/deployer_test.go b/integration-tests/infra_deployments/deployer_test.go new file mode 100644 index 0000000..a349f90 --- /dev/null +++ b/integration-tests/infra_deployments/deployer_test.go @@ -0,0 +1,100 @@ +package infra_deployments_test + +import ( + "fmt" + "net/url" + "testing" + + "github.com/goplugin/plugin-starknet/integration-tests/common" + "github.com/goplugin/plugin-starknet/ops/gauntlet" + "github.com/goplugin/plugin-starknet/ops/utils" + "github.com/goplugin/pluginv3.0/integration-tests/client" + "github.com/stretchr/testify/require" +) + +const ( + L2RpcUrl = "https://alpha4-2.starknet.io" + P2pPort = "5001" +) + +var ( + observationSource = ` + val [type="bridge" name="bridge-coinmetrics" requestData=<{"data": {"from":"PLI","to":"USD"}}>] + parse [type="jsonparse" path="result"] + val -> parse + ` + juelsPerFeeCoinSource = `""" + sum [type="sum" values=<[451000]> ] + sum + """ + ` +) + +func createKeys(testState *testing.T) ([]*client.Plugin, error) { + urls := [][]string{ + // Node access params + {"NODE_URL", "NODE_USER", "NODE_PASS"}, + } + var clients []*client.Plugin + + for _, nodeUrl := range urls { + u, _ := url.Parse(nodeUrl[0]) + c, err := client.NewPlugin(&client.PluginConfig{ + URL: nodeUrl[0], + Email: nodeUrl[1], + Password: nodeUrl[2], + RemoteIP: u.Host, + }) + if err != nil { + return nil, err + } + key, _ := c.MustReadP2PKeys() + if key == nil { + _, _, err = c.CreateP2PKey() + require.NoError(testState, err) + } + clients = append(clients, c) + } + return clients, nil +} +func TestOCRBasic(testState *testing.T) { + var err error + t := &common.Test{} + t.Common = common.New() + t.Common.Default(testState) + t.Cc = &common.PluginClient{} + t.Common.P2PPort = P2pPort + t.Cc.PluginNodes, err = createKeys(testState) + require.NoError(testState, err) + t.Cc.NKeys, _, err = client.CreateNodeKeysBundle(t.Cc.PluginNodes, t.Common.ChainName, t.Common.ChainId) + require.NoError(testState, err) + for _, n := range t.Cc.PluginNodes { + _, _, err = n.CreateStarkNetChain(&client.StarkNetChainAttributes{ + Type: t.Common.ChainName, + ChainID: t.Common.ChainId, + Config: client.StarkNetChainConfig{}, + }) + require.NoError(testState, err) + _, _, err = n.CreateStarkNetNode(&client.StarkNetNodeAttributes{ + Name: t.Common.ChainName, + ChainID: t.Common.ChainId, + Url: L2RpcUrl, + }) + require.NoError(testState, err) + } + t.Common.Testnet = true + t.Common.L2RPCUrl = L2RpcUrl + t.Sg, err = gauntlet.NewStarknetGauntlet(fmt.Sprintf("%s/", utils.ProjectRoot)) + require.NoError(testState, err, "Could not get a new gauntlet struct") + err = t.Sg.SetupNetwork(t.Common.L2RPCUrl) + require.NoError(testState, err, "Setting up gauntlet network should not fail") + err = t.DeployGauntlet(0, 100000000000, 9, "auto", 1, 1) + require.NoError(testState, err, "Deploying contracts should not fail") + t.SetBridgeTypeAttrs(&client.BridgeTypeAttributes{ + Name: "bridge-coinmetrics", + URL: "ADAPTER_URL", // ADAPTER_URL e.g https://adapters.main.sand.cldev.sh/coinmetrics + }) + + err = t.Common.CreateJobsForContract(t.Cc, observationSource, juelsPerFeeCoinSource, t.OCRAddr, t.AccountAddresses) + require.NoError(testState, err) +} diff --git a/integration-tests/networks.yaml b/integration-tests/networks.yaml new file mode 100644 index 0000000..cf683f3 --- /dev/null +++ b/integration-tests/networks.yaml @@ -0,0 +1,67 @@ +private_keys: &private_keys + private_keys: # Open source private keys for use in simulated networks + - ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + - 59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d + - 5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a + - 7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6 + - 47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a + - 8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba + - 92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e + - 4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356 + - dbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 + - 2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 + - f214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897 + - 701b615bbdfb9de65240bc28bd21bbc0d996645a3dd57e7b12bc2bdf6f192c82 + - a267530f49f8280200edf313ee7af6b827f2a8bce2897751d06a843f644967b1 + - 47c99abed3324a2707c28affff1267e45918ec8c3f20b8aa892e8b065d2942dd + - c526ee95bf44d8fc405a158bb884d9d1238d99f0612e9f33d006bb0789009aaa + - 8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61 + - ea6c44ac03bff858b476bba40716402b03e41b8e97e276d1baec7c37d42484a0 + - 689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b061667b5a93e037fd + - de9be858da4a475276426320d5e9262ecfc3ba460bfac56360bfa6c4c28b4ee0 + - df57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e + +selected_networks: # Selected network(s) for test execution + - 'geth' + - 'starknet-dev' + +networks: + geth: &common_ethereum + name: 'Ethereum Geth dev' + chain_id: 1337 + type: eth_simulated + secret_private_keys: false + namespace_for_secret: default + <<: *private_keys + plugin_transaction_limit: 500000 + transaction_timeout: 2m + minimum_confirmations: 1 + gas_estimation_buffer: 10000 + block_gas_limit: 40000000 + starknet-dev: + name: 'Starknet dev simulator' + chain_id: 2020 + type: l2_starknet_dev + l1_bridge_addr: '0x83D76591560d9CD02CE16c060c92118d19F996b3' + ethereum_kovan: &common_ethereum_testnet + name: 'Ethereum Kovan' + chain_id: 42 + type: eth_testnet + namespace_for_secret: default + secret_private_keys: false + secret_private_url: false + private_url: kovan_testnet_url + private_keys: + - kovan_testnet_1 + plugin_transaction_limit: 500000 + transaction_timeout: 2m + minimum_confirmations: 1 + gas_estimation_buffer: 10000 + block_gas_limit: 40000000 + ethereum_goerli: + <<: *common_ethereum_testnet + name: 'Ethereum Goerli' + chain_id: 5 + private_url: goerli_private_url + private_keys: + - goerli_testnet_1 diff --git a/integration-tests/package.json b/integration-tests/package.json new file mode 100644 index 0000000..c2725fe --- /dev/null +++ b/integration-tests/package.json @@ -0,0 +1,7 @@ +{ + "name": "@pluginv3.0/starknet-integration-tests", + "version": "0.0.1", + "license": "MIT", + "dependencies": {}, + "devDependencies": {} +} diff --git a/integration-tests/scripts/buildTestImage b/integration-tests/scripts/buildTestImage new file mode 100755 index 0000000..a8a8f8f --- /dev/null +++ b/integration-tests/scripts/buildTestImage @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# build test binaries +# accepts a single space separated argument of the folders to build + +set -ex + +# get this scripts directory +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cd "$SCRIPT_DIR"/../../ || exit 1 + +TAG_VERSION="${1}" +BASE_IMAGE_VERSION="${2}" +SUITES=$3 +DEFAULT_SUITES="smoke soak" +ACCOUNT=$(aws sts get-caller-identity | jq -r .Account) +AWS_BASE="${ACCOUNT}".dkr.ecr.us-west-2.amazonaws.com +TAG="${AWS_BASE}"/plugin-starknet-tests:"${TAG_VERSION}" +BASE_IMAGE="${AWS_BASE}"/test-base-image + +if [ "${TAG_VERSION}" = "" ]; then + echo "Need an argument for the image tag version in argument 1" + exit 1 +fi + +if [ "${BASE_IMAGE_VERSION}" = "" ]; then + echo "Need an argument for the test-base-image tag version in argument 2" + exit 1 +fi + +if [ "${SUITES}" = "" ]; then + echo "SUITES not set, using defaults \"${DEFAULT_SUITES}\"" + SUITES=${DEFAULT_SUITES} +fi + +aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin "${AWS_BASE}" +docker build -t "${TAG}" -f "./integration-tests/test.Dockerfile" --build-arg BASE_IMAGE="${BASE_IMAGE}" --build-arg IMAGE_VERSION="${BASE_IMAGE_VERSION}" --build-arg SUITES="${SUITES}" . +if "${4}" = "true"]; then + docker push "${TAG}" +fi diff --git a/integration-tests/scripts/buildTests b/integration-tests/scripts/buildTests new file mode 100755 index 0000000..6c9731b --- /dev/null +++ b/integration-tests/scripts/buildTests @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# build test binaries +# accepts a single space separated argument of the folders to build + +set -ex + +# get this scripts directory +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cd "$SCRIPT_DIR"/../../ || exit 1 + +# integration prep +make test-integration-prep + +cd "$SCRIPT_DIR"/../ || exit 1 + +# parse out quotes if they exist in the string +temp="${1%\"}" +tosplit="${temp#\"}" + +# find the suite name +OIFS=$IFS +IFS=' ' +for x in $tosplit +do + go test -c ./"${x}" +done +IFS=$OIFS diff --git a/integration-tests/scripts/entrypoint b/integration-tests/scripts/entrypoint new file mode 100755 index 0000000..94ea19c --- /dev/null +++ b/integration-tests/scripts/entrypoint @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Runs tests for a specific product + +set -ex + +# get this scripts directory +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cd "$SCRIPT_DIR"/../ || exit 1 + +# Arguments needed +# ARGS=${ARGS:=} any extra args for go test +# SUITE=${SUITE:=} the suite of tests you want to run +# TEST_NAME=${TEST_NAME:=} The specific test to run +# run the tests +nix develop -c ./"${SUITE}".test -test.v -test.count 1 ${ARGS} -test.run ^${TEST_NAME}$ diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go new file mode 100644 index 0000000..934eb46 --- /dev/null +++ b/integration-tests/smoke/ocr2_test.go @@ -0,0 +1,64 @@ +package smoke_test + +// revive:disable:dot-imports +import ( + "flag" + "fmt" + "github.com/goplugin/pluginv3.0/integration-tests/actions" + "go.uber.org/zap/zapcore" + "testing" + + "github.com/goplugin/plugin-starknet/integration-tests/common" + "github.com/goplugin/plugin-starknet/ops/gauntlet" + "github.com/goplugin/plugin-starknet/ops/utils" + "github.com/stretchr/testify/require" +) + +var ( + keepAlive bool +) + +func init() { + flag.BoolVar(&keepAlive, "keep-alive", false, "enable to keep the cluster alive") +} + +var ( + err error + testState *common.Test + decimals = 9 + mockServerVal = 900000000 +) + +func TestOCRBasic(t *testing.T) { + testState = &common.Test{ + T: t, + } + testState.Common = common.New() + testState.Common.Default(t) + // Setting this to the root of the repo for cmd exec func for Gauntlet + testState.Sg, err = gauntlet.NewStarknetGauntlet(fmt.Sprintf("%s/", utils.ProjectRoot)) + require.NoError(t, err, "Could not get a new gauntlet struct") + + testState.DeployCluster() + require.NoError(t, err, "Deploying cluster should not fail") + if testState.Common.Env.WillUseRemoteRunner() { + return // short circuit here if using a remote runner + } + err = testState.Sg.SetupNetwork(testState.Common.L2RPCUrl) + require.NoError(t, err, "Setting up gauntlet network should not fail") + err = testState.DeployGauntlet(0, 100000000000, decimals, "auto", 1, 1) + require.NoError(t, err, "Deploying contracts should not fail") + if !testState.Common.Testnet { + testState.Devnet.AutoLoadState(testState.OCR2Client, testState.OCRAddr) + } + testState.SetUpNodes(mockServerVal) + + err = testState.ValidateRounds(10, false) + require.NoError(t, err, "Validating round should not fail") + + t.Cleanup(func() { + err = actions.TeardownSuite(t, testState.Common.Env, utils.ProjectRoot, testState.Cc.PluginNodes, nil, zapcore.ErrorLevel) + require.NoError(t, err, "Error tearing down environment") + }) + +} diff --git a/integration-tests/soak/ocr2_test.go b/integration-tests/soak/ocr2_test.go new file mode 100644 index 0000000..cb46ef5 --- /dev/null +++ b/integration-tests/soak/ocr2_test.go @@ -0,0 +1,58 @@ +package soak_test + +// revive:disable:dot-imports +import ( + "flag" + "fmt" + "testing" + "time" + + "github.com/goplugin/plugin-starknet/integration-tests/common" + "github.com/goplugin/plugin-starknet/ops/gauntlet" + "github.com/goplugin/plugin-starknet/ops/utils" + "github.com/goplugin/pluginv3.0/integration-tests/actions" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +var ( + keepAlive bool + err error + testState *common.Test + decimals = 9 + mockServerVal = 900000000 +) + +func init() { + flag.BoolVar(&keepAlive, "keep-alive", false, "enable to keep the cluster alive") +} +func TestOCRSoak(t *testing.T) { + testState = &common.Test{ + T: t, + } + testState.Common = common.New() + testState.Common.Default(t) + // Setting this to the root of the repo for cmd exec func for Gauntlet + testState.Sg, err = gauntlet.NewStarknetGauntlet(fmt.Sprintf("%s/", utils.ProjectRoot)) + require.NoError(t, err, "Could not get a new gauntlet struct") + testState.DeployCluster() + require.NoError(t, err, "Deploying cluster should not fail") + if testState.Common.Env.WillUseRemoteRunner() { + return // short circuit here if using a remote runner + } + err = testState.Sg.SetupNetwork(testState.Common.L2RPCUrl) + require.NoError(t, err, "Setting up network should not fail") + time.Sleep(8 * time.Hour) + err = testState.DeployGauntlet(0, 100000000000, decimals, "auto", 1, 1) + require.NoError(t, err, "Deploying contracts should not fail") + if !testState.Common.Testnet { + testState.Devnet.AutoLoadState(testState.OCR2Client, testState.OCRAddr) + } + testState.SetUpNodes(mockServerVal) + err = testState.ValidateRounds(99999999, true) + require.NoError(t, err, "Validating round should not fail") + t.Cleanup(func() { + err = actions.TeardownSuite(t, testState.Common.Env, utils.ProjectRoot, testState.Cc.PluginNodes, nil, zapcore.ErrorLevel) + require.NoError(t, err, "Error tearing down environment") + }) +} diff --git a/integration-tests/test.Dockerfile b/integration-tests/test.Dockerfile new file mode 100644 index 0000000..d7f87f5 --- /dev/null +++ b/integration-tests/test.Dockerfile @@ -0,0 +1,9 @@ +FROM nixos/nix:latest + +ARG SUITES=smoke soak +ENV NIX_USER_CONF_FILES=/repo/nix.conf + +COPY . /repo/ +WORKDIR /repo +RUN nix develop -c /repo/integration-tests/scripts/buildTests "${SUITES}" +ENTRYPOINT ["/repo/integration-tests/scripts/entrypoint"] diff --git a/integration-tests/test.Dockerfile.dockerignore b/integration-tests/test.Dockerfile.dockerignore new file mode 100644 index 0000000..2010941 --- /dev/null +++ b/integration-tests/test.Dockerfile.dockerignore @@ -0,0 +1,24 @@ +.direnv +.DS_Store +**/*.rs.bk +.idea +.vscode/ +.github/ + +# TS +node_modules/ +contracts/node_modules/ +**/tsconfig.tsbuildinfo +dist +.env +flow-report.jsons +report.json +bin + +# test +id.json +integration-tests/logs +integration-tests/smoke/logs +integration-teststests/smoke/contracts-chaos-state.json +tmp-manifest-* +tests-smoke-report.xml diff --git a/integration-tests/utils/common.go b/integration-tests/utils/common.go new file mode 100644 index 0000000..f7d19c5 --- /dev/null +++ b/integration-tests/utils/common.go @@ -0,0 +1,24 @@ +package utils + +import ( + "os" + "testing" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" + + envConf "github.com/goplugin/plugin-env/config" +) + +// GetTestLogger TODO: This is a duplicate of the same function in plugin-testing-framework. We should replace this with a call to the ctf version when plugin-starknet is updated to use the latest ctf version. +// GetTestLogger instantiates a logger that takes into account the test context and the log level +func GetTestLogger(t *testing.T) zerolog.Logger { + lvlStr := os.Getenv(envConf.EnvVarLogLevel) + if lvlStr == "" { + lvlStr = "info" + } + lvl, err := zerolog.ParseLevel(lvlStr) + require.NoError(t, err, "error parsing log level") + l := zerolog.New(zerolog.NewTestWriter(t)).Output(zerolog.ConsoleWriter{Out: os.Stderr}).Level(lvl).With().Timestamp().Logger() + return l +} diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..9529342 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,37 @@ +// jest.config.ts +import type { Config } from '@jest/types' + +// Prepares 'config.projects' entry for a Jest TS project under '/packages-ts' +const projectConfig = (name: string) => ({ + displayName: name, + testMatch: [`/packages-ts/${name}/**/*.test.ts`], + transform: { + '^.+\\.(ts|tsx)$': 'ts-jest', + }, + globals: { + 'ts-jest': { + tsconfig: `/packages-ts/${name}/tsconfig.json`, + }, + }, +}) + +const config: Config.InitialOptions = { + rootDir: '.', + preset: 'ts-jest', + testEnvironment: 'node', + verbose: true, + automock: true, + testPathIgnorePatterns: ['dist/', 'node_modules/'], + projects: [ + projectConfig('starknet-gauntlet'), + projectConfig('starknet-gauntlet-argent'), + projectConfig('starknet-gauntlet-cli'), + projectConfig('starknet-gauntlet-example'), + projectConfig('starknet-gauntlet-multisig'), + projectConfig('starknet-gauntlet-ocr2'), + projectConfig('starknet-gauntlet-oz'), + projectConfig('starknet-gauntlet-token'), + projectConfig('starknet-gauntlet-emergency-protocol'), + ], +} +export default config diff --git a/monitoring/README.md b/monitoring/README.md new file mode 100644 index 0000000..a8075b4 --- /dev/null +++ b/monitoring/README.md @@ -0,0 +1,91 @@ +# STOM + +## Useful links + +- Starknet on-chain monitor [generated docs](https://pkg.go.dev/github.com/goplugin/plugin-starknet/monitoring/pkg/monitoring). +- On-chain monitoring (OM) framework architecture docs in [blueprints](https://github.com/goplugin/plugin-blueprints/blob/master/monitoring/README.md). +- OM framework [generated docs](https://pkg.go.dev/github.com/goplugin/plugin-relay/pkg/monitoring). + +## Local development + +- Start the monitor's third party dependencies using [docker-compose](https://docs.docker.com/compose/). + Use the docker-compose.yml file in `./ops`: + +```sh +docker-compose up +``` + +- Start an http server that mimics weiwatchers locally. It needs to export a json configuration file for feeds: + +```json +[ + { + "name": "PLI / USD", + "path": "link-usd", + "symbol": "$", + "heartbeat": 0, + "contract_type": "numerical_median_feed", + "status": "testing", + "contract_address": "", + "multiply": "100000000", + "proxy_address": "" + } +] +``` + +It also needs to export a json configuration for for node operators: + +```json +[ + { + "id": "noop", + "nodeAddress": [] + } +] +``` + +One option is to create a folder `/tmp/configs` and add two files `feeds.json` and `nodes.json` with the configs from above, then: + +```bash +python3 -m http.server 4000 +``` + +- Start STOM locally. You will need and RPC endpoint and the address of the PLI token. Make sure you `cd ./monitoring`. + +```bash +STARKNET_RPC_ENDPOINT="" \ +STARKNET_NETWORK_NAME="devnet" \ +STARKNET_NETWORK_ID="1" \ +STARKNET_CHAIN_ID="1" \ +STARKNET_READ_TIMEOUT="5s" \ +STARKNET_POLL_INTERVAL="10s" #test \ +STARKNET_PLI_TOKEN_ADDRESS="" \ +KAFKA_BROKERS="localhost:29092" \ +KAFKA_CLIENT_ID="starknet" \ +KAFKA_SECURITY_PROTOCOL="PLAINTEXT" \ +KAFKA_SASL_MECHANISM="PLAIN" \ +KAFKA_SASL_USERNAME="" \ +KAFKA_SASL_PASSWORD="" \ +KAFKA_CONFIG_SET_SIMPLIFIED_TOPIC="config_set_simplified" \ +KAFKA_TRANSMISSION_TOPIC="transmission_topic" \ +SCHEMA_REGISTRY_URL="http://localhost:8989" \ +SCHEMA_REGISTRY_USERNAME="" \ +SCHEMA_REGISTRY_PASSWORD="" \ +HTTP_ADDRESS="localhost:3000" \ +FEEDS_URL="http://localhost:4000/feeds.json" \ +NODES_URL="http://localhost:4000/nodes.json" \ +go run ./cmd/monitoring/main.go +``` + +- Check the output for the Prometheus scraper + +```bash +curl http://localhost:3000/metrics +``` + +- To check the output for Kafka, you need to install [kcat](https://github.com/edenhill/kcat). After you install, run: + +```bash +kcat -b localhost:29092 -t config_set_simplified +kcat -b localhost:29092 -t transmission_topic +``` diff --git a/monitoring/cmd/monitoring/main.go b/monitoring/cmd/monitoring/main.go new file mode 100644 index 0000000..7a75db0 --- /dev/null +++ b/monitoring/cmd/monitoring/main.go @@ -0,0 +1,80 @@ +package main + +import ( + "context" + "fmt" + + "github.com/goplugin/plugin-relay/pkg/logger" + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + "github.com/goplugin/plugin-starknet/monitoring/pkg/monitoring" +) + +func main() { + ctx := context.Background() + + log, err := logger.New() + if err != nil { + log.Fatal(err) + } + defer func() { + if serr := log.Sync(); serr != nil { + fmt.Printf("Error while closing Logger: %v\n", serr) + } + }() + + starknetConfig, err := monitoring.ParseStarknetConfig() + if err != nil { + log.Fatalw("failed to parse starknet specific configuration", "error", err) + return + } + + readTimeout := starknetConfig.GetReadTimeout() + starknetClient, err := starknet.NewClient( + starknetConfig.GetChainID(), + starknetConfig.GetRPCEndpoint(), + logger.With(log, "component", "starknet-client"), + &readTimeout, + ) + if err != nil { + log.Fatalw("failed to build a starknet.Client", "error", err) + } + ocr2Client, err := ocr2.NewClient( + starknetClient, + logger.With(log, "component", "ocr2-client"), + ) + if err != nil { + log.Fatalw("failed to build a ocr2.Client", "error", err) + } + + envelopeSourceFactory := monitoring.NewEnvelopeSourceFactory(ocr2Client) + txResultsFactory := monitoring.NewTxResultsSourceFactory(ocr2Client) + + monitor, err := relayMonitoring.NewMonitor( + ctx, + logger.With(log, "component", "monitor"), + starknetConfig, + envelopeSourceFactory, + txResultsFactory, + monitoring.StarknetFeedsParser, + monitoring.StarknetNodesParser, + ) + if err != nil { + log.Fatalw("failed to build monitor", "error", err) + return + } + + proxySourceFactory := monitoring.NewProxySourceFactory(ocr2Client) + monitor.SourceFactories = append(monitor.SourceFactories, proxySourceFactory) + + prometheusExporterFactory := monitoring.NewPrometheusExporterFactory( + monitoring.NewMetrics(logger.With(log, "component", "starknet-metrics")), + ) + monitor.ExporterFactories = append(monitor.ExporterFactories, prometheusExporterFactory) + + monitor.Run() + log.Info("monitor stopped") +} diff --git a/monitoring/go.mod b/monitoring/go.mod new file mode 100644 index 0000000..8a8796c --- /dev/null +++ b/monitoring/go.mod @@ -0,0 +1,71 @@ +module github.com/goplugin/plugin-starknet/monitoring + +go 1.20 + +require ( + github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac + github.com/dontpanicdao/caigo v0.4.0 + github.com/prometheus/client_golang v1.14.0 + github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82 + github.com/goplugin/plugin-starknet/relayer v0.0.0-20230412143414-b1e534d34592 + github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc + github.com/stretchr/testify v1.8.2 + go.uber.org/multierr v1.9.0 +) + +require ( + github.com/benbjohnson/clock v1.3.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/confluentinc/confluent-kafka-go v1.9.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/ethereum/go-ethereum v1.11.5 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/linkedin/goavro/v2 v2.12.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/riferrei/srclient v0.5.4 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 // indirect + github.com/satori/go.uuid v1.2.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.5.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.7.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace ( + // Fix go mod tidy issue for ambiguous imports from go-ethereum + // See https://github.com/ugorji/go/issues/279 + github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.1 + + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + + github.com/goplugin/plugin-starknet/relayer => ../relayer +) diff --git a/monitoring/go.sum b/monitoring/go.sum new file mode 100644 index 0000000..3e0b0b4 --- /dev/null +++ b/monitoring/go.sum @@ -0,0 +1,353 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac h1:TQ2m26VW06Df1P82Ed/jZhBtf13pReWyl2XQ8hy+J08= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac/go.mod h1:FTk2+xybtQe5X+oNFx+a0n5EeZMD9Nc+LCH4fxFwrEE= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/actgardner/gogen-avro/v10 v10.1.0/go.mod h1:o+ybmVjEa27AAr35FRqU98DJu1fXES56uXniYFv4yDA= +github.com/actgardner/gogen-avro/v10 v10.2.1/go.mod h1:QUhjeHPchheYmMDni/Nx7VB0RsT/ee8YIgGY/xpEQgQ= +github.com/actgardner/gogen-avro/v9 v9.1.0/go.mod h1:nyTj6wPqDJoxM3qdnjcLv+EnMDSDFqE0qDpva2QRmKc= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= +github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/confluentinc/confluent-kafka-go v1.9.2 h1:gV/GxhMBUb03tFWkN+7kdhg+zf+QUM+wVkI9zwh770Q= +github.com/confluentinc/confluent-kafka-go v1.9.2/go.mod h1:ptXNqsuDfYbAE/LBW6pnwWZElUoWxHoV8E43DCrliyo= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/dontpanicdao/caigo v0.4.0 h1:S0wRKh2EZ9qj6IfHZIGXxiJF37emRCqnZwDhRb1+DJ4= +github.com/dontpanicdao/caigo v0.4.0/go.mod h1:1YuwgcVLODaS/n0vfuYN/Q0mdWs8UDfDMkSpUdkKXD4= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.11.5 h1:3M1uan+LAUvdn+7wCEFrcMM4LJTeuxDrPTg/f31a5QQ= +github.com/ethereum/go-ethereum v1.11.5/go.mod h1:it7x0DWnTDMfVFdXcU6Ti4KEFQynLHVRarcSlPr0HBo= +github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= +github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= +github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= +github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20211008130755-947d60d73cc0/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hamba/avro v1.5.6/go.mod h1:3vNT0RLXXpFm2Tb/5KC71ZRJlOroggq1Rcitb6k4Fr8= +github.com/heetch/avro v0.3.1/go.mod h1:4xn38Oz/+hiEUTpbVfGVLfvOg0yKLlRP7Q9+gJJILgA= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/invopop/jsonschema v0.4.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= +github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= +github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/juju/qthttptest v0.1.1/go.mod h1:aTlAv8TYaflIiTDIQYzxnl1QdPjAg8Q8qJMErpKy6A4= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/linkedin/goavro v2.1.0+incompatible/go.mod h1:bBCwI2eGYpUI/4820s67MElg9tdeLbINjLjiM2xZFYM= +github.com/linkedin/goavro/v2 v2.9.7/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= +github.com/linkedin/goavro/v2 v2.10.0/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= +github.com/linkedin/goavro/v2 v2.10.1/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= +github.com/linkedin/goavro/v2 v2.11.1/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= +github.com/linkedin/goavro/v2 v2.12.0 h1:rIQQSj8jdAUlKQh6DttK8wCRv4t4QO09g1C4aBWXslg= +github.com/linkedin/goavro/v2 v2.12.0/go.mod h1:KXx+erlq+RPlGSPmLF7xGo6SAbh8sCQ53x064+ioxhk= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/nrwiersma/avro-benchmarks v0.0.0-20210913175520-21aec48c8f76/go.mod h1:iKyFMidsk/sVYONJRE372sJuX/QTRPacU7imPqqsu7g= +github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/riferrei/srclient v0.5.4 h1:dfwyR5u23QF7beuVl2WemUY2KXh5+Sc4DHKyPXBNYuc= +github.com/riferrei/srclient v0.5.4/go.mod h1:vbkLmWcgYa7JgfPvuy/+K8fTS0p1bApqadxrxi/S1MI= +github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a/go.mod h1:4r5QyqhjIWCcK8DO4KMclc5Iknq5qVBAlbYYzAbUScQ= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= +github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 h1:lEOLY2vyGIqKWUI9nzsOJRV3mb3WC9dXYORsLEUcoeY= +github.com/santhosh-tekuri/jsonschema/v5 v5.1.1/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82 h1:FX7LW/czuotFwzfK3UavL7HkKQv6fn/5wzcZASdKWQ0= +github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82/go.mod h1:3E3PXaMEl2gADk/DTkbOxsvtpDcJ5ZSyW+vt0TjsEH0= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc h1:aSCDAai0Dmbhp/KHTtJnC/EJcaEz4CAO80SKRzRZiQA= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc/go.mod h1:5JnCHuYgmIP9ZyXzgAfI5Iwu0WxBtBKp+ApeT5o1Cjw= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A= +github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220503193339-ba3ae3f07e29/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183/go.mod h1:FvqrFXt+jCsyQibeRv4xxEJBL5iG2DDW5aeJwzDiq4A= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v1 v1.0.0/go.mod h1:CxwszS/Xz1C49Ucd2i6Zil5UToP1EmyrFhKaMVbg1mk= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/httprequest.v1 v1.2.1/go.mod h1:x2Otw96yda5+8+6ZeWwHIJTFkEHWP/qP8pJOzqEtWPM= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/retry.v1 v1.0.3/go.mod h1:FJkXmWiMaAo7xB+xhvDF59zhfjDWyzmyAxiT4dB688g= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/monitoring/ops/Dockerfile b/monitoring/ops/Dockerfile new file mode 100644 index 0000000..2b9dbdf --- /dev/null +++ b/monitoring/ops/Dockerfile @@ -0,0 +1,29 @@ +# Build image + +FROM golang:1.20-buster as build + +# Copy source + +RUN mkdir -p /starknet-monitoring/cmd +COPY ./cmd/monitoring /starknet-monitoring/cmd/monitoring +COPY ./pkg /starknet-monitoring/pkg +COPY ./go.mod /starknet-monitoring/ +COPY ./go.sum /starknet-monitoring/ + +# Compile binary + +WORKDIR /starknet-monitoring +RUN go build -o ./monitoring ./cmd/monitoring/*.go + +# Production image + +FROM ubuntu:20.04 + +RUN apt-get update && apt-get install -y ca-certificates +COPY --from=build /starknet-monitoring/monitoring /monitoring + +# Expose prometheus default port +EXPOSE 9090/tcp + +ENTRYPOINT ["/monitoring"] +CMD ["--help"] diff --git a/monitoring/ops/docker-compose.yml b/monitoring/ops/docker-compose.yml new file mode 100644 index 0000000..62a57b1 --- /dev/null +++ b/monitoring/ops/docker-compose.yml @@ -0,0 +1,49 @@ +--- +version: '3' +services: + zookeeper: + image: confluentinc/cp-zookeeper:6.2.1 + hostname: zookeeper + container_name: zookeeper + ports: + - "2181:2181" + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + + kafka: + image: confluentinc/cp-kafka:6.2.1 + hostname: kafka + container_name: kafka + depends_on: + - zookeeper + ports: + - "29092:29092" + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092 + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 + KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 + KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 + KAFKA_SOCKET_REQUEST_MAX_BYTES: 80001200 + KAFKA_MESSAGE_MAX_BYTES: 80001200 + KAFKA_CFG_MAX_REQUEST_SIZE: 80001200 + + schema-registry: + image: confluentinc/cp-schema-registry:6.2.1 + hostname: schema-registry + container_name: schema-registry + depends_on: + - zookeeper + - kafka + ports: + - "8989:8989" + environment: + SCHEMA_REGISTRY_HOST_NAME: schema-registry + SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: 'zookeeper:2181' + SCHEMA_REGISTRY_DEBUG: 'true' + SCHEMA_REGISTRY_LISTENERS: 'http://schema-registry:8989' + SCHEMA_REGISTRY_SCHEMA_COMPATIBILITY_LEVEL: 'full_transitive' diff --git a/monitoring/pkg/monitoring/config_chain.go b/monitoring/pkg/monitoring/config_chain.go new file mode 100644 index 0000000..355ce3c --- /dev/null +++ b/monitoring/pkg/monitoring/config_chain.go @@ -0,0 +1,117 @@ +package monitoring + +import ( + "fmt" + "net/url" + "os" + "time" + + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" +) + +type StarknetConfig struct { + rpcEndpoint string + networkName string + networkID string + chainID string + readTimeout time.Duration + pollInterval time.Duration + linkTokenAddress string +} + +var _ relayMonitoring.ChainConfig = StarknetConfig{} + +func (s StarknetConfig) GetRPCEndpoint() string { return s.rpcEndpoint } +func (s StarknetConfig) GetNetworkName() string { return s.networkName } +func (s StarknetConfig) GetNetworkID() string { return s.networkID } +func (s StarknetConfig) GetChainID() string { return s.chainID } +func (s StarknetConfig) GetReadTimeout() time.Duration { return s.readTimeout } +func (s StarknetConfig) GetPollInterval() time.Duration { return s.pollInterval } +func (s StarknetConfig) GetLinkTokenAddress() string { return s.linkTokenAddress } + +func (s StarknetConfig) ToMapping() map[string]interface{} { + return map[string]interface{}{ + "network_name": s.networkName, + "network_id": s.networkID, + "chain_id": s.chainID, + } +} + +func ParseStarknetConfig() (StarknetConfig, error) { + cfg := StarknetConfig{} + + if err := parseEnvVars(&cfg); err != nil { + return cfg, err + } + + applyDefaults(&cfg) + + err := validateConfig(cfg) + return cfg, err +} + +func parseEnvVars(cfg *StarknetConfig) error { + if value, isPresent := os.LookupEnv("STARKNET_RPC_ENDPOINT"); isPresent { + cfg.rpcEndpoint = value + } + if value, isPresent := os.LookupEnv("STARKNET_NETWORK_NAME"); isPresent { + cfg.networkName = value + } + if value, isPresent := os.LookupEnv("STARKNET_NETWORK_ID"); isPresent { + cfg.networkID = value + } + if value, isPresent := os.LookupEnv("STARKNET_CHAIN_ID"); isPresent { + cfg.chainID = value + } + if value, isPresent := os.LookupEnv("STARKNET_READ_TIMEOUT"); isPresent { + readTimeout, err := time.ParseDuration(value) + if err != nil { + return fmt.Errorf("failed to parse env var STARKNET_READ_TIMEOUT, see https://pkg.go.dev/time#ParseDuration: %w", err) + } + cfg.readTimeout = readTimeout + } + if value, isPresent := os.LookupEnv("STARKNET_POLL_INTERVAL"); isPresent { + pollInterval, err := time.ParseDuration(value) + if err != nil { + return fmt.Errorf("failed to parse env var STARKNET_POLL_INTERVAL, see https://pkg.go.dev/time#ParseDuration: %w", err) + } + cfg.pollInterval = pollInterval + } + if value, isPresent := os.LookupEnv("STARKNET_PLI_TOKEN_ADDRESS"); isPresent { + cfg.linkTokenAddress = value + } + return nil +} + +func validateConfig(cfg StarknetConfig) error { + // Required config + for envVarName, currentValue := range map[string]string{ + "STARKNET_RPC_ENDPOINT": cfg.rpcEndpoint, + "STARKNET_NETWORK_NAME": cfg.networkName, + "STARKNET_NETWORK_ID": cfg.networkID, + "STARKNET_CHAIN_ID": cfg.chainID, + "STARKNET_PLI_TOKEN_ADDRESS": cfg.linkTokenAddress, + } { + if currentValue == "" { + return fmt.Errorf("'%s' env var is required", envVarName) + } + } + // Validate URLs. + for envVarName, currentValue := range map[string]string{ + "STARKNET_RPC_ENDPOINT": cfg.rpcEndpoint, + } { + if _, err := url.ParseRequestURI(currentValue); err != nil { + return fmt.Errorf("%s='%s' is not a valid URL: %w", envVarName, currentValue, err) + } + } + return nil +} + +func applyDefaults(cfg *StarknetConfig) { + if cfg.readTimeout == 0 { + cfg.readTimeout = 2 * time.Second + } + if cfg.pollInterval == 0 { + cfg.pollInterval = 5 * time.Second + } +} diff --git a/monitoring/pkg/monitoring/config_feed.go b/monitoring/pkg/monitoring/config_feed.go new file mode 100644 index 0000000..2d58532 --- /dev/null +++ b/monitoring/pkg/monitoring/config_feed.go @@ -0,0 +1,110 @@ +package monitoring + +import ( + "encoding/json" + "fmt" + "io" + "math/big" + + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" +) + +type StarknetFeedConfig struct { + Name string `json:"name,omitempty"` + Path string `json:"path,omitempty"` + Symbol string `json:"symbol,omitempty"` + HeartbeatSec int64 `json:"heartbeat,omitempty"` + ContractType string `json:"contract_type,omitempty"` + ContractStatus string `json:"status,omitempty"` + MultiplyRaw string `json:"multiply,omitempty"` + Multiply *big.Int `json:"-"` + + ContractAddress string `json:"contract_address,omitempty"` + ProxyAddress string `json:"proxy_address,omitempty"` +} + +var _ relayMonitoring.FeedConfig = StarknetFeedConfig{} + +// GetID returns the state account's address as that uniquely +// identifies a feed on Starknet. In Starknet, a program is stateless and we +// use the same program for all feeds so we can't use the program +// account's address. +func (s StarknetFeedConfig) GetID() string { + return s.ContractAddress +} + +func (s StarknetFeedConfig) GetName() string { + return s.Name +} + +func (s StarknetFeedConfig) GetPath() string { + return s.Path +} + +func (s StarknetFeedConfig) GetFeedPath() string { + return s.Path +} + +func (s StarknetFeedConfig) GetSymbol() string { + return s.Symbol +} + +func (s StarknetFeedConfig) GetHeartbeatSec() int64 { + return s.HeartbeatSec +} + +func (s StarknetFeedConfig) GetContractType() string { + return s.ContractType +} + +func (s StarknetFeedConfig) GetContractStatus() string { + return s.ContractStatus +} + +func (s StarknetFeedConfig) GetMultiply() *big.Int { + return s.Multiply +} + +func (s StarknetFeedConfig) GetContractAddress() string { + return s.ContractAddress +} + +func (s StarknetFeedConfig) GetContractAddressBytes() []byte { + return []byte(s.ContractAddress) +} + +func (s StarknetFeedConfig) ToMapping() map[string]interface{} { + return map[string]interface{}{ + "feed_name": s.Name, + "feed_path": s.Path, + "symbol": s.Symbol, + "heartbeat_sec": int64(s.HeartbeatSec), + "contract_type": s.ContractType, + "contract_status": s.ContractStatus, + "contract_address": []byte(s.ContractAddress), + + // These fields are legacy. They are required in the schema but they + // should be set to a zero value for any other chain. + "transmissions_account": []byte{}, + "state_account": []byte{}, + } +} + +func StarknetFeedsParser(buf io.ReadCloser) ([]relayMonitoring.FeedConfig, error) { + rawFeeds := []StarknetFeedConfig{} + decoder := json.NewDecoder(buf) + if err := decoder.Decode(&rawFeeds); err != nil { + return nil, fmt.Errorf("unable to unmarshal feeds config data: %w", err) + } + feeds := make([]relayMonitoring.FeedConfig, len(rawFeeds)) + for i, rawFeed := range rawFeeds { + multiply, ok := new(big.Int).SetString(rawFeed.MultiplyRaw, 10) + if !ok { + return nil, fmt.Errorf("failed to parse multiply '%s' into a big.Int", rawFeed.MultiplyRaw) + } + // NOTE: multiply is not required so if a parse error occurs, we'll use 0. + rawFeed.Multiply = multiply + feeds[i] = relayMonitoring.FeedConfig(rawFeed) + } + return feeds, nil +} diff --git a/monitoring/pkg/monitoring/config_node.go b/monitoring/pkg/monitoring/config_node.go new file mode 100644 index 0000000..4adc1c4 --- /dev/null +++ b/monitoring/pkg/monitoring/config_node.go @@ -0,0 +1,40 @@ +package monitoring + +import ( + "encoding/json" + "fmt" + "io" + + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +type StarknetNodeConfig struct { + ID string `json:"id,omitempty"` + NodeAddress []string `json:"nodeAddress,omitempty"` +} + +func (s StarknetNodeConfig) GetName() string { + return s.ID +} + +func (s StarknetNodeConfig) GetAccount() types.Account { + address := "" + if len(s.NodeAddress) != 0 { + address = s.NodeAddress[0] + } + return types.Account(address) +} + +func StarknetNodesParser(buf io.ReadCloser) ([]relayMonitoring.NodeConfig, error) { + rawNodes := []StarknetNodeConfig{} + decoder := json.NewDecoder(buf) + if err := decoder.Decode(&rawNodes); err != nil { + return nil, fmt.Errorf("unable to unmarshal nodes config data: %w", err) + } + nodes := make([]relayMonitoring.NodeConfig, len(rawNodes)) + for i, rawNode := range rawNodes { + nodes[i] = rawNode + } + return nodes, nil +} diff --git a/monitoring/pkg/monitoring/exporter_prometheus.go b/monitoring/pkg/monitoring/exporter_prometheus.go new file mode 100644 index 0000000..168d090 --- /dev/null +++ b/monitoring/pkg/monitoring/exporter_prometheus.go @@ -0,0 +1,103 @@ +package monitoring + +import ( + "context" + "fmt" + "sync" + + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" +) + +// NewPrometheusExporterFactory builds an implementation of the Exporter for prometheus. +func NewPrometheusExporterFactory( + metrics Metrics, +) relayMonitoring.ExporterFactory { + return &prometheusExporterFactory{ + metrics, + } +} + +type prometheusExporterFactory struct { + metrics Metrics +} + +func (p *prometheusExporterFactory) NewExporter( + params relayMonitoring.ExporterParams, +) (relayMonitoring.Exporter, error) { + starknetFeedConfig, ok := params.FeedConfig.(StarknetFeedConfig) + if !ok { + return nil, fmt.Errorf("expected feedConfig to be of type StarknetFeedConfig not %T", params.FeedConfig) + } + return &prometheusExporter{ + params.ChainConfig, + starknetFeedConfig, + p.metrics, + sync.Mutex{}, + map[string]struct{}{}, + }, nil +} + +type prometheusExporter struct { + chainConfig relayMonitoring.ChainConfig + feedConfig StarknetFeedConfig + metrics Metrics + addressesMu sync.Mutex + addressesSet map[string]struct{} +} + +func (p *prometheusExporter) Export(ctx context.Context, data interface{}) { + proxyData, isProxyData := data.(ProxyData) + if !isProxyData { + return + } + answer := float64(proxyData.Answer.Uint64()) + multiply := float64(p.feedConfig.Multiply.Uint64()) + if multiply == 0 { + multiply = 1.0 + } + p.metrics.SetProxyAnswersRaw( + answer, + p.feedConfig.ProxyAddress, + p.feedConfig.GetID(), + p.chainConfig.GetChainID(), + p.feedConfig.GetContractStatus(), + p.feedConfig.GetContractType(), + p.feedConfig.GetName(), + p.feedConfig.GetPath(), + p.chainConfig.GetNetworkID(), + p.chainConfig.GetNetworkName(), + ) + p.metrics.SetProxyAnswers( + answer/multiply, + p.feedConfig.ProxyAddress, + p.feedConfig.GetID(), + p.chainConfig.GetChainID(), + p.feedConfig.GetContractStatus(), + p.feedConfig.GetContractType(), + p.feedConfig.GetName(), + p.feedConfig.GetPath(), + p.chainConfig.GetNetworkID(), + p.chainConfig.GetNetworkName(), + ) + p.addressesMu.Lock() + defer p.addressesMu.Unlock() + p.addressesSet[p.feedConfig.ProxyAddress] = struct{}{} +} + +func (p *prometheusExporter) Cleanup(_ context.Context) { + p.addressesMu.Lock() + defer p.addressesMu.Unlock() + for address := range p.addressesSet { + p.metrics.Cleanup( + address, + p.feedConfig.GetContractAddress(), + p.chainConfig.GetChainID(), + p.feedConfig.GetContractStatus(), + p.feedConfig.GetContractType(), + p.feedConfig.GetName(), + p.feedConfig.GetPath(), + p.chainConfig.GetNetworkID(), + p.chainConfig.GetNetworkName(), + ) + } +} diff --git a/monitoring/pkg/monitoring/metrics.go b/monitoring/pkg/monitoring/metrics.go new file mode 100644 index 0000000..74d20bc --- /dev/null +++ b/monitoring/pkg/monitoring/metrics.go @@ -0,0 +1,91 @@ +package monitoring + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" +) + +// Metrics is an interface for prometheus metrics. Makes testing easier. +type Metrics interface { + SetProxyAnswersRaw(answer float64, proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string) + SetProxyAnswers(answer float64, proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string) + Cleanup(proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string) +} + +var ( + proxyAnswersRaw = promauto.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "proxy_answers_raw", + Help: "Reports the latest raw answer from the proxy contract.", + }, + []string{"proxy_contract_address", "feed_id", "chain_id", "contract_status", "contract_type", "feed_name", "feed_path", "network_id", "network_name"}, + ) + proxyAnswers = promauto.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "proxy_answers", + Help: "Reports the latest answer from the proxy contract divided by the feed's multiplier parameter.", + }, + []string{"proxy_contract_address", "feed_id", "chain_id", "contract_status", "contract_type", "feed_name", "feed_path", "network_id", "network_name"}, + ) +) + +// NewMetrics does wisott +func NewMetrics(log relayMonitoring.Logger) Metrics { + return &defaultMetrics{log} +} + +type defaultMetrics struct { + log relayMonitoring.Logger +} + +func (d *defaultMetrics) SetProxyAnswersRaw(answer float64, proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string) { + proxyAnswersRaw.With(prometheus.Labels{ + "proxy_contract_address": proxyContractAddress, + "feed_id": feedID, + "chain_id": chainID, + "contract_status": contractStatus, + "contract_type": contractType, + "feed_name": feedName, + "feed_path": feedPath, + "network_id": networkID, + "network_name": networkName, + }).Set(answer) +} + +func (d *defaultMetrics) SetProxyAnswers(answer float64, proxyContractAddress, feedID, chainID, contractStatus, contractType, feedName, feedPath, networkID, networkName string) { + proxyAnswers.With(prometheus.Labels{ + "proxy_contract_address": proxyContractAddress, + "feed_id": feedID, + "chain_id": chainID, + "contract_status": contractStatus, + "contract_type": contractType, + "feed_name": feedName, + "feed_path": feedPath, + "network_id": networkID, + "network_name": networkName, + }).Set(answer) +} + +func (d *defaultMetrics) Cleanup( + proxyContractAddress, feedID, chainID, contractStatus, contractType string, + feedName, feedPath, networkID, networkName string, +) { + labels := prometheus.Labels{ + "proxy_contract_address": proxyContractAddress, + "feed_id": feedID, + "chain_id": chainID, + "contract_status": contractStatus, + "contract_type": contractType, + "feed_name": feedName, + "feed_path": feedPath, + "network_id": networkID, + "network_name": networkName, + } + if !proxyAnswersRaw.Delete(labels) { + d.log.Errorw("failed to delete metric", "name", "proxy_answers_raw", "labels", labels) + } + if !proxyAnswers.Delete(labels) { + d.log.Errorw("failed to delete metric", "name", "proxy_answers", "labels", labels) + } +} diff --git a/monitoring/pkg/monitoring/source_envelope.go b/monitoring/pkg/monitoring/source_envelope.go new file mode 100644 index 0000000..090ae6e --- /dev/null +++ b/monitoring/pkg/monitoring/source_envelope.go @@ -0,0 +1,180 @@ +package monitoring + +import ( + "context" + "fmt" + "math/big" + "sync" + + junotypes "github.com/NethermindEth/juno/pkg/types" + "github.com/dontpanicdao/caigo" + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" + relayUtils "github.com/goplugin/plugin-relay/pkg/utils" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + "go.uber.org/multierr" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +func NewEnvelopeSourceFactory( + ocr2Reader ocr2.OCR2Reader, +) relayMonitoring.SourceFactory { + return &envelopeSourceFactory{ + ocr2Reader, + } +} + +type envelopeSourceFactory struct { + ocr2Reader ocr2.OCR2Reader +} + +func (s *envelopeSourceFactory) NewSource( + chainConfig relayMonitoring.ChainConfig, + feedConfig relayMonitoring.FeedConfig, +) (relayMonitoring.Source, error) { + starknetChainConfig, ok := chainConfig.(StarknetConfig) + if !ok { + return nil, fmt.Errorf("expected feedConfig to be of type StarknetFeedConfig not %T", feedConfig) + } + return &envelopeSource{ + feedConfig.GetContractAddress(), + starknetChainConfig.GetLinkTokenAddress(), + s.ocr2Reader, + }, nil +} + +func (s *envelopeSourceFactory) GetType() string { + return "envelope" +} + +type envelopeSource struct { + contractAddress string + linkTokenAddress string + ocr2Reader ocr2.OCR2Reader +} + +func (s *envelopeSource) Fetch(ctx context.Context) (interface{}, error) { + envelope := relayMonitoring.Envelope{} + var envelopeMu sync.Mutex + var envelopeErr error + subs := &relayUtils.Subprocesses{} + + subs.Go(func() { + latestRoundData, newTransmissionEvent, err := s.fetchLatestNewTransmissionEvent(ctx, s.contractAddress) + envelopeMu.Lock() + defer envelopeMu.Unlock() + if err != nil { + envelopeErr = multierr.Combine(envelopeErr, fmt.Errorf("fetchLatestNewTransmissionEvent failed: %w", err)) + return + } + envelope.BlockNumber = latestRoundData.BlockNumber + if newTransmissionEvent.Transmitter != nil { + envelope.Transmitter = types.Account(newTransmissionEvent.Transmitter.String()) + } + envelope.AggregatorRoundID = latestRoundData.RoundID + envelope.ConfigDigest = newTransmissionEvent.ConfigDigest + envelope.Epoch = newTransmissionEvent.Epoch + envelope.Round = newTransmissionEvent.Round + envelope.LatestAnswer = newTransmissionEvent.LatestAnswer + envelope.LatestTimestamp = newTransmissionEvent.LatestTimestamp + envelope.JuelsPerFeeCoin = newTransmissionEvent.JuelsPerFeeCoin + }) + + subs.Go(func() { + contractConfig, err := s.fetchContractConfig(ctx, s.contractAddress) + envelopeMu.Lock() + defer envelopeMu.Unlock() + if err != nil { + envelopeErr = multierr.Combine(envelopeErr, fmt.Errorf("fetchContractConfig failed: %w", err)) + return + } + envelope.ContractConfig = contractConfig.Config + }) + + subs.Go(func() { + availableLink, err := s.ocr2Reader.LinkAvailableForPayment(ctx, s.contractAddress) + envelopeMu.Lock() + defer envelopeMu.Unlock() + if err != nil { + envelopeErr = multierr.Combine(envelopeErr, fmt.Errorf("fetch LinkAvailableForPayment failed: %w", err)) + return + } + envelope.LinkAvailableForPayment = availableLink + }) + + subs.Go(func() { + balance, err := s.fetchLinkBalance(ctx, s.linkTokenAddress, s.contractAddress) + envelopeMu.Lock() + defer envelopeMu.Unlock() + if err != nil { + envelopeErr = multierr.Combine(envelopeErr, fmt.Errorf("fetchLinkBalance failed: %w", err)) + return + } + envelope.LinkBalance = balance + }) + + subs.Wait() + return envelope, envelopeErr +} + +func (s *envelopeSource) fetchLatestNewTransmissionEvent(ctx context.Context, contractAddress string) ( + latestRound ocr2.RoundData, + transmission ocr2.NewTransmissionEvent, + err error, +) { + latestRound, err = s.ocr2Reader.LatestRoundData(ctx, contractAddress) + if err != nil { + return latestRound, transmission, fmt.Errorf("failed to fetch latest_round_data: %w", err) + } + transmissions, err := s.ocr2Reader.NewTransmissionsFromEventsAt(ctx, contractAddress, latestRound.BlockNumber) + if err != nil { + return latestRound, transmission, fmt.Errorf("failed to fetch new_transmission events: %w", err) + } + if len(transmissions) == 0 { + // NOTE This shouldn't happen! LatestRound says this block should have a transmission and we didn't find any! + return latestRound, transmission, fmt.Errorf("no transmissions found in the block %d", latestRound.BlockNumber) + } + for _, transmission = range transmissions { + if transmission.RoundId == latestRound.RoundID { + return latestRound, transmission, nil + } + } + // NOTE! This also shouldn't happen! We found transmissions in the block suggested by LatestRound but they have a different round id! + return latestRound, transmission, fmt.Errorf("no new_trasmission event found to correspond with the round id %d in block %d", latestRound.RoundID, latestRound.BlockNumber) +} + +func (s *envelopeSource) fetchContractConfig(ctx context.Context, contractAddress string) (config ocr2.ContractConfig, err error) { + configDetails, err := s.ocr2Reader.LatestConfigDetails(ctx, contractAddress) + if err != nil { + return config, fmt.Errorf("couldn't fetch latest config details for contract '%s': %w", contractAddress, err) + } + config, err = s.ocr2Reader.ConfigFromEventAt(ctx, contractAddress, configDetails.Block) + if err != nil { + return config, fmt.Errorf("couldn't fetch config at block '%d' for contract '%s': %w", configDetails.Block, contractAddress, err) + } + return config, nil +} + +var zeroBigInt = big.NewInt(0) + +func (s *envelopeSource) fetchLinkBalance(ctx context.Context, linkTokenAddress, contractAddress string) (*big.Int, error) { + results, err := s.ocr2Reader.BaseReader().CallContract(ctx, starknet.CallOps{ + ContractAddress: linkTokenAddress, + Selector: "balanceOf", + Calldata: []string{ + caigo.HexToBN(contractAddress).String(), + }, + }) + if err != nil { + return nil, fmt.Errorf("failed call to ECR20 contract, balanceOf method: %w", err) + } + if len(results) < 1 { + return nil, fmt.Errorf("insufficient data from balanceOf '%v': %w", results, err) + } + linkBalance := junotypes.HexToFelt(results[0]).Big() + if linkBalance.Cmp(zeroBigInt) == 0 { + return nil, fmt.Errorf("contract's PLI balance should not be zero") + } + return linkBalance, nil +} diff --git a/monitoring/pkg/monitoring/source_envelope_test.go b/monitoring/pkg/monitoring/source_envelope_test.go new file mode 100644 index 0000000..9b14773 --- /dev/null +++ b/monitoring/pkg/monitoring/source_envelope_test.go @@ -0,0 +1,185 @@ +package monitoring + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/dontpanicdao/caigo" + caigotypes "github.com/dontpanicdao/caigo/types" + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + + ocr2Mocks "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/mocks" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + starknetMocks "github.com/goplugin/plugin-starknet/relayer/pkg/starknet/mocks" +) + +func TestEnvelopeSource(t *testing.T) { + // This test makes sure that the mapping between the response from the ocr2.Client + // method calls and the output of the Envelope source is correct. + + chainConfig := generateChainConfig() + feedConfig := generateFeedConfig() + + ocr2Reader := ocr2Mocks.NewOCR2Reader(t) + ocr2Reader.On( + "LatestRoundData", + mock.Anything, // ctx + feedConfig.ContractAddress, + ).Return(ocr2ClientLatestRoundDataResponse, nil).Once() + ocr2Reader.On( + "NewTransmissionsFromEventsAt", + mock.Anything, // ctx + feedConfig.ContractAddress, + ocr2ClientLatestRoundDataResponse.BlockNumber, + ).Return(ocr2ClientNewTransmissionEventAtResponse, nil).Once() + ocr2Reader.On( + "LatestConfigDetails", + mock.Anything, // ctx + feedConfig.ContractAddress, + ).Return(ocr2ClientLatestConfigDetailsResponse, nil).Once() + ocr2Reader.On( + "ConfigFromEventAt", + mock.Anything, // ctx + feedConfig.ContractAddress, + ocr2ClientLatestConfigDetailsResponse.Block, + ).Return(ocr2ClientConfigFromEventAtResponse, nil).Once() + ocr2Reader.On( + "LinkAvailableForPayment", + mock.Anything, // ctx + feedConfig.ContractAddress, + ).Return(ocr2ClientLinkAvailableForPaymentResponse, nil).Once() + + baseReader := starknetMocks.NewReader(t) + ocr2Reader.On("BaseReader").Return(baseReader) + baseReader.On( + "CallContract", + mock.Anything, // ctx + starknet.CallOps{ + ContractAddress: chainConfig.GetLinkTokenAddress(), + Selector: "balanceOf", + Calldata: []string{ + caigo.HexToBN(feedConfig.ContractAddress).String(), + }, + }, + ).Return(starknetReaderCallContractBalanceOfResponse, nil) + + factory := NewEnvelopeSourceFactory(ocr2Reader) + source, err := factory.NewSource(chainConfig, feedConfig) + require.NoError(t, err) + rawEnvelope, err := source.Fetch(context.Background()) + require.NoError(t, err) + envelope, ok := rawEnvelope.(relayMonitoring.Envelope) + require.True(t, ok) + + require.Equal(t, expectedEnvelope, envelope) +} + +var ( + ocr2ClientLatestRoundDataResponse = ocr2.RoundData{ + RoundID: 0xf5b, + Answer: bigIntFromString("3618502788666131213697322783095070105623107215331596699973092056134972020481"), + BlockNumber: 0xe07, + StartedAt: time.Date(2022, time.September, 27, 18, 50, 0, 0, time.Local), + UpdatedAt: time.Date(2022, time.September, 27, 18, 51, 0, 0, time.Local), + } + ocr2ClientNewTransmissionEventAtResponse = []ocr2.NewTransmissionEvent{ + { + RoundId: 0xf5b, + LatestAnswer: bigIntFromString("-900000000"), + Transmitter: caigotypes.StrToFelt("634447934223750826572902672583054702307815157196919304685470566142330202833"), + LatestTimestamp: time.Date(2022, time.September, 27, 18, 51, 0, 0, time.Local), + Observers: []uint8{0x1, 0x2, 0x3, 0x4}, + ObservationsLen: 0x4, + Observations: []*big.Int{ + bigIntFromString("3618502788666131213697322783095070105623107215331596699973092056134972020481"), + bigIntFromString("3618502788666131213697322783095070105623107215331596699973092056134972020481"), + bigIntFromString("3618502788666131213697322783095070105623107215331596699973092056134972020481"), + bigIntFromString("3618502788666131213697322783095070105623107215331596699973092056134972020481"), + }, + JuelsPerFeeCoin: big.NewInt(451000), + GasPrice: big.NewInt(1), + ConfigDigest: types.ConfigDigest{0x0, 0x4, 0x18, 0xe5, 0x44, 0xab, 0xa8, 0x18, 0x15, 0xa5, 0x2b, 0xf0, 0x11, 0x58, 0xc6, 0x9b, 0x38, 0x8a, 0x48, 0x9f, 0x76, 0xd, 0xd8, 0x3d, 0x84, 0x3f, 0x1d, 0x31, 0x22, 0xdb, 0x78, 0xa}, + Epoch: 0x519, + Round: 0x5, + Reimbursement: big.NewInt(0), + }, + } + ocr2ClientLatestConfigDetailsResponse = ocr2.ContractConfigDetails{ + Block: 0x11, + Digest: types.ConfigDigest{0x0, 0x4, 0x18, 0xe5, 0x44, 0xab, 0xa8, 0x18, 0x15, 0xa5, 0x2b, 0xf0, 0x11, 0x58, 0xc6, 0x9b, 0x38, 0x8a, 0x48, 0x9f, 0x76, 0xd, 0xd8, 0x3d, 0x84, 0x3f, 0x1d, 0x31, 0x22, 0xdb, 0x78, 0xa}, + } + ocr2ClientConfigFromEventAtResponse = ocr2.ContractConfig{ + Config: types.ContractConfig{ + ConfigDigest: types.ConfigDigest{0x0, 0x4, 0x18, 0xe5, 0x44, 0xab, 0xa8, 0x18, 0x15, 0xa5, 0x2b, 0xf0, 0x11, 0x58, 0xc6, 0x9b, 0x38, 0x8a, 0x48, 0x9f, 0x76, 0xd, 0xd8, 0x3d, 0x84, 0x3f, 0x1d, 0x31, 0x22, 0xdb, 0x78, 0xa}, + ConfigCount: 0x1, + Signers: []types.OnchainPublicKey{ + types.OnchainPublicKey{0x6, 0x43, 0x41, 0xfa, 0xc3, 0x1, 0xc6, 0x2c, 0x38, 0xa9, 0xef, 0xdb, 0x86, 0xf6, 0xa2, 0x5a, 0x34, 0xd2, 0x4, 0x4f, 0x29, 0x2e, 0x94, 0xfb, 0xe4, 0x78, 0xa6, 0x67, 0x19, 0xb3, 0x80, 0x9e}, + types.OnchainPublicKey{0x1, 0xe2, 0xe1, 0x45, 0x47, 0x3, 0x7d, 0xb0, 0xd2, 0xe, 0xc6, 0xc9, 0x4b, 0xc7, 0x91, 0xea, 0xf2, 0xc9, 0x98, 0xad, 0x92, 0x79, 0xbb, 0xd, 0x21, 0x80, 0x15, 0x14, 0xd0, 0x6f, 0xa5, 0x7e}, + types.OnchainPublicKey{0x3, 0xb6, 0xcb, 0xd7, 0xbd, 0x52, 0x2d, 0xc8, 0xb0, 0xb4, 0x15, 0x3d, 0x60, 0x44, 0xec, 0xa7, 0x7e, 0x3e, 0xcf, 0xde, 0xe0, 0xc9, 0x5d, 0x20, 0x75, 0x50, 0x61, 0xf4, 0xbc, 0x7b, 0xf5, 0x4d}, + types.OnchainPublicKey{0x2, 0x4a, 0xa1, 0x21, 0x5b, 0xf4, 0xa3, 0xbb, 0x13, 0xea, 0x19, 0x57, 0x74, 0x28, 0xb7, 0xbe, 0xb5, 0xb9, 0x28, 0xb5, 0x74, 0x96, 0x78, 0xfa, 0x46, 0x87, 0x3b, 0x62, 0x7b, 0x22, 0x2a, 0x14}, + types.OnchainPublicKey{0x2, 0xa9, 0xc8, 0x4f, 0x88, 0x14, 0x17, 0xb5, 0xc9, 0xd1, 0x3b, 0x80, 0x2a, 0xc9, 0x93, 0xc5, 0x2c, 0x82, 0x88, 0x62, 0x32, 0xf7, 0x4e, 0x47, 0x5a, 0x92, 0xcc, 0x1a, 0xa, 0x1, 0x10, 0xda}, + }, + Transmitters: []types.Account{ + "0x033c95af529827a2372743bfc820b4d0bd08605fda5e089d1a7ad3a33caa48fc", + "0x05e457e084ff8e7279985ffb7ad7a65a6adfa8485e7d5d615c015268d5aa9971", + "0x0692a71d868ee9fc22091d8f73c16dabaf9219fa74c4bcc7d385f398949ba8d2", + "0x01232b74b82e490f373453baebe7e217cc6d33d798824a04f8274fa83bc2acd4", + "0x016715b5cc943835f196b7caf5a8aeb0e85b3f975dc43c14c90d0376e87eead1", + }, + F: 0x1, + OnchainConfig: []uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xb7, 0x89, 0x18, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0x48, 0x76, 0xe8, 0x0}, + OffchainConfigVersion: 0x2, + OffchainConfig: []uint8{0x8, 0x80, 0xa0, 0xd9, 0xe6, 0x1d, 0x10, 0x80, 0xd8, 0x8e, 0xe1, 0x6f, 0x18, 0x80, 0xbc, 0xc1, 0x96, 0xb, 0x20, 0x80, 0xca, 0xb5, 0xee, 0x1, 0x28, 0x80, 0x90, 0xdf, 0xc0, 0x4a, 0x30, 0x5, 0x3a, 0x2, 0x1, 0x2, 0x42, 0x20, 0xe9, 0x4f, 0x24, 0x4a, 0xcd, 0x86, 0x7d, 0xa5, 0x72, 0x54, 0x35, 0x57, 0x82, 0xb7, 0x1d, 0xb4, 0x50, 0x83, 0xd3, 0x67, 0xa7, 0xef, 0x23, 0x71, 0x5e, 0xb5, 0xce, 0x64, 0x38, 0xdf, 0x16, 0x1b, 0x42, 0x20, 0x34, 0xb6, 0xb5, 0xd, 0x9a, 0x47, 0xa2, 0x25, 0xe7, 0x91, 0xb3, 0x67, 0x7a, 0x1e, 0xd, 0x12, 0x2b, 0xa0, 0xc, 0xe9, 0x60, 0xd3, 0x7c, 0x76, 0x46, 0xec, 0x84, 0xcd, 0xd6, 0xfa, 0x9c, 0x48, 0x42, 0x20, 0x6a, 0xbc, 0xb4, 0x9d, 0xc7, 0xf4, 0xa9, 0x2f, 0xc4, 0x50, 0x89, 0x82, 0xa8, 0xa, 0xc1, 0x54, 0x23, 0x79, 0x8a, 0x2d, 0xe, 0x47, 0x1e, 0x95, 0xf4, 0x1e, 0x30, 0xeb, 0x68, 0x85, 0x29, 0xa6, 0x42, 0x20, 0x9b, 0xab, 0xa6, 0x36, 0x27, 0xbf, 0xa5, 0x31, 0x26, 0x9f, 0x32, 0x40, 0xb4, 0xc4, 0xe9, 0x8e, 0x86, 0xbc, 0xd5, 0x99, 0x83, 0xc5, 0x27, 0x31, 0x5f, 0x7a, 0xd1, 0x2f, 0x51, 0x5d, 0xd8, 0xfc, 0x42, 0x20, 0x72, 0xd7, 0x97, 0xfe, 0x3c, 0x8, 0xd8, 0x97, 0xfe, 0xe8, 0xdd, 0xa3, 0xa9, 0x40, 0x66, 0xa3, 0x4d, 0xa7, 0x27, 0x81, 0x4f, 0xf, 0x1f, 0x6c, 0x72, 0x22, 0xba, 0xdc, 0x52, 0x18, 0xcf, 0xb2, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x45, 0x7a, 0x66, 0x67, 0x38, 0x70, 0x32, 0x71, 0x58, 0x42, 0x38, 0x74, 0x77, 0x37, 0x6b, 0x42, 0x59, 0x72, 0x76, 0x75, 0x4d, 0x6e, 0x75, 0x47, 0x70, 0x66, 0x75, 0x79, 0x71, 0x59, 0x67, 0x4a, 0x50, 0x76, 0x78, 0x70, 0x77, 0x69, 0x62, 0x73, 0x50, 0x68, 0x67, 0x5a, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x4c, 0x5a, 0x4a, 0x58, 0x71, 0x44, 0x59, 0x56, 0x32, 0x48, 0x45, 0x53, 0x35, 0x4a, 0x76, 0x6b, 0x4b, 0x35, 0x72, 0x6f, 0x65, 0x39, 0x77, 0x67, 0x44, 0x38, 0x4c, 0x67, 0x6d, 0x73, 0x69, 0x36, 0x51, 0x69, 0x71, 0x6a, 0x6d, 0x46, 0x31, 0x4b, 0x38, 0x38, 0x4d, 0x57, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x39, 0x73, 0x45, 0x63, 0x45, 0x33, 0x50, 0x32, 0x79, 0x6d, 0x4b, 0x39, 0x42, 0x5a, 0x50, 0x45, 0x51, 0x43, 0x47, 0x35, 0x6d, 0x6f, 0x67, 0x59, 0x4b, 0x48, 0x63, 0x68, 0x71, 0x48, 0x53, 0x69, 0x57, 0x52, 0x45, 0x4c, 0x68, 0x4a, 0x52, 0x5a, 0x32, 0x69, 0x69, 0x56, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x45, 0x33, 0x56, 0x76, 0x4b, 0x79, 0x47, 0x70, 0x6d, 0x74, 0x52, 0x36, 0x55, 0x48, 0x6b, 0x51, 0x45, 0x75, 0x31, 0x43, 0x73, 0x70, 0x51, 0x47, 0x78, 0x4c, 0x67, 0x55, 0x56, 0x77, 0x4b, 0x64, 0x4c, 0x64, 0x4b, 0x46, 0x71, 0x4a, 0x35, 0x4e, 0x52, 0x74, 0x47, 0x74, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x52, 0x6b, 0x62, 0x7a, 0x79, 0x6b, 0x41, 0x48, 0x38, 0x4b, 0x55, 0x48, 0x57, 0x69, 0x52, 0x77, 0x66, 0x31, 0x45, 0x73, 0x55, 0x33, 0x46, 0x65, 0x67, 0x37, 0x73, 0x53, 0x57, 0x42, 0x65, 0x56, 0x43, 0x6b, 0x77, 0x6e, 0x4e, 0x57, 0x46, 0x57, 0x74, 0x36, 0x5a, 0x73, 0x52, 0x0, 0x60, 0x80, 0x94, 0xeb, 0xdc, 0x3, 0x68, 0x80, 0x84, 0xaf, 0x5f, 0x70, 0x80, 0x84, 0xaf, 0x5f, 0x78, 0x80, 0x84, 0xaf, 0x5f, 0x82, 0x1, 0x9e, 0x1, 0xa, 0x20, 0x54, 0x42, 0xd5, 0xda, 0xdc, 0x41, 0xfc, 0xf, 0xf1, 0xca, 0xc, 0x31, 0x37, 0x72, 0xe3, 0xed, 0xb7, 0xb7, 0xfd, 0x1e, 0x79, 0x49, 0x5b, 0x8e, 0xa6, 0x69, 0x94, 0xb6, 0x7e, 0xf9, 0xed, 0x40, 0x12, 0x20, 0x62, 0x28, 0x9f, 0xaf, 0xb1, 0x57, 0xd5, 0x85, 0x2a, 0xb2, 0x6c, 0x41, 0x3f, 0xf2, 0xb8, 0x41, 0x45, 0x9b, 0x80, 0x2c, 0x30, 0xe2, 0x4d, 0xf5, 0xf7, 0x9e, 0x85, 0x9c, 0xff, 0xc, 0x21, 0xb4, 0x1a, 0x10, 0x26, 0xbd, 0x1f, 0x5e, 0x13, 0xa5, 0x3d, 0x8b, 0xc2, 0xaf, 0xc1, 0x73, 0x33, 0x6c, 0xa5, 0xa4, 0x1a, 0x10, 0xe, 0x7a, 0xe, 0x77, 0x3a, 0xec, 0x57, 0x35, 0x1d, 0xb7, 0xc, 0xf0, 0x7f, 0x86, 0x74, 0x1, 0x1a, 0x10, 0x45, 0xaa, 0x20, 0x68, 0x4b, 0x49, 0x97, 0x3a, 0x26, 0x22, 0x18, 0x77, 0x9f, 0x67, 0x93, 0x72, 0x1a, 0x10, 0x1c, 0x4d, 0xd7, 0x4a, 0x54, 0xb2, 0xd, 0x92, 0x7, 0xec, 0xcd, 0x95, 0xe6, 0xd4, 0xaf, 0x91, 0x1a, 0x10, 0xea, 0x76, 0xae, 0x49, 0x62, 0x87, 0xef, 0xb7, 0x12, 0x60, 0xfb, 0xd6, 0x13, 0xfe, 0x48, 0xcb}, + }, + ConfigBlock: 0x11, + } + starknetReaderCallContractBalanceOfResponse = []string{"0x56bc75e2d63100000", "0x0"} + ocr2ClientLinkAvailableForPaymentResponse = bigIntFromString("99999991552000000000") + expectedEnvelope = relayMonitoring.Envelope{ + ConfigDigest: types.ConfigDigest{0x0, 0x4, 0x18, 0xe5, 0x44, 0xab, 0xa8, 0x18, 0x15, 0xa5, 0x2b, 0xf0, 0x11, 0x58, 0xc6, 0x9b, 0x38, 0x8a, 0x48, 0x9f, 0x76, 0xd, 0xd8, 0x3d, 0x84, 0x3f, 0x1d, 0x31, 0x22, 0xdb, 0x78, 0xa}, + Epoch: 0x519, + Round: 0x5, + LatestAnswer: bigIntFromString("-900000000"), + LatestTimestamp: time.Date(2022, time.September, 27, 18, 51, 0, 0, time.Local), + ContractConfig: types.ContractConfig{ + ConfigDigest: types.ConfigDigest{0x0, 0x4, 0x18, 0xe5, 0x44, 0xab, 0xa8, 0x18, 0x15, 0xa5, 0x2b, 0xf0, 0x11, 0x58, 0xc6, 0x9b, 0x38, 0x8a, 0x48, 0x9f, 0x76, 0xd, 0xd8, 0x3d, 0x84, 0x3f, 0x1d, 0x31, 0x22, 0xdb, 0x78, 0xa}, + ConfigCount: 0x1, + Signers: []types.OnchainPublicKey{ + types.OnchainPublicKey{0x6, 0x43, 0x41, 0xfa, 0xc3, 0x1, 0xc6, 0x2c, 0x38, 0xa9, 0xef, 0xdb, 0x86, 0xf6, 0xa2, 0x5a, 0x34, 0xd2, 0x4, 0x4f, 0x29, 0x2e, 0x94, 0xfb, 0xe4, 0x78, 0xa6, 0x67, 0x19, 0xb3, 0x80, 0x9e}, + types.OnchainPublicKey{0x1, 0xe2, 0xe1, 0x45, 0x47, 0x3, 0x7d, 0xb0, 0xd2, 0xe, 0xc6, 0xc9, 0x4b, 0xc7, 0x91, 0xea, 0xf2, 0xc9, 0x98, 0xad, 0x92, 0x79, 0xbb, 0xd, 0x21, 0x80, 0x15, 0x14, 0xd0, 0x6f, 0xa5, 0x7e}, + types.OnchainPublicKey{0x3, 0xb6, 0xcb, 0xd7, 0xbd, 0x52, 0x2d, 0xc8, 0xb0, 0xb4, 0x15, 0x3d, 0x60, 0x44, 0xec, 0xa7, 0x7e, 0x3e, 0xcf, 0xde, 0xe0, 0xc9, 0x5d, 0x20, 0x75, 0x50, 0x61, 0xf4, 0xbc, 0x7b, 0xf5, 0x4d}, + types.OnchainPublicKey{0x2, 0x4a, 0xa1, 0x21, 0x5b, 0xf4, 0xa3, 0xbb, 0x13, 0xea, 0x19, 0x57, 0x74, 0x28, 0xb7, 0xbe, 0xb5, 0xb9, 0x28, 0xb5, 0x74, 0x96, 0x78, 0xfa, 0x46, 0x87, 0x3b, 0x62, 0x7b, 0x22, 0x2a, 0x14}, + types.OnchainPublicKey{0x2, 0xa9, 0xc8, 0x4f, 0x88, 0x14, 0x17, 0xb5, 0xc9, 0xd1, 0x3b, 0x80, 0x2a, 0xc9, 0x93, 0xc5, 0x2c, 0x82, 0x88, 0x62, 0x32, 0xf7, 0x4e, 0x47, 0x5a, 0x92, 0xcc, 0x1a, 0xa, 0x1, 0x10, 0xda}, + }, + Transmitters: []types.Account{ + "0x033c95af529827a2372743bfc820b4d0bd08605fda5e089d1a7ad3a33caa48fc", + "0x05e457e084ff8e7279985ffb7ad7a65a6adfa8485e7d5d615c015268d5aa9971", + "0x0692a71d868ee9fc22091d8f73c16dabaf9219fa74c4bcc7d385f398949ba8d2", + "0x01232b74b82e490f373453baebe7e217cc6d33d798824a04f8274fa83bc2acd4", + "0x016715b5cc943835f196b7caf5a8aeb0e85b3f975dc43c14c90d0376e87eead1", + }, + F: 0x1, + OnchainConfig: []uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xb7, 0x89, 0x18, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0x48, 0x76, 0xe8, 0x0}, + OffchainConfigVersion: 0x2, + OffchainConfig: []uint8{0x8, 0x80, 0xa0, 0xd9, 0xe6, 0x1d, 0x10, 0x80, 0xd8, 0x8e, 0xe1, 0x6f, 0x18, 0x80, 0xbc, 0xc1, 0x96, 0xb, 0x20, 0x80, 0xca, 0xb5, 0xee, 0x1, 0x28, 0x80, 0x90, 0xdf, 0xc0, 0x4a, 0x30, 0x5, 0x3a, 0x2, 0x1, 0x2, 0x42, 0x20, 0xe9, 0x4f, 0x24, 0x4a, 0xcd, 0x86, 0x7d, 0xa5, 0x72, 0x54, 0x35, 0x57, 0x82, 0xb7, 0x1d, 0xb4, 0x50, 0x83, 0xd3, 0x67, 0xa7, 0xef, 0x23, 0x71, 0x5e, 0xb5, 0xce, 0x64, 0x38, 0xdf, 0x16, 0x1b, 0x42, 0x20, 0x34, 0xb6, 0xb5, 0xd, 0x9a, 0x47, 0xa2, 0x25, 0xe7, 0x91, 0xb3, 0x67, 0x7a, 0x1e, 0xd, 0x12, 0x2b, 0xa0, 0xc, 0xe9, 0x60, 0xd3, 0x7c, 0x76, 0x46, 0xec, 0x84, 0xcd, 0xd6, 0xfa, 0x9c, 0x48, 0x42, 0x20, 0x6a, 0xbc, 0xb4, 0x9d, 0xc7, 0xf4, 0xa9, 0x2f, 0xc4, 0x50, 0x89, 0x82, 0xa8, 0xa, 0xc1, 0x54, 0x23, 0x79, 0x8a, 0x2d, 0xe, 0x47, 0x1e, 0x95, 0xf4, 0x1e, 0x30, 0xeb, 0x68, 0x85, 0x29, 0xa6, 0x42, 0x20, 0x9b, 0xab, 0xa6, 0x36, 0x27, 0xbf, 0xa5, 0x31, 0x26, 0x9f, 0x32, 0x40, 0xb4, 0xc4, 0xe9, 0x8e, 0x86, 0xbc, 0xd5, 0x99, 0x83, 0xc5, 0x27, 0x31, 0x5f, 0x7a, 0xd1, 0x2f, 0x51, 0x5d, 0xd8, 0xfc, 0x42, 0x20, 0x72, 0xd7, 0x97, 0xfe, 0x3c, 0x8, 0xd8, 0x97, 0xfe, 0xe8, 0xdd, 0xa3, 0xa9, 0x40, 0x66, 0xa3, 0x4d, 0xa7, 0x27, 0x81, 0x4f, 0xf, 0x1f, 0x6c, 0x72, 0x22, 0xba, 0xdc, 0x52, 0x18, 0xcf, 0xb2, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x45, 0x7a, 0x66, 0x67, 0x38, 0x70, 0x32, 0x71, 0x58, 0x42, 0x38, 0x74, 0x77, 0x37, 0x6b, 0x42, 0x59, 0x72, 0x76, 0x75, 0x4d, 0x6e, 0x75, 0x47, 0x70, 0x66, 0x75, 0x79, 0x71, 0x59, 0x67, 0x4a, 0x50, 0x76, 0x78, 0x70, 0x77, 0x69, 0x62, 0x73, 0x50, 0x68, 0x67, 0x5a, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x4c, 0x5a, 0x4a, 0x58, 0x71, 0x44, 0x59, 0x56, 0x32, 0x48, 0x45, 0x53, 0x35, 0x4a, 0x76, 0x6b, 0x4b, 0x35, 0x72, 0x6f, 0x65, 0x39, 0x77, 0x67, 0x44, 0x38, 0x4c, 0x67, 0x6d, 0x73, 0x69, 0x36, 0x51, 0x69, 0x71, 0x6a, 0x6d, 0x46, 0x31, 0x4b, 0x38, 0x38, 0x4d, 0x57, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x39, 0x73, 0x45, 0x63, 0x45, 0x33, 0x50, 0x32, 0x79, 0x6d, 0x4b, 0x39, 0x42, 0x5a, 0x50, 0x45, 0x51, 0x43, 0x47, 0x35, 0x6d, 0x6f, 0x67, 0x59, 0x4b, 0x48, 0x63, 0x68, 0x71, 0x48, 0x53, 0x69, 0x57, 0x52, 0x45, 0x4c, 0x68, 0x4a, 0x52, 0x5a, 0x32, 0x69, 0x69, 0x56, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x45, 0x33, 0x56, 0x76, 0x4b, 0x79, 0x47, 0x70, 0x6d, 0x74, 0x52, 0x36, 0x55, 0x48, 0x6b, 0x51, 0x45, 0x75, 0x31, 0x43, 0x73, 0x70, 0x51, 0x47, 0x78, 0x4c, 0x67, 0x55, 0x56, 0x77, 0x4b, 0x64, 0x4c, 0x64, 0x4b, 0x46, 0x71, 0x4a, 0x35, 0x4e, 0x52, 0x74, 0x47, 0x74, 0x4a, 0x34, 0x31, 0x32, 0x44, 0x33, 0x4b, 0x6f, 0x6f, 0x57, 0x52, 0x6b, 0x62, 0x7a, 0x79, 0x6b, 0x41, 0x48, 0x38, 0x4b, 0x55, 0x48, 0x57, 0x69, 0x52, 0x77, 0x66, 0x31, 0x45, 0x73, 0x55, 0x33, 0x46, 0x65, 0x67, 0x37, 0x73, 0x53, 0x57, 0x42, 0x65, 0x56, 0x43, 0x6b, 0x77, 0x6e, 0x4e, 0x57, 0x46, 0x57, 0x74, 0x36, 0x5a, 0x73, 0x52, 0x0, 0x60, 0x80, 0x94, 0xeb, 0xdc, 0x3, 0x68, 0x80, 0x84, 0xaf, 0x5f, 0x70, 0x80, 0x84, 0xaf, 0x5f, 0x78, 0x80, 0x84, 0xaf, 0x5f, 0x82, 0x1, 0x9e, 0x1, 0xa, 0x20, 0x54, 0x42, 0xd5, 0xda, 0xdc, 0x41, 0xfc, 0xf, 0xf1, 0xca, 0xc, 0x31, 0x37, 0x72, 0xe3, 0xed, 0xb7, 0xb7, 0xfd, 0x1e, 0x79, 0x49, 0x5b, 0x8e, 0xa6, 0x69, 0x94, 0xb6, 0x7e, 0xf9, 0xed, 0x40, 0x12, 0x20, 0x62, 0x28, 0x9f, 0xaf, 0xb1, 0x57, 0xd5, 0x85, 0x2a, 0xb2, 0x6c, 0x41, 0x3f, 0xf2, 0xb8, 0x41, 0x45, 0x9b, 0x80, 0x2c, 0x30, 0xe2, 0x4d, 0xf5, 0xf7, 0x9e, 0x85, 0x9c, 0xff, 0xc, 0x21, 0xb4, 0x1a, 0x10, 0x26, 0xbd, 0x1f, 0x5e, 0x13, 0xa5, 0x3d, 0x8b, 0xc2, 0xaf, 0xc1, 0x73, 0x33, 0x6c, 0xa5, 0xa4, 0x1a, 0x10, 0xe, 0x7a, 0xe, 0x77, 0x3a, 0xec, 0x57, 0x35, 0x1d, 0xb7, 0xc, 0xf0, 0x7f, 0x86, 0x74, 0x1, 0x1a, 0x10, 0x45, 0xaa, 0x20, 0x68, 0x4b, 0x49, 0x97, 0x3a, 0x26, 0x22, 0x18, 0x77, 0x9f, 0x67, 0x93, 0x72, 0x1a, 0x10, 0x1c, 0x4d, 0xd7, 0x4a, 0x54, 0xb2, 0xd, 0x92, 0x7, 0xec, 0xcd, 0x95, 0xe6, 0xd4, 0xaf, 0x91, 0x1a, 0x10, 0xea, 0x76, 0xae, 0x49, 0x62, 0x87, 0xef, 0xb7, 0x12, 0x60, 0xfb, 0xd6, 0x13, 0xfe, 0x48, 0xcb}, + }, + BlockNumber: 0xe07, + Transmitter: types.Account("0x16715b5cc943835f196b7caf5a8aeb0e85b3f975dc43c14c90d0376e87eead1"), + LinkBalance: bigIntFromString("100000000000000000000"), + LinkAvailableForPayment: bigIntFromString("99999991552000000000"), + JuelsPerFeeCoin: big.NewInt(451000), + AggregatorRoundID: 0xf5b, + } +) + +func bigIntFromString(s string) *big.Int { + out, _ := new(big.Int).SetString(s, 10) + return out +} diff --git a/monitoring/pkg/monitoring/source_proxy.go b/monitoring/pkg/monitoring/source_proxy.go new file mode 100644 index 0000000..f1b1800 --- /dev/null +++ b/monitoring/pkg/monitoring/source_proxy.go @@ -0,0 +1,56 @@ +package monitoring + +import ( + "context" + "fmt" + "math/big" + + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" +) + +type ProxyData struct { + Answer *big.Int +} + +func NewProxySourceFactory( + ocr2Reader ocr2.OCR2Reader, +) relayMonitoring.SourceFactory { + return &proxySourceFactory{ + ocr2Reader, + } +} + +type proxySourceFactory struct { + ocr2Reader ocr2.OCR2Reader +} + +func (s *proxySourceFactory) NewSource( + _ relayMonitoring.ChainConfig, + feedConfig relayMonitoring.FeedConfig, +) (relayMonitoring.Source, error) { + return &proxySource{ + feedConfig.GetContractAddress(), + s.ocr2Reader, + }, nil +} + +func (s *proxySourceFactory) GetType() string { + return "proxy" +} + +type proxySource struct { + contractAddress string + ocr2Reader ocr2.OCR2Reader +} + +func (s *proxySource) Fetch(ctx context.Context) (interface{}, error) { + latestTransmission, err := s.ocr2Reader.LatestTransmissionDetails(ctx, s.contractAddress) + if err != nil { + return nil, fmt.Errorf("couldn't fetch latest_transmission_details: %w", err) + } + return ProxyData{ + Answer: latestTransmission.LatestAnswer, + }, nil +} diff --git a/monitoring/pkg/monitoring/source_proxy_test.go b/monitoring/pkg/monitoring/source_proxy_test.go new file mode 100644 index 0000000..7705657 --- /dev/null +++ b/monitoring/pkg/monitoring/source_proxy_test.go @@ -0,0 +1,53 @@ +package monitoring + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + ocr2Mocks "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/mocks" +) + +func TestProxySource(t *testing.T) { + // This test makes sure that the mapping between the response from the ocr2.Client + // method calls and the output of the Proxy source is correct. + + chainConfig := generateChainConfig() + feedConfig := generateFeedConfig() + + ocr2Reader := ocr2Mocks.NewOCR2Reader(t) + ocr2Reader.On( + "LatestTransmissionDetails", + mock.Anything, // ctx + feedConfig.ContractAddress, + ).Return(ocr2ClientLatestTransmissionDetailsResponseForProxy, nil).Once() + + factory := NewProxySourceFactory(ocr2Reader) + source, err := factory.NewSource(chainConfig, feedConfig) + require.NoError(t, err) + rawProxyData, err := source.Fetch(context.Background()) + require.NoError(t, err) + proxyData, ok := rawProxyData.(ProxyData) + require.True(t, ok) + + require.Equal(t, + ocr2ClientLatestTransmissionDetailsResponseForProxy.LatestAnswer.String(), + proxyData.Answer.String(), + ) +} + +var ( + ocr2ClientLatestTransmissionDetailsResponseForProxy = ocr2.TransmissionDetails{ + Digest: types.ConfigDigest{0x0, 0x4, 0x18, 0xe5, 0x44, 0xab, 0xa8, 0x18, 0x15, 0xa5, 0x2b, 0xf0, 0x11, 0x58, 0xc6, 0x9b, 0x38, 0x8a, 0x48, 0x9f, 0x76, 0xd, 0xd8, 0x3d, 0x84, 0x3f, 0x1d, 0x31, 0x22, 0xdb, 0x78, 0xa}, + Epoch: 0x1, + Round: 0x9, + LatestAnswer: big.NewInt(10000), + LatestTimestamp: time.Now(), + } +) diff --git a/monitoring/pkg/monitoring/source_txresults.go b/monitoring/pkg/monitoring/source_txresults.go new file mode 100644 index 0000000..04592df --- /dev/null +++ b/monitoring/pkg/monitoring/source_txresults.go @@ -0,0 +1,63 @@ +package monitoring + +import ( + "context" + "fmt" + "sync" + + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" +) + +func NewTxResultsSourceFactory( + ocr2Reader ocr2.OCR2Reader, +) relayMonitoring.SourceFactory { + return &txResultsSourceFactory{ + ocr2Reader, + } +} + +type txResultsSourceFactory struct { + ocr2Reader ocr2.OCR2Reader +} + +func (s *txResultsSourceFactory) NewSource( + _ relayMonitoring.ChainConfig, + feedConfig relayMonitoring.FeedConfig, +) (relayMonitoring.Source, error) { + return &txResultsSource{ + feedConfig.GetContractAddress(), + s.ocr2Reader, + 0, + sync.Mutex{}, + }, nil +} + +func (s *txResultsSourceFactory) GetType() string { + return "txresults" +} + +type txResultsSource struct { + contractAddress string + ocr2Reader ocr2.OCR2Reader + + prevRoundID uint32 + prevRoundIDMu sync.Mutex +} + +func (s *txResultsSource) Fetch(ctx context.Context) (interface{}, error) { + latestRoundData, err := s.ocr2Reader.LatestRoundData(ctx, s.contractAddress) + if err != nil { + return nil, fmt.Errorf("failed to fetch latest_round_data: %w", err) + } + s.prevRoundIDMu.Lock() + defer s.prevRoundIDMu.Unlock() + var numSucceeded uint32 + if s.prevRoundID != 0 { + numSucceeded = latestRoundData.RoundID - s.prevRoundID + } + s.prevRoundID = latestRoundData.RoundID + // Note that failed/rejected transactions count is always set to 0 because there is no way to count them. + return relayMonitoring.TxResults{NumSucceeded: uint64(numSucceeded), NumFailed: 0}, nil +} diff --git a/monitoring/pkg/monitoring/source_txresults_test.go b/monitoring/pkg/monitoring/source_txresults_test.go new file mode 100644 index 0000000..7c6a0bb --- /dev/null +++ b/monitoring/pkg/monitoring/source_txresults_test.go @@ -0,0 +1,60 @@ +package monitoring + +import ( + "context" + "testing" + + relayMonitoring "github.com/goplugin/plugin-relay/pkg/monitoring" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + ocr2Mocks "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/mocks" +) + +func TestTxResultsSource(t *testing.T) { + // This test makes sure that the mapping between the response from the ocr2.Client + // method calls and the output of the TxResults source is correct. + + chainConfig := generateChainConfig() + feedConfig := generateFeedConfig() + + ocr2Reader := ocr2Mocks.NewOCR2Reader(t) + ocr2Reader.On( + "LatestRoundData", + mock.Anything, // ctx + feedConfig.ContractAddress, + ).Return(ocr2ClientLatestRoundDataResponseForTxResults1, nil).Once() + ocr2Reader.On( + "LatestRoundData", + mock.Anything, // ctx + feedConfig.ContractAddress, + ).Return(ocr2ClientLatestRoundDataResponseForTxResults2, nil).Once() + + factory := NewTxResultsSourceFactory(ocr2Reader) + source, err := factory.NewSource(chainConfig, feedConfig) + require.NoError(t, err) + // First call identifies no new transactions. + rawTxResults, err := source.Fetch(context.Background()) + require.NoError(t, err) + txResults, ok := rawTxResults.(relayMonitoring.TxResults) + require.True(t, ok) + require.Equal(t, txResults.NumSucceeded, uint64(0)) + require.Equal(t, txResults.NumFailed, uint64(0)) + // Second call identifies new transactions + rawTxResults, err = source.Fetch(context.Background()) + require.NoError(t, err) + txResults, ok = rawTxResults.(relayMonitoring.TxResults) + require.True(t, ok) + require.Equal(t, txResults.NumSucceeded, uint64(1)) + require.Equal(t, txResults.NumFailed, uint64(0)) +} + +var ( + ocr2ClientLatestRoundDataResponseForTxResults1 = ocr2.RoundData{ + RoundID: 100, + } + ocr2ClientLatestRoundDataResponseForTxResults2 = ocr2.RoundData{ + RoundID: 101, + } +) diff --git a/monitoring/pkg/monitoring/testutils.go b/monitoring/pkg/monitoring/testutils.go new file mode 100644 index 0000000..40d2a92 --- /dev/null +++ b/monitoring/pkg/monitoring/testutils.go @@ -0,0 +1,58 @@ +package monitoring + +import ( + "fmt" + "math/big" + "math/rand" + "time" +) + +func generateChainConfig() StarknetConfig { + return StarknetConfig{ + rpcEndpoint: "http://starknet/6969", + networkName: "devnet", + networkID: "1", + chainID: "devnet", + readTimeout: 100 * time.Millisecond, + pollInterval: 1 * time.Second, + linkTokenAddress: generateAddr(), + } +} + +func generateFeedConfig() StarknetFeedConfig { + coins := []string{"btc", "eth", "matic", "link", "avax", "ftt", "srm", "usdc", "sol", "ray"} + coin := coins[rand.Intn(len(coins))] + + return StarknetFeedConfig{ + Name: fmt.Sprintf("%s / usd", coin), + Path: fmt.Sprintf("%s-usd", coin), + Symbol: "$", + HeartbeatSec: 1, + ContractType: "ocr2", + ContractStatus: "live", + + MultiplyRaw: "1000000", + Multiply: big.NewInt(1000000), + + ContractAddress: generateAddr(), + ProxyAddress: generateAddr(), + } +} + +func generateAddr() string { + pool := []string{ + "0x0398eca85a333bc5de78f87d70d26f6e1f2438da6d163424b20f6190d3c38a21", + "0x057605d472e1478b66396d8abec8f6c58348d9278d25049d9d73dafab40cde0c", + "0x18e693006a3dc4db5adf7812c2e4ab8d7729707fcb3c439de0939f39de8d2b", + "0x05c96456a9d58aa45e997182050f07a0649638a8f1d955935b42b6898d99e63d", + "0x0358549759856b585a7b74ce5462e0ec0e56dbcc8fc729255150da2b62b702a6", + "0x025d26785bc488193674b4e504f1ea0fc0bc28b0b92b7ce3e4b63ea5514bc3ab", + } + return pool[rand.Intn(len(pool))] +} + +var ( + _ = generateChainConfig() + _ = generateFeedConfig() + _ = generateAddr() +) diff --git a/nix.conf b/nix.conf new file mode 100644 index 0000000..c7d7291 --- /dev/null +++ b/nix.conf @@ -0,0 +1 @@ +experimental-features = nix-command flakes diff --git a/ops/README.md b/ops/README.md new file mode 100644 index 0000000..4a7f42a --- /dev/null +++ b/ops/README.md @@ -0,0 +1,11 @@ +## Local k8s environment + +## Running via `localenv` simple CLI + +- [CLI doc and commands](./localenv/README.md) + +## Manual Instructions + +You can find setup instructions [here](../../docs/kubernetes.md) + +See an example of building new environments [here](../../docs/integration-tests/testing.md) \ No newline at end of file diff --git a/ops/charts/devnet/.helmignore b/ops/charts/devnet/.helmignore new file mode 100644 index 0000000..c13e3c8 --- /dev/null +++ b/ops/charts/devnet/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj \ No newline at end of file diff --git a/ops/charts/devnet/Chart.yaml b/ops/charts/devnet/Chart.yaml new file mode 100644 index 0000000..1af9fa1 --- /dev/null +++ b/ops/charts/devnet/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +description: StarkNET Pathfined/devnet deployment +name: starknetdev +version: 0.1.0 +keywords: + - starknet + - pathfinder \ No newline at end of file diff --git a/ops/charts/devnet/templates/NOTES.txt b/ops/charts/devnet/templates/NOTES.txt new file mode 100644 index 0000000..9399803 --- /dev/null +++ b/ops/charts/devnet/templates/NOTES.txt @@ -0,0 +1 @@ +StarkNET dev node installed! \ No newline at end of file diff --git a/ops/charts/devnet/templates/_helpers.tpl b/ops/charts/devnet/templates/_helpers.tpl new file mode 100644 index 0000000..328fd46 --- /dev/null +++ b/ops/charts/devnet/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 24 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 24 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 24 | trimSuffix "-" -}} +{{- end -}} \ No newline at end of file diff --git a/ops/charts/devnet/templates/deployment.yaml b/ops/charts/devnet/templates/deployment.yaml new file mode 100644 index 0000000..10735f7 --- /dev/null +++ b/ops/charts/devnet/templates/deployment.yaml @@ -0,0 +1,72 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: starknet-dev + labels: + release: {{ .Release.Name }} + app: starknet-dev +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + release: {{ .Release.Name }} + app: starknet-dev + template: + metadata: + labels: + release: {{ .Release.Name }} + app: starknet-dev + spec: + volumes: + - name: vol + hostPath: + path: /dumps + containers: + - name: {{ .Chart.Name }} + volumeMounts: + - name: vol + mountPath: /dumps +{{- if eq .Values.real_node true }} + image: "{{ .Values.repository | default "eqlabs/pathfinder"}}:{{ .Values.tag | default "v0.1.8-alpha"}}" +{{- else }} + image: "{{ .Values.repository | default "shardlabs/starknet-devnet"}}:{{ .Values.tag | default "0.5.0"}}" + args: ["--lite-mode", "--port", {{ .Values.service.internalPort | quote}}, "--seed", {{ .Values.seed | quote}}] +{{- end }} + imagePullPolicy: IfNotPresent +{{- if eq .Values.real_node true }} + env: + - name: PATHFINDER_HTTP_RPC_ADDRESS + value: "0.0.0.0:5000" + - name: RUSTLOG + value: "info" + - name: PATHFINDER_ETHEREUM_API_URL + value: {{ .Values.url_http_L1 }} +{{- else }} + env: + - name: PYTHONUNBUFFERED + value: "1" + - name: PATHFINDER_ETHEREUM_API_URL + value: {{ .Values.url_http_L1 }} +{{- end }} + ports: + - name: http + containerPort: {{ .Values.service.internalPort }} + livenessProbe: + httpGet: + path: /is_alive + port: {{ .Values.service.externalPort }} + initialDelaySeconds: 1 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /is_alive + port: {{ .Values.service.externalPort }} + initialDelaySeconds: 2 + periodSeconds: 1 + resources: + requests: + memory: {{ .Values.resources.requests.memory }} + cpu: {{ .Values.resources.requests.cpu }} + limits: + memory: {{ .Values.resources.limits.memory }} + cpu: {{ .Values.resources.limits.cpu }} diff --git a/ops/charts/devnet/templates/service.yaml b/ops/charts/devnet/templates/service.yaml new file mode 100644 index 0000000..f5763d3 --- /dev/null +++ b/ops/charts/devnet/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: starknet-dev + labels: + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.externalPort }} + targetPort: {{ .Values.service.internalPort }} + protocol: TCP + selector: + release: {{ .Release.Name }} + app: starknet-dev diff --git a/ops/charts/devnet/values.yaml b/ops/charts/devnet/values.yaml new file mode 100644 index 0000000..fd2690b --- /dev/null +++ b/ops/charts/devnet/values.yaml @@ -0,0 +1,16 @@ +# Declare variables to be passed into your templates. +replicaCount: 1 +service: + type: ClusterIP + externalPort: 5000 + internalPort: 5000 +resources: + limits: + cpu: 2000m + memory: 2048Mi + requests: + cpu: 2000m + memory: 2048Mi +url_http_L1: "" +real_node: false +seed: 0 diff --git a/ops/charts/hardhat/.helmignore b/ops/charts/hardhat/.helmignore new file mode 100644 index 0000000..c13e3c8 --- /dev/null +++ b/ops/charts/hardhat/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj \ No newline at end of file diff --git a/ops/charts/hardhat/Chart.yaml b/ops/charts/hardhat/Chart.yaml new file mode 100644 index 0000000..bf6532b --- /dev/null +++ b/ops/charts/hardhat/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +description: Hardhat deployment +name: hardhat +version: 0.1.0 +keywords: + - hardhat diff --git a/ops/charts/hardhat/templates/NOTES.txt b/ops/charts/hardhat/templates/NOTES.txt new file mode 100644 index 0000000..9d383c6 --- /dev/null +++ b/ops/charts/hardhat/templates/NOTES.txt @@ -0,0 +1 @@ +Hardhat node installed! \ No newline at end of file diff --git a/ops/charts/hardhat/templates/_helpers.tpl b/ops/charts/hardhat/templates/_helpers.tpl new file mode 100644 index 0000000..328fd46 --- /dev/null +++ b/ops/charts/hardhat/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 24 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 24 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 24 | trimSuffix "-" -}} +{{- end -}} \ No newline at end of file diff --git a/ops/charts/hardhat/templates/deployment.yaml b/ops/charts/hardhat/templates/deployment.yaml new file mode 100644 index 0000000..1374437 --- /dev/null +++ b/ops/charts/hardhat/templates/deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hardhat + labels: + release: {{ .Release.Name }} + app: hardhat +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + release: {{ .Release.Name }} + app: hardhat + template: + metadata: + labels: + release: {{ .Release.Name }} + app: hardhat + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.repository | default "ethereumoptimism/hardhat-node"}}:{{ .Values.tag | default "nightly"}}" + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: {{ .Values.service.internalPort }} + livenessProbe: + httpGet: + path: / + port: {{ .Values.service.externalPort }} + initialDelaySeconds: 1 + periodSeconds: 30 + readinessProbe: + httpGet: + path: / + port: {{ .Values.service.externalPort }} + initialDelaySeconds: 2 + periodSeconds: 1 + resources: + requests: + memory: {{ .Values.resources.requests.memory }} + cpu: {{ .Values.resources.requests.cpu }} + limits: + memory: {{ .Values.resources.limits.memory }} + cpu: {{ .Values.resources.limits.cpu }} \ No newline at end of file diff --git a/ops/charts/hardhat/templates/service.yaml b/ops/charts/hardhat/templates/service.yaml new file mode 100644 index 0000000..fb1364e --- /dev/null +++ b/ops/charts/hardhat/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: hardhat + labels: + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.externalPort }} + targetPort: {{ .Values.service.internalPort }} + protocol: TCP + selector: + release: {{ .Release.Name }} + app: hardhat \ No newline at end of file diff --git a/ops/charts/hardhat/values.yaml b/ops/charts/hardhat/values.yaml new file mode 100644 index 0000000..c7e2a5e --- /dev/null +++ b/ops/charts/hardhat/values.yaml @@ -0,0 +1,14 @@ +# Declare variables to be passed into your templates. +replicaCount: 1 +service: + name: hardhat-service + type: ClusterIP + externalPort: 8545 + internalPort: 8545 +resources: + limits: + cpu: 2000m + memory: 2048Mi + requests: + cpu: 2000m + memory: 2048Mi \ No newline at end of file diff --git a/ops/devnet/devnet.go b/ops/devnet/devnet.go new file mode 100644 index 0000000..1830402 --- /dev/null +++ b/ops/devnet/devnet.go @@ -0,0 +1,126 @@ +package devnet + +import ( + "context" + "fmt" + "strings" + "time" + + caigotypes "github.com/dontpanicdao/caigo/types" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + + "github.com/go-resty/resty/v2" + "github.com/rs/zerolog/log" +) + +type StarknetDevnetClient struct { + ctx context.Context + cancel context.CancelFunc + client *resty.Client + dumpPath string +} + +func (devnet *StarknetDevnetClient) NewStarknetDevnetClient(rpcUrl string, dumpPath string) *StarknetDevnetClient { + ctx, cancel := context.WithCancel(context.Background()) + return &StarknetDevnetClient{ + ctx: ctx, + cancel: cancel, + client: resty.New().SetBaseURL(rpcUrl), + dumpPath: dumpPath, + } +} + +// AutoSyncL1 auto calls /flush/ every 2 seconds to sync L1<>L2 +func (devnet *StarknetDevnetClient) AutoSyncL1() { + t := time.NewTicker(2 * time.Second) + go func() { + for { + select { + case <-devnet.ctx.Done(): + log.Debug().Msg("Shutting down L1 sync") + return + case <-t.C: + log.Debug().Msg("Syncing L1") + _, err := devnet.client.R().Post("/postman/flush") + if err != nil { + log.Error().Err(err).Msg("failed to sync L1") + } + } + } + }() +} + +// AutoDumpState dumps devnet state every 10 sec +func (devnet *StarknetDevnetClient) AutoDumpState() { + t := time.NewTicker(20 * time.Minute) + go func() { + for { + select { + case <-devnet.ctx.Done(): + log.Debug().Msg("Shutting down devnet dump") + return + case <-t.C: + log.Debug().Msg("Dumping state") + _, err := devnet.client.R().SetBody(map[string]any{ + "path": devnet.dumpPath, + }).Post("/dump") + if err != nil { + log.Error().Err(err).Msg("Failed to dump devnet state") + } + } + } + }() +} + +// AutoLoadState auto loads last saved devnet state on contract not found +func (devnet *StarknetDevnetClient) AutoLoadState(client *ocr2.Client, ocrAddress string) { + t := time.NewTicker(15 * time.Second) + go func() { + for { + select { + case <-devnet.ctx.Done(): + log.Debug().Msg("Shutting down devnet dump") + return + case <-t.C: + log.Debug().Msg("Checking for devnet OCR contract errors") + _, err := client.LatestTransmissionDetails(devnet.ctx, caigotypes.HexToHash(ocrAddress)) + if err != nil && strings.Contains(err.Error(), "is not deployed") { + _, err = devnet.client.R().SetBody(map[string]any{ + "path": devnet.dumpPath, + }).Post("/load") + if err != nil { + log.Error().Err(err).Msg("Failed to dump devnet state") + } + } + + } + } + }() +} + +// FundAccounts Funds provided accounts with 100 eth each +func (devnet *StarknetDevnetClient) FundAccounts(l2AccList []string) error { + for _, key := range l2AccList { + res, err := devnet.client.R().SetBody(map[string]any{ + "address": key, + "amount": 1e21, + }).Post("/mint") + if err != nil { + return err + } + log.Info().Msg(fmt.Sprintf("Funding account: %s", string(res.Body()))) + } + return nil +} + +// LoadL1MessagingContract loads and sets up the L1 messaging contract and URL +func (devnet *StarknetDevnetClient) LoadL1MessagingContract(l1RpcUrl string) error { + resp, err := devnet.client.R().SetBody(map[string]any{ + "networkUrl": l1RpcUrl, + }).Post("/postman/load_l1_messaging_contract") + if err != nil { + return err + } + log.Warn().Interface("Response", resp.String()).Msg("Set up L1 messaging contract") + return nil +} diff --git a/ops/devnet/environment.go b/ops/devnet/environment.go new file mode 100644 index 0000000..dc5e38f --- /dev/null +++ b/ops/devnet/environment.go @@ -0,0 +1,107 @@ +package devnet + +import ( + "fmt" + + "github.com/rs/zerolog/log" + "github.com/goplugin/plugin-env/client" + "github.com/goplugin/plugin-env/config" + "github.com/goplugin/plugin-env/environment" + "github.com/goplugin/plugin-starknet/ops/utils" +) + +const NetworkName = "starknet-dev" + +type Chart struct { + HelmProps *HelmProps + Props *Props +} +type Props struct { +} + +type HelmProps struct { + Name string + Path string + Values *map[string]any + Version string +} + +func (m Chart) IsDeploymentNeeded() bool { + return true +} + +func (m Chart) GetProps() any { + return m.Props +} + +func (m Chart) GetName() string { + return m.HelmProps.Name +} + +func (m Chart) GetPath() string { + return m.HelmProps.Path +} + +func (m Chart) GetValues() *map[string]any { + return m.HelmProps.Values +} + +func (m Chart) GetVersion() string { + return m.HelmProps.Version +} + +func (m Chart) ExportData(e *environment.Environment) error { + devnetLocalHttp, err := e.Fwd.FindPort("starknet-dev:0", "starknetdev", "http").As(client.LocalConnection, client.HTTP) + if err != nil { + return err + } + devnetInternalHttp, err := e.Fwd.FindPort("starknet-dev:0", "starknetdev", "http").As(client.RemoteConnection, client.HTTP) + if err != nil { + return err + } + e.URLs[NetworkName] = append(e.URLs[NetworkName], devnetLocalHttp) + e.URLs[NetworkName] = append(e.URLs[NetworkName], devnetInternalHttp) + log.Info().Str("Name", "Devnet").Str("URLs", devnetLocalHttp).Msg("Devnet network") + return nil +} + +func defaultProps() map[string]any { + return map[string]any{ + "replicas": "1", + "starknet-dev": map[string]any{ + "image": map[string]any{ + "image": "shardlabs/starknet-devnet", + "version": "v0.3.5", + }, + "resources": map[string]any{ + "requests": map[string]any{ + "cpu": "1000m", + "memory": "1024Mi", + }, + "limits": map[string]any{ + "cpu": "1000m", + "memory": "1024Mi", + }, + }, + "seed": "123", + "real_node": "false", + }, + } + +} + +func New(props *Props) environment.ConnectedChart { + dp := defaultProps() + if props != nil { + config.MustMerge(&dp, props) + } + + return Chart{ + HelmProps: &HelmProps{ + Name: NetworkName, + Path: fmt.Sprintf("%s/charts/devnet", utils.OpsRoot), + Values: &dp, + }, + Props: props, + } +} diff --git a/ops/gauntlet/gauntlet_starknet.go b/ops/gauntlet/gauntlet_starknet.go new file mode 100644 index 0000000..17108e0 --- /dev/null +++ b/ops/gauntlet/gauntlet_starknet.go @@ -0,0 +1,213 @@ +package gauntlet + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/goplugin/plugin-testing-framework/gauntlet" +) + +var ( + sg *StarknetGauntlet +) + +type StarknetGauntlet struct { + dir string + G *gauntlet.Gauntlet + gr *GauntletResponse + options *gauntlet.ExecCommandOptions +} + +// GauntletResponse Default response output for starknet gauntlet commands +type GauntletResponse struct { + Responses []struct { + Tx struct { + Hash string `json:"hash"` + Address string `json:"address"` + Status string `json:"status"` + + Tx struct { + Address string `json:"address"` + Code string `json:"code"` + Result []string `json:"result"` + TransactionHash string `json:"transaction_hash"` + } `json:"tx"` + } `json:"tx"` + Contract string `json:"contract"` + } `json:"responses"` +} + +// NewStarknetGauntlet Creates a default gauntlet config +func NewStarknetGauntlet(workingDir string) (*StarknetGauntlet, error) { + g, err := gauntlet.NewGauntlet() + g.SetWorkingDir(workingDir) + if err != nil { + return nil, err + } + sg = &StarknetGauntlet{ + dir: workingDir, + G: g, + gr: &GauntletResponse{}, + options: &gauntlet.ExecCommandOptions{ + ErrHandling: []string{}, + CheckErrorsInRead: true, + }, + } + return sg, nil +} + +// FetchGauntletJsonOutput Parse gauntlet json response that is generated after yarn gauntlet command execution +func (sg *StarknetGauntlet) FetchGauntletJsonOutput() (*GauntletResponse, error) { + var payload = &GauntletResponse{} + gauntletOutput, err := os.ReadFile(sg.dir + "report.json") + if err != nil { + return payload, err + } + err = json.Unmarshal(gauntletOutput, &payload) + if err != nil { + return payload, err + } + return payload, nil +} + +// SetupNetwork Sets up a new network and sets the NODE_URL for Devnet / Starknet RPC +func (sg *StarknetGauntlet) SetupNetwork(addr string) error { + sg.G.AddNetworkConfigVar("NODE_URL", addr) + err := sg.G.WriteNetworkConfigMap(sg.dir + "packages-ts/starknet-gauntlet-cli/networks/") + if err != nil { + return err + } + + return nil +} + +func (sg *StarknetGauntlet) InstallDependencies() error { + sg.G.Command = "yarn" + _, err := sg.G.ExecCommand([]string{"install"}, *sg.options) + if err != nil { + return err + } + sg.G.Command = "gauntlet" + return nil +} + +func (sg *StarknetGauntlet) DeployAccountContract(salt int64, pubKey string) (string, error) { + _, err := sg.G.ExecCommand([]string{"account:deploy", fmt.Sprintf("--salt=%d", salt), fmt.Sprintf("--publicKey=%s", pubKey)}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) DeployLinkTokenContract() (string, error) { + _, err := sg.G.ExecCommand([]string{"token:deploy", "--link"}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) MintLinkToken(token, to, amount string) (string, error) { + _, err := sg.G.ExecCommand([]string{"token:mint", fmt.Sprintf("--recipient=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) TransferToken(token, to, amount string) (string, error) { + _, err := sg.G.ExecCommand([]string{"token:transfer", fmt.Sprintf("--recipient=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) DeployOCR2ControllerContract(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, linkTokenAddress string) (string, error) { + _, err := sg.G.ExecCommand([]string{"ocr2:deploy", fmt.Sprintf("--minSubmissionValue=%d", minSubmissionValue), fmt.Sprintf("--maxSubmissionValue=%d", maxSubmissionValue), fmt.Sprintf("--decimals=%d", decimals), fmt.Sprintf("--name=%s", name), fmt.Sprintf("--link=%s", linkTokenAddress)}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) DeployAccessControllerContract() (string, error) { + _, err := sg.G.ExecCommand([]string{"access_controller:deploy"}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) DeployOCR2ProxyContract(aggregator string) (string, error) { + _, err := sg.G.ExecCommand([]string{"proxy:deploy", fmt.Sprintf("--address=%s", aggregator)}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) SetOCRBilling(observationPaymentGjuels int64, transmissionPaymentGjuels int64, ocrAddress string) (string, error) { + _, err := sg.G.ExecCommand([]string{"ocr2:set_billing", fmt.Sprintf("--observationPaymentGjuels=%d", observationPaymentGjuels), fmt.Sprintf("--transmissionPaymentGjuels=%d", transmissionPaymentGjuels), ocrAddress}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) SetConfigDetails(cfg string, ocrAddress string) (string, error) { + _, err := sg.G.ExecCommand([]string{"ocr2:set_config", "--input=" + cfg, ocrAddress}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} + +func (sg *StarknetGauntlet) AddAccess(aggregator, address string) (string, error) { + _, err := sg.G.ExecCommand([]string{"ocr2:add_access", fmt.Sprintf("--address=%s", address), aggregator}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} diff --git a/ops/go.mod b/ops/go.mod new file mode 100644 index 0000000..68a54f9 --- /dev/null +++ b/ops/go.mod @@ -0,0 +1,149 @@ +module github.com/goplugin/plugin-starknet/ops + +go 1.20 + +require ( + github.com/dontpanicdao/caigo v0.4.0 + github.com/go-resty/resty/v2 v2.7.0 + github.com/rs/zerolog v1.29.1 + github.com/goplugin/plugin-env v0.3.29 + github.com/goplugin/plugin-starknet/relayer v0.0.0-20221102160912-61646f534e3a + github.com/goplugin/plugin-testing-framework v1.11.5 +) + +require ( + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect + github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect + github.com/aws/jsii-runtime-go v1.75.0 // indirect + github.com/benbjohnson/clock v1.3.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect + github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/ethereum/go-ethereum v1.11.5 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/fatih/camelcase v1.0.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fvbommel/sortorder v1.0.2 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/gogo/protobuf v1.3.3 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/moby/spdystream v0.2.0 // indirect + github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.15.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/russross/blackfriday v1.6.0 // indirect + github.com/satori/go.uuid v1.2.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82 // indirect + github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc // indirect + github.com/spf13/cobra v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.8.2 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.5.0 // indirect + github.com/xlab/treeprint v1.1.0 // indirect + github.com/yuin/goldmark v1.4.13 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/mod v0.9.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.7.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.25.4 // indirect + k8s.io/apiextensions-apiserver v0.25.3 // indirect + k8s.io/apimachinery v0.25.4 // indirect + k8s.io/cli-runtime v0.25.4 // indirect + k8s.io/client-go v0.25.4 // indirect + k8s.io/component-base v0.25.4 // indirect + k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/kubectl v0.25.4 // indirect + k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect + sigs.k8s.io/controller-runtime v0.13.0 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/kustomize/api v0.12.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) + +replace ( + // Fix go mod tidy issue for ambiguous imports from go-ethereum + // See https://github.com/ugorji/go/issues/279 + github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.1 + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + + github.com/goplugin/plugin-starknet/relayer => ../relayer +) diff --git a/ops/go.sum b/ops/go.sum new file mode 100644 index 0000000..d3518a9 --- /dev/null +++ b/ops/go.sum @@ -0,0 +1,517 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac h1:TQ2m26VW06Df1P82Ed/jZhBtf13pReWyl2XQ8hy+J08= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac/go.mod h1:FTk2+xybtQe5X+oNFx+a0n5EeZMD9Nc+LCH4fxFwrEE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= +github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= +github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= +github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= +github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= +github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 h1:CyuI+igIjadM/GRnE2o0q+WCwipDh0n2cUYFPAvxziM= +github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657/go.mod h1:JRiumF+RFsH1mrrP8FUsi9tExPylKkO/oSRWeQEUdLE= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dontpanicdao/caigo v0.4.0 h1:S0wRKh2EZ9qj6IfHZIGXxiJF37emRCqnZwDhRb1+DJ4= +github.com/dontpanicdao/caigo v0.4.0/go.mod h1:1YuwgcVLODaS/n0vfuYN/Q0mdWs8UDfDMkSpUdkKXD4= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.11.5 h1:3M1uan+LAUvdn+7wCEFrcMM4LJTeuxDrPTg/f31a5QQ= +github.com/ethereum/go-ethereum v1.11.5/go.mod h1:it7x0DWnTDMfVFdXcU6Ti4KEFQynLHVRarcSlPr0HBo= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= +github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= +github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= +github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/goplugin/plugin-env v0.3.29 h1:hcIw/BeuB0wKiiE3umAUNBZzWkHO24XF3OW9xSrlMbI= +github.com/goplugin/plugin-env v0.3.29/go.mod h1:9c0Czq4a6wZKY20BcoAlK29DnejQIiLo/MwKYtSFnHk= +github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82 h1:FX7LW/czuotFwzfK3UavL7HkKQv6fn/5wzcZASdKWQ0= +github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82/go.mod h1:3E3PXaMEl2gADk/DTkbOxsvtpDcJ5ZSyW+vt0TjsEH0= +github.com/goplugin/plugin-testing-framework v1.11.5 h1:gYSnOQhLxgE0mxwnv015nNnPgH9kcosx+AzPboEFo38= +github.com/goplugin/plugin-testing-framework v1.11.5/go.mod h1:0ktPcDE5fFSvNewsaHuC4tGVaiCMQsl5RN/cWO5k0rg= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc h1:aSCDAai0Dmbhp/KHTtJnC/EJcaEz4CAO80SKRzRZiQA= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc/go.mod h1:5JnCHuYgmIP9ZyXzgAfI5Iwu0WxBtBKp+ApeT5o1Cjw= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A= +github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= +github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g= +go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= +gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= +k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= +k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k= +k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo= +k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= +k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= +k8s.io/cli-runtime v0.25.4 h1:GTSBN7aKBrc2LqpdO30CmHQqJtRmotxV7XsMSP+QZIk= +k8s.io/cli-runtime v0.25.4/go.mod h1:JGOw1CR8v4Mcz6cEKA7bFQe0bPrNn1l5sGAX1/Ke4Eg= +k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8= +k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= +k8s.io/component-base v0.25.4 h1:n1bjg9Yt+G1C0WnIDJmg2fo6wbEU1UGMRiQSjmj7hNQ= +k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/kubectl v0.25.4 h1:O3OA1z4V1ZyvxCvScjq0pxAP7ABgznr8UvnVObgI6Dc= +k8s.io/kubectl v0.25.4/go.mod h1:CKMrQ67Bn2YCP26tZStPQGq62zr9pvzEf65A0navm8k= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= +sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= +sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= +sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= +sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/ops/hardhat/environment.go b/ops/hardhat/environment.go new file mode 100644 index 0000000..9c29290 --- /dev/null +++ b/ops/hardhat/environment.go @@ -0,0 +1,108 @@ +package hardhat + +import ( + "fmt" + + "github.com/rs/zerolog/log" + "github.com/goplugin/plugin-env/client" + "github.com/goplugin/plugin-env/environment" + "github.com/goplugin/plugin-starknet/ops/utils" +) + +type Chart struct { + HelmProps *HelmProps + Props *Props +} +type Props struct { + NetworkName string `envconfig:"network_name"` + Simulated bool `envconfig:"network_simulated"` + HttpURLs []string `envconfig:"http_url"` + WsURLs []string `envconfig:"ws_url"` + Values map[string]any +} + +type HelmProps struct { + Name string + Path string + Values *map[string]any + Version string +} + +func (m Chart) IsDeploymentNeeded() bool { + return true +} + +func (m Chart) GetVersion() string { + return m.HelmProps.Version +} + +func (m Chart) GetProps() any { + return m.Props +} + +func (m Chart) GetName() string { + return m.HelmProps.Name +} + +func (m Chart) GetPath() string { + return m.HelmProps.Path +} + +func (m Chart) GetValues() *map[string]any { + return m.HelmProps.Values +} + +func (m Chart) ExportData(e *environment.Environment) error { + devnetLocalHttp, err := e.Fwd.FindPort("hardhat:0", "hardhat", "http").As(client.LocalConnection, client.HTTP) + if err != nil { + return err + } + devnetInternalHttp, err := e.Fwd.FindPort("hardhat:0", "hardhat", "http").As(client.RemoteConnection, client.HTTP) + if err != nil { + return err + } + e.URLs[m.Props.NetworkName] = append(e.URLs[m.Props.NetworkName], devnetLocalHttp) + e.URLs[m.Props.NetworkName] = append(e.URLs[m.Props.NetworkName], devnetInternalHttp) + log.Info().Str("Name", "Devnet").Str("URLs", devnetLocalHttp).Msg("Devnet network") + return nil +} + +func defaultProps() *Props { + return &Props{ + NetworkName: "hardhat", + Values: map[string]any{ + "replicas": "1", + "starknet-dev": map[string]any{ + "image": map[string]any{ + "image": "ethereumoptimism/hardhat-node", + "version": "nightly", + }, + "resources": map[string]any{ + "requests": map[string]any{ + "cpu": "1000m", + "memory": "1024Mi", + }, + "limits": map[string]any{ + "cpu": "1000m", + "memory": "1024Mi", + }, + }, + }, + }, + } +} + +func New(props *Props) environment.ConnectedChart { + if props == nil { + props = defaultProps() + } + return Chart{ + HelmProps: &HelmProps{ + Name: "hardhat", + Path: fmt.Sprintf("%s/charts/hardhat", utils.OpsRoot), + Values: &props.Values, + Version: "", + }, + Props: props, + } +} diff --git a/ops/localenv/README.md b/ops/localenv/README.md new file mode 100644 index 0000000..9da8d24 --- /dev/null +++ b/ops/localenv/README.md @@ -0,0 +1,49 @@ +# Simple Local Env CLI + +## Prerequisites +``` +k3d - local kubernetes cluster +docker - build local containers +kubectl - interact with kubernetes cluster +``` + +``` +make install +``` + +make sure gauntlet and contract artifacts are properly compiled +``` +yarn +make build-ts-contracts +``` + +## Commands +```bash + +# starts up a k3d environment with a local registry +go run main.go create + +# builds a local plugin image +# note: assumes a folder structure like Documents/plugin + Documents/plugin-starknet +go run main.go build + +# runs the go test environment using the locally compiled image +# note: the namespace is in the first few lines of logging +go run main.go run + +# removes the pods that were spun up during the `run` command +go run main.go stop + +# removes the entire k3d environment & registry +go run main.go delete +``` + +## Useful Commands & Tools +```bash +# pull logs from plugin node +# example: kubectl logs --namespace plugin-smoke-ocr-starknet-ci-4553f plugin-0-d79496974-kzczg -c node +# container is not needed if inspecting pod with single container (like starknet-devnet) +kubectl logs --namespace -c +``` + +Useful kubernetes cluster explorer - [Lens](https://k8slens.dev/) or [k9s](https://k9scli.io/)(lite weight, CLI based) diff --git a/ops/localenv/main.go b/ops/localenv/main.go new file mode 100644 index 0000000..38e34d4 --- /dev/null +++ b/ops/localenv/main.go @@ -0,0 +1,123 @@ +package main + +import ( + "errors" + "fmt" + "io" + "os" + "os/exec" + "strings" + "sync" + + "github.com/goplugin/plugin-starknet/ops/utils" +) + +// TODO: consider extracting entire file to `plugin-relay/ops` or into a separate CLI tool +// this simply runs underlying functions but does not import them + +// PODMAN: +// ~/.config/containers/registries.conf +// [[registry]] +// location = "localhost:12345" +// insecure = true + +func main() { + if len(os.Args) < 2 { + panic("missing required command") + } + + switch strings.ToLower(os.Args[1]) { + // create k8s cluster + resources + case "create": + run("create registry", "k3d", "registry", "create", "registry.localhost", "--port", "127.0.0.1:12345") + run("create k8s cluster", "k3d", "cluster", "create", "local", "--api-port", "127.0.0.1:12346", "--registry-use", "k3d-registry.localhost:12345") + run("switch k8s context", "kubectl", "config", "use-context", "k3d-local") + // build and upload image to local registry + case "build": + context := "../../../plugin" // TODO: make this an arg + run("build image", "docker", "build", "-f", context+"/core/plugin.Dockerfile", context, "-t", "plugin:local") + run("tag image", "docker", "tag", "plugin:local", "localhost:12345/plugin:local") + run("push image", "docker", "push", "localhost:12345/plugin:local") + // run ginkgo commands to spin up environment + case "run": + // move to repo root + if err := os.Chdir(utils.IntegrationTestsRoot); err != nil { + panic(err) + } + setEnvIfNotExists("PLUGIN_IMAGE", "k3d-registry.localhost:12345/plugin") + setEnvIfNotExists("PLUGIN_VERSION", "local") + setEnvIfNotExists("KEEP_ENVIRONMENTS", "ALWAYS") + setEnvIfNotExists("NODE_COUNT", "1") + setEnvIfNotExists("TTL", "900h") + run("start environment", "go", "test", "-count", "1", "-v", "-timeout", "30m", "--run", "^TestOCRBasic$", "./smoke") + // stop k8s namespace from environment + case "stop": + if len(os.Args) < 3 { + panic("missing namespace argument") + } + run("stopping environment", "kubectl", "delete", "namespaces", os.Args[2]) + // delete removes the k8s cluster + case "delete": + run("remove k8s cluster", "k3d", "cluster", "delete", "local") + run("remove registry", "k3d", "registry", "delete", "k3d-registry.localhost") + default: + panic("unrecognized command") + } +} + +func setEnvIfNotExists(key, defaultValue string) { + value := os.Getenv(key) + if value == "" { + os.Setenv(key, defaultValue) + value = defaultValue + } + fmt.Printf("Using %s=%s\n", key, value) +} + +func run(name string, f string, args ...string) { + fmt.Printf("\n-- %s --\n", strings.ToUpper(name)) + cmd := exec.Command(f, args...) + stdout, err := cmd.StdoutPipe() + if err != nil { + panic(err) + } + stderr, err := cmd.StderrPipe() + if err != nil { + panic(err) + } + + // stream output to cmd line + var wg sync.WaitGroup + wg.Add(2) + go func() { + p := make([]byte, 100) + for { + n, err := stdout.Read(p) + if errors.Is(err, io.EOF) { + wg.Done() + break + } + fmt.Print(string(p[:n])) + } + }() + go func() { + p := make([]byte, 100) + for { + n, err := stderr.Read(p) + if errors.Is(err, io.EOF) { + wg.Done() + break + } + fmt.Print(string(p[:n])) + } + }() + + if err := cmd.Start(); err != nil { + panic(err) + } + + wg.Wait() + if err := cmd.Wait(); err != nil { + panic(err) + } +} diff --git a/ops/plugin-starknet.yaml b/ops/plugin-starknet.yaml new file mode 100644 index 0000000..6b27753 --- /dev/null +++ b/ops/plugin-starknet.yaml @@ -0,0 +1,30 @@ +namespace_prefix: plugin-stark +charts: + geth: + index: 1 + starknet: + path: ./ops/charts/starknet + index: 1 + values: +# false = stark-devnet +# true = pathfinder, must provide goerli or mainnet url in "url_http_L1" env var +# uncomment +# real_node: true +# url_http_L1: "some goerli url" +# or + real_node: false +# you can also override image vars +# repository: "" +# tag: "" + mockserver-config: + index: 1 + mockserver: + index: 2 + plugin: + index: 2 + values: + replicas: 5 + plugin: + image: + image: "public.ecr.aws/plugin/plugin" + version: "latest" \ No newline at end of file diff --git a/ops/scripts/devnet-hardhat-down.sh b/ops/scripts/devnet-hardhat-down.sh new file mode 100755 index 0000000..57baa59 --- /dev/null +++ b/ops/scripts/devnet-hardhat-down.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# TODO: this script needs to be replaced with a predefined K8s enviroment + +echo "Cleaning up Starknet Devnet container..." + +dpid=`docker ps | grep plugin-starknet.starknet-devnet | awk '{print $1}'`; +echo "Checking for existing 'plugin-starknet.starknet-devnet' docker container..." +if [ -z "$dpid" ] +then + echo "No docker Starknet Devnet container running."; +else + docker kill $dpid; + docker rm $dpid; +fi + +echo "Cleaning up Hardhat container..." + +dpid=`docker ps | grep plugin-starknet.hardhat | awk '{print $1}'`; +echo "Checking for existing 'plugin-starknet.hardhat' docker container..." +if [ -z "$dpid" ] +then + echo "No docker Hardhat container running."; +else + docker kill $dpid; + docker rm $dpid; +fi + +echo "Cleanup finished." diff --git a/ops/scripts/devnet-hardhat.sh b/ops/scripts/devnet-hardhat.sh new file mode 100755 index 0000000..7559625 --- /dev/null +++ b/ops/scripts/devnet-hardhat.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# TODO: this script needs to be replaced with a predefined K8s enviroment + +cpu_struct=`arch`; +echo $cpu_struct; + +node --version; + +# Clean up first +bash "$(dirname -- "$0";)/devnet-hardhat-down.sh" + +echo "Checking CPU structure..." +if [[ $cpu_struct == *"arm"* ]] +then + echo "Starting arm devnet container..." + docker run -p 5050:5050 -p 8545:8545 -d --name plugin-starknet.starknet-devnet shardlabs/starknet-devnet:0.5.0; +else + echo "Starting i386 devnet container..." + docker run -p 5050:5050 -p 8545:8545 -d --name plugin-starknet.starknet-devnet shardlabs/starknet-devnet:0.5.0; +fi + +echo "Starting hardhat..." +docker run --net container:plugin-starknet.starknet-devnet -d --name plugin-starknet.hardhat ethereumoptimism/hardhat-node:nightly diff --git a/ops/test_helpers.go b/ops/test_helpers.go new file mode 100644 index 0000000..b223222 --- /dev/null +++ b/ops/test_helpers.go @@ -0,0 +1,112 @@ +package ops + +import ( + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/txm" +) + +var ( + // seed = 0 keys for starknet-devnet + PrivateKeys0Seed = txm.PrivateKeys0Seed + + DevnetClassHash = txm.DevnetClassHash + DevnetSalt = txm.DevnetSalt +) + +// OCR2Config Default config for OCR2 for starknet +type OCR2Config struct { + F int `json:"f"` + Signers []string `json:"signers"` + Transmitters []string `json:"transmitters"` + OnchainConfig string `json:"onchainConfig"` + OffchainConfig *OffchainConfig `json:"offchainConfig"` + OffchainConfigVersion int `json:"offchainConfigVersion"` + Secret string `json:"secret"` +} + +type OffchainConfig struct { + DeltaProgressNanoseconds int64 `json:"deltaProgressNanoseconds"` + DeltaResendNanoseconds int64 `json:"deltaResendNanoseconds"` + DeltaRoundNanoseconds int64 `json:"deltaRoundNanoseconds"` + DeltaGraceNanoseconds int `json:"deltaGraceNanoseconds"` + DeltaStageNanoseconds int64 `json:"deltaStageNanoseconds"` + RMax int `json:"rMax"` + S []int `json:"s"` + OffchainPublicKeys []string `json:"offchainPublicKeys"` + PeerIds []string `json:"peerIds"` + ReportingPluginConfig *ReportingPluginConfig `json:"reportingPluginConfig"` + MaxDurationQueryNanoseconds int `json:"maxDurationQueryNanoseconds"` + MaxDurationObservationNanoseconds int `json:"maxDurationObservationNanoseconds"` + MaxDurationReportNanoseconds int `json:"maxDurationReportNanoseconds"` + MaxDurationShouldAcceptFinalizedReportNanoseconds int `json:"maxDurationShouldAcceptFinalizedReportNanoseconds"` + MaxDurationShouldTransmitAcceptedReportNanoseconds int `json:"maxDurationShouldTransmitAcceptedReportNanoseconds"` + ConfigPublicKeys []string `json:"configPublicKeys"` +} + +type ReportingPluginConfig struct { + AlphaReportInfinite bool `json:"alphaReportInfinite"` + AlphaReportPpb int `json:"alphaReportPpb"` + AlphaAcceptInfinite bool `json:"alphaAcceptInfinite"` + AlphaAcceptPpb int `json:"alphaAcceptPpb"` + DeltaCNanoseconds int `json:"deltaCNanoseconds"` +} + +var TestOCR2Config = OCR2Config{ + F: 1, + // Signers: onChainKeys, // user defined + // Transmitters: txKeys, // user defined + OnchainConfig: "", + OffchainConfig: &OffchainConfig{ + DeltaProgressNanoseconds: 8000000000, + DeltaResendNanoseconds: 30000000000, + DeltaRoundNanoseconds: 3000000000, + DeltaGraceNanoseconds: 500000000, + DeltaStageNanoseconds: 20000000000, + RMax: 5, + S: []int{1, 2}, + // OffchainPublicKeys: offChainKeys, // user defined + // PeerIds: peerIds, // user defined + ReportingPluginConfig: &ReportingPluginConfig{ + AlphaReportInfinite: false, + AlphaReportPpb: 0, + AlphaAcceptInfinite: false, + AlphaAcceptPpb: 0, + DeltaCNanoseconds: 0, + }, + MaxDurationQueryNanoseconds: 0, + MaxDurationObservationNanoseconds: 1000000000, + MaxDurationReportNanoseconds: 200000000, + MaxDurationShouldAcceptFinalizedReportNanoseconds: 200000000, + MaxDurationShouldTransmitAcceptedReportNanoseconds: 200000000, + // ConfigPublicKeys: cfgKeys, // user defined + }, + OffchainConfigVersion: 2, + Secret: "awe accuse polygon tonic depart acuity onyx inform bound gilbert expire", +} + +var TestOnKeys = []string{ + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603730", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603731", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603732", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603733", +} + +var TestTxKeys = []string{ + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603734", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603735", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603736", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603737", +} + +var TestOffKeys = []string{ + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852090", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852091", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852092", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852093", +} + +var TestCfgKeys = []string{ + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852094", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852095", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852096", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852097", +} diff --git a/ops/utils/project_path.go b/ops/utils/project_path.go new file mode 100644 index 0000000..2ba241b --- /dev/null +++ b/ops/utils/project_path.go @@ -0,0 +1,16 @@ +package utils + +import ( + "path/filepath" + "runtime" +) + +var ( + _, b, _, _ = runtime.Caller(0) + // ProjectRoot Root folder of this project + ProjectRoot = filepath.Join(filepath.Dir(b), "/../..") + // SolanaTestsRoot path to starknet e2e tests + IntegrationTestsRoot = filepath.Join(ProjectRoot, "integration-tests") + // OpsRoot path to ops folder + OpsRoot = filepath.Join(ProjectRoot, "ops") +) diff --git a/package.json b/package.json new file mode 100644 index 0000000..49a64f9 --- /dev/null +++ b/package.json @@ -0,0 +1,61 @@ +{ + "name": "plugin-starknet", + "private": true, + "version": "0.0.1", + "description": "Plugin's Starknet integration monorepo", + "workspaces": [ + "contracts", + "examples/contracts/*", + "packages-ts/*" + ], + "keywords": [ + "typescript", + "cli" + ], + "main": "packages-ts/starknet-gauntlet-cli/dist/index.js", + "bin": "packages-ts/starknet-gauntlet-cli/dist/index.js", + "scripts": { + "gauntlet": "yarn build && node ./packages-ts/starknet-gauntlet-cli/dist/index.js", + "test": "yarn build && yarn workspaces run test", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "lint": "tsc -b ./tsconfig.json", + "format": "yarn prettier --write .", + "format:check": "yarn prettier --check .", + "clean": "tsc -b --clean ./tsconfig.json", + "build": "yarn clean && tsc -b ./tsconfig.json", + "bundle": "yarn build && pkg . --no-native-build", + "release": "yarn changeset publish" + }, + "pkg": { + "scripts": [ + "packages-ts/starknet-gauntlet-cli/dist/index.js" + ], + "targets": [ + "linux", + "macos" + ], + "outputPath": "bin", + "assets": [ + "node_modules/@pluginv3.0-dev", + "packages-ts/*/contract_artifacts/**/*", + "packages-ts/starknet-gauntlet-cli/networks/" + ] + }, + "devDependencies": { + "@changesets/cli": "^2.22.0", + "@types/bn.js": "^5.1.1", + "@types/jest": "^28.1.0", + "@types/node": "^18.7.11", + "bn.js": "^5.2.1", + "jest": "^28.1.0", + "pkg": "^5.2.1", + "prettier": "2.1.1", + "ts-jest": "^28.0.7", + "ts-node": "^10.8.0", + "typescript": "4.7.2" + }, + "dependencies": { + "starknet": "^5.2.0" + } +} diff --git a/packages-ts/integration-eqlabs-multisig/hardhat.config.ts b/packages-ts/integration-eqlabs-multisig/hardhat.config.ts new file mode 100644 index 0000000..ba93e3e --- /dev/null +++ b/packages-ts/integration-eqlabs-multisig/hardhat.config.ts @@ -0,0 +1,29 @@ +import { HardhatUserConfig } from 'hardhat/types' +import '@shardlabs/starknet-hardhat-plugin' + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +const config: HardhatUserConfig = { + starknet: { + venv: 'active', + network: 'devnet', + wallets: { + OpenZeppelin: { + accountName: 'OpenZeppelin', + modulePath: 'starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount', + accountPath: '~/.starknet_accounts', + }, + }, + }, + networks: { + devnet: { + url: 'http://127.0.0.1:5050/', + }, + }, + paths: { + starknetArtifacts: '../../node_modules/starsign-multisig/starknet-artifacts/contracts', + }, +} + +export default config diff --git a/packages-ts/integration-eqlabs-multisig/package.json b/packages-ts/integration-eqlabs-multisig/package.json new file mode 100644 index 0000000..8202297 --- /dev/null +++ b/packages-ts/integration-eqlabs-multisig/package.json @@ -0,0 +1,24 @@ +{ + "name": "@pluginv3.0/starknet-integration-tests-eqlabs-multisig", + "version": "1.0.0", + "description": "Multisig integration test", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "npx hardhat --network localhost test" + }, + "devDependencies": { + "@changesets/cli": "^2.22.0", + "@nomiclabs/hardhat-ethers": "^2.0.5", + "@shardlabs/starknet-hardhat-plugin": "^0.8.0-alpha.0", + "@types/chai": "^4.3.3", + "@types/elliptic": "^6.4.14", + "@types/mocha": "^9.1.1", + "chai": "^4.3.6", + "ethers": "^5.6.8", + "hardhat": "^2.10.2", + "starsign-multisig": "^0.3.0" + } +} diff --git a/packages-ts/integration-eqlabs-multisig/test/Multisig.test.ts b/packages-ts/integration-eqlabs-multisig/test/Multisig.test.ts new file mode 100644 index 0000000..4210dcb --- /dev/null +++ b/packages-ts/integration-eqlabs-multisig/test/Multisig.test.ts @@ -0,0 +1,88 @@ +import { expect } from 'chai' +import { starknet } from 'hardhat' +import { StarknetContract, Account } from 'hardhat/types/runtime' +import { num, hash } from 'starknet' +import { account } from '@pluginv3.0/starknet' + +describe('Multisig integration tests', function () { + this.timeout(300_000) + + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + let account1: Account + let account2: Account + let account3: Account + + let multisig: StarknetContract + + before(async function () { + account1 = await starknet.OpenZeppelinAccount.createAccount() + account2 = await starknet.OpenZeppelinAccount.createAccount() + account3 = await starknet.OpenZeppelinAccount.createAccount() + + await funder.fund([ + { account: account1.address, amount: 1e21 }, + { account: account2.address, amount: 1e21 }, + { account: account3.address, amount: 1e21 }, + ]) + await account1.deployAccount() + await account2.deployAccount() + await account3.deployAccount() + }) + + it('Deploy contract', async () => { + let multisigFactory = await starknet.getContractFactory('Multisig') + await account1.declare(multisigFactory) + + multisig = await account1.deploy(multisigFactory, { + signers: [ + num.toBigInt(account1.starknetContract.address), + num.toBigInt(account2.starknetContract.address), + num.toBigInt(account3.starknetContract.address), + ], + threshold: 2, + }) + + expect(multisig).to.be.ok + }) + + it('should submit & confirm transaction', async () => { + const nonce = 0 + const newThreshold = 1n + const selector = hash.getSelectorFromName('set_threshold') + + const payload = { + to: multisig.address, + function_selector: selector, + calldata: [newThreshold], + nonce, + } + + { + const res = await account1.invoke(multisig, 'submit_transaction', payload) + const txReciept = await starknet.getTransactionReceipt(res) + + expect(txReciept.events.length).to.equal(2) + expect(txReciept.events[0].data.length).to.equal(3) + expect(txReciept.events[0].data[1]).to.equal(num.toHex(num.toBigInt(nonce, 'hex'))) + } + + await account1.invoke(multisig, 'confirm_transaction', { + nonce, + }) + + await account2.invoke(multisig, 'confirm_transaction', { + nonce, + }) + + await account3.invoke(multisig, 'execute_transaction', { + nonce, + }) + + { + const res = await multisig.call('get_threshold') + expect(res.threshold).to.equal(newThreshold) + } + }) +}) diff --git a/packages-ts/integration-eqlabs-multisig/tsconfig.json b/packages-ts/integration-eqlabs-multisig/tsconfig.json new file mode 100644 index 0000000..8ac8056 --- /dev/null +++ b/packages-ts/integration-eqlabs-multisig/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["./test"], + "files": ["./hardhat.config.ts"] + } + \ No newline at end of file diff --git a/packages-ts/starknet-gauntlet-argent/LICENSE b/packages-ts/starknet-gauntlet-argent/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-argent/README.md b/packages-ts/starknet-gauntlet-argent/README.md new file mode 100644 index 0000000..864ad4e --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/README.md @@ -0,0 +1,31 @@ +# Starknet Gauntlet Commands for Argent Contracts + +## Account + +### Deploy + +``` +yarn gauntlet argent_account:deploy --network= +``` + +Note the contract address. The contract is not configured yet. A signer needs to be specified in it: + +### Initialize + +```bash +yarn gauntlet argent_account:initialize --network= +# OR If you already have a private key +yarn gauntlet argent_account:initialize --network= --publicKey= +``` + +If no public key is provided, the command will generate a new Keypair and will give the details during the execution. + +You need to pay some fee to call initialize, but as this could be the first account wallet you are deploying, use the `--noWallet` option to bypass the fee. This will be soon deprecated + +At the end of the process, you will want to include the account contract and the private key to your `.env` configuration file. + +```bash +# .env +PRIVATE_KEY=0x... +ACCOUNT=0x... +``` diff --git a/packages-ts/starknet-gauntlet-argent/package.json b/packages-ts/starknet-gauntlet-argent/package.json new file mode 100644 index 0000000..bafbbc8 --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/package.json @@ -0,0 +1,31 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-argent", + "version": "0.0.1", + "description": "Starknet Gauntlet Argent contracts", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-argent --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/starknet-gauntlet": "*" + } +} diff --git a/packages-ts/starknet-gauntlet-argent/src/commands/account/deploy.ts b/packages-ts/starknet-gauntlet-argent/src/commands/account/deploy.ts new file mode 100644 index 0000000..290d56e --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/src/commands/account/deploy.ts @@ -0,0 +1,49 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + ExecutionContext, + makeExecuteCommand, + Validation, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { accountContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = {} + +type ContractInput = [] + +const makeUserInput = async (flags, args): Promise => ({}) + +const makeContractInput = async ( + input: UserInput, + context: ExecutionContext, +): Promise => { + return [] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info(`About to deploy an Argent Account Contract`) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.ACCOUNT, + category: CATEGORIES.ACCOUNT, + action: 'deploy', + ux: { + description: 'Deploys an Argent Labs Account contract', + examples: [`${CATEGORIES.ACCOUNT}:deploy --network=`], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: accountContractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-argent/src/commands/account/index.ts b/packages-ts/starknet-gauntlet-argent/src/commands/account/index.ts new file mode 100644 index 0000000..dc9ac9a --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/src/commands/account/index.ts @@ -0,0 +1,4 @@ +import Deploy from './deploy' +import Initialize from './initialize' + +export default [Deploy, Initialize] diff --git a/packages-ts/starknet-gauntlet-argent/src/commands/account/initialize.ts b/packages-ts/starknet-gauntlet-argent/src/commands/account/initialize.ts new file mode 100644 index 0000000..674d6cb --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/src/commands/account/initialize.ts @@ -0,0 +1,84 @@ +import { + AfterExecute, + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, + Validation, +} from '@pluginv3.0/starknet-gauntlet' +import { ec } from 'starknet' +import { CATEGORIES } from '../../lib/categories' +import { accountContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + publicKey: string + privateKey?: string +} + +type ContractInput = [string, 0] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + // If public key is not provided, generate a new address + const keypair = ec.starkCurve.utils.randomPrivateKey() + const generatedPK = '0x' + Buffer.from(keypair).toString('hex') + const pubkey = flags.publicKey || ec.starkCurve.getStarkKey(keypair) + return { + publicKey: pubkey, + privateKey: !flags.publicKey && generatedPK, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.publicKey, 0] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info(`About to deploy an Account Contract with public key ${input.contract[0]}`) + if (input.user.privateKey) { + await deps.prompt(`The generated private key will be shown next, continue?`) + deps.logger.line() + + deps.logger.info(`To sign future transactions, store the Private Key`) + deps.logger.info(`PRIVATE_KEY: ${input.user.privateKey}`) + + deps.logger.line() + } +} + +const afterExecute: AfterExecute = (context, input, deps) => async ( + result, +) => { + deps.logger.success(`Account contract located at ${result.responses[0].tx.address}`) + return { + publicKey: input.user.publicKey, + privateKey: input.user.privateKey, + } +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.ACCOUNT, + category: CATEGORIES.ACCOUNT, + action: 'initialize', + ux: { + description: + 'Initializes an Argent Account Contract (Generates a public/private key for account)', + examples: [ + `${CATEGORIES.ACCOUNT}:initialize --network= --publicKey=
`, + ], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: accountContractLoader, + hooks: { + beforeExecute, + afterExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-argent/src/commands/index.ts b/packages-ts/starknet-gauntlet-argent/src/commands/index.ts new file mode 100644 index 0000000..4924c4a --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/src/commands/index.ts @@ -0,0 +1,3 @@ +import Account from './account' + +export default [...Account] diff --git a/packages-ts/starknet-gauntlet-argent/src/index.ts b/packages-ts/starknet-gauntlet-argent/src/index.ts new file mode 100644 index 0000000..66ccd58 --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/src/index.ts @@ -0,0 +1,3 @@ +import Commands from './commands' + +export { Commands } diff --git a/packages-ts/starknet-gauntlet-argent/src/lib/categories.ts b/packages-ts/starknet-gauntlet-argent/src/lib/categories.ts new file mode 100644 index 0000000..e9005bb --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/src/lib/categories.ts @@ -0,0 +1,5 @@ +import { CONTRACT_LIST } from './contracts' + +export const CATEGORIES = { + ACCOUNT: CONTRACT_LIST.ACCOUNT, +} diff --git a/packages-ts/starknet-gauntlet-argent/src/lib/contracts.ts b/packages-ts/starknet-gauntlet-argent/src/lib/contracts.ts new file mode 100644 index 0000000..8194ef5 --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/src/lib/contracts.ts @@ -0,0 +1,14 @@ +import fs from 'fs' +import { CompiledContract, json } from 'starknet' + +export enum CONTRACT_LIST { + ACCOUNT = 'argent_account', +} + +export const loadContract = (name: CONTRACT_LIST): CompiledContract => { + return json.parse( + fs.readFileSync(`${__dirname}/../../artifacts/abi/${name}.json`).toString('ascii'), + ) +} + +export const accountContractLoader = () => loadContract(CONTRACT_LIST.ACCOUNT) diff --git a/packages-ts/starknet-gauntlet-argent/tsconfig.json b/packages-ts/starknet-gauntlet-argent/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-argent/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-cli/LICENSE b/packages-ts/starknet-gauntlet-cli/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-cli/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-cli/README.md b/packages-ts/starknet-gauntlet-cli/README.md new file mode 100644 index 0000000..ac78265 --- /dev/null +++ b/packages-ts/starknet-gauntlet-cli/README.md @@ -0,0 +1,39 @@ +# Starknet Gauntlet CLI + +This packages expose the commands to be used as a CLI of the following packages: + +- @pluginv3.0/starknet-gauntlet-example +- @pluginv3.0/starknet-gauntlet-account +- @pluginv3.0/starknet-gauntlet-ocr2 + +## Setup + +Every command accepts the `--network=` flag. The value will load the static environment variables under `./networks/.env.`. Currently 2 network configurations are available: + +1. Local + +```bash +NODE_URL=http://127.0.0.1:5000 +``` + +2. Testnet + +```bash +NODE_URL=https://alpha4.starknet.io +``` + +## Miscellaneous + +- To show available methods for all contracts: + +``` +yarn gauntlet -h +``` + +-To show available methods for a single contract: + +``` +yarn gauntlet ocr2:deploy -h +``` + +It will show details for the specificed function with their needed parameters and their types, if any diff --git a/packages-ts/starknet-gauntlet-cli/networks/.env.goerli b/packages-ts/starknet-gauntlet-cli/networks/.env.goerli new file mode 100644 index 0000000..2840fba --- /dev/null +++ b/packages-ts/starknet-gauntlet-cli/networks/.env.goerli @@ -0,0 +1,7 @@ + +# alternative public endpoints +#NODE_URL=https://goerli.prylabs.net +#NODE_URL=https://rpc.goerli.mudit.blog +#NODE_URL=https://rpc.slock.it/goerli +#NODE_URL=https://www.ethercluster.com/goerli +NODE_URL=https://rpc.ankr.com/eth_goerli diff --git a/packages-ts/starknet-gauntlet-cli/networks/.env.local b/packages-ts/starknet-gauntlet-cli/networks/.env.local new file mode 100644 index 0000000..494d52c --- /dev/null +++ b/packages-ts/starknet-gauntlet-cli/networks/.env.local @@ -0,0 +1 @@ +NODE_URL=http://127.0.0.1:5050 \ No newline at end of file diff --git a/packages-ts/starknet-gauntlet-cli/package.json b/packages-ts/starknet-gauntlet-cli/package.json new file mode 100644 index 0000000..8b17aa9 --- /dev/null +++ b/packages-ts/starknet-gauntlet-cli/package.json @@ -0,0 +1,38 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-cli", + "version": "0.0.1", + "description": "Starknet Gauntlet CLI", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-cli --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/starknet-gauntlet-oz": "*", + "@pluginv3.0/starknet-gauntlet-argent": "*", + "@pluginv3.0/starknet-gauntlet-example": "*", + "@pluginv3.0/starknet-gauntlet-ocr2": "*", + "@pluginv3.0/starknet-gauntlet-token": "*", + "@pluginv3.0/starknet-gauntlet-multisig": "*", + "@pluginv3.0/starknet-gauntlet-emergency-protocol": "*", + "@pluginv3.0/starknet-gauntlet-ledger": "*" + } +} diff --git a/packages-ts/starknet-gauntlet-cli/src/index.ts b/packages-ts/starknet-gauntlet-cli/src/index.ts new file mode 100644 index 0000000..fae1de1 --- /dev/null +++ b/packages-ts/starknet-gauntlet-cli/src/index.ts @@ -0,0 +1,174 @@ +import { + executeCommands as OCR2ExecuteCommands, + inspectionCommands as OCR2InspectionCommands, +} from '@pluginv3.0/starknet-gauntlet-ocr2' +import { + executeCommands as ExampleExecuteCommands, + inspectionCommands as ExampleInspectionsCommands, +} from '@pluginv3.0/starknet-gauntlet-example' +import { Commands as OZCommands } from '@pluginv3.0/starknet-gauntlet-oz' +import { + L2Commands as L2StarkgateCommands, + InspectionCommands as StarkgateInspectionCommands, +} from '@pluginv3.0/starknet-gauntlet-token' +import { Commands as ArgentCommands } from '@pluginv3.0/starknet-gauntlet-argent' +import { + L1Commands as L1EmergencyProtocolCommands, + L2Commands as L2EmergencyProtocolCommands, + L2InspectionCommands as L2EmergencyProtocolInspectionCommands, +} from '@pluginv3.0/starknet-gauntlet-emergency-protocol' +import { + executeCommands as MultisigExecuteCommands, + inspectionCommands as MultisigInspectionCommands, + wrapCommand as multisigWrapCommand, +} from '@pluginv3.0/starknet-gauntlet-multisig' + +import { executeCLI } from '@pluginv3.0/gauntlet-core' +import { existsSync } from 'fs' +import path from 'path' +import { io, logger, prompt } from '@pluginv3.0/gauntlet-core/dist/utils' +import { + CommandCtor, + Dependencies, + Env, + ExecuteCommandInstance, + InspectCommandInstance, + makeProvider, + makeWallet as makeDefaultWallet, +} from '@pluginv3.0/starknet-gauntlet' +import { + EVMExecuteCommandInstance, + CommandCtor as EVMCommandCtor, + makeWallet as EVMMakeWallet, + makeProvider as EVMMakeProvider, + EVMDependencies, +} from '@pluginv3.0/evm-gauntlet' +import { makeWallet as makeLedgerWallet } from '@pluginv3.0/starknet-gauntlet-ledger' + +export const noopPrompt: typeof prompt = async () => {} + +const registerExecuteCommand = ( + registerCommand: (deps: Dependencies) => CommandCtor>, + emptyPrompt = false, +) => { + const deps: Dependencies | Omit = { + logger: logger, + prompt: emptyPrompt ? noopPrompt : prompt, + makeEnv: (flags) => { + const env: Env = { + providerUrl: process.env.NODE_URL, + pk: process.env.PRIVATE_KEY, + publicKey: process.env.PUBLIC_KEY, + account: process.env.ACCOUNT, + multisig: process.env.MULTISIG, + billingAccessController: process.env.BILLING_ACCESS_CONTROLLER, + link: process.env.PLI, + secret: flags.secret || process.env.SECRET, + withLedger: !!flags.withLedger || !!process.env.WITH_LEDGER, + ledgerPath: (flags.ledgerPath as string) || process.env.LEDGER_PATH, + } + return env + }, + makeProvider: makeProvider, + makeWallet: async (env: Env) => { + if (env.withLedger) { + return makeLedgerWallet(env) + } + + return makeDefaultWallet(env) + }, + } + return registerCommand(deps) +} + +const registerEVMExecuteCommand = >( + registerCommand: (deps: EVMDependencies) => EVMCommandCtor>, + gauntletConfig, +) => { + const deps: EVMDependencies = { + logger: logger, + prompt: prompt, + makeEnv: (flags) => { + return { + providerUrl: process.env.NODE_URL, + pk: process.env.PRIVATE_KEY, + } + }, + makeProvider: EVMMakeProvider, + makeWallet: EVMMakeWallet, + } + return registerCommand(deps) +} + +const registerInspectionCommand = ( + registerCommand: ( + deps: Omit, + ) => CommandCtor>, +) => { + const deps: Omit = { + logger: logger, + prompt: prompt, + makeEnv: (flags) => { + const env: Env = { + providerUrl: process.env.NODE_URL, + } + return env + }, + makeProvider: makeProvider, + } + return registerCommand(deps) +} + +const L1ExecuteCommands: any[] = [...L1EmergencyProtocolCommands] +const L2ExecuteCommands = [ + ...OCR2ExecuteCommands, + ...ExampleExecuteCommands, + ...OZCommands, + ...L2StarkgateCommands, + ...ArgentCommands, + ...MultisigExecuteCommands, + ...L2EmergencyProtocolCommands, +] + +const msigCommands = L2ExecuteCommands.map((c) => registerExecuteCommand(c, true)).map( + multisigWrapCommand, +) +const unregistedInspectionCommands = [ + ...ExampleInspectionsCommands, + ...MultisigInspectionCommands, + ...OCR2InspectionCommands, + ...L2EmergencyProtocolInspectionCommands, + ...StarkgateInspectionCommands, +] + +const commands = { + custom: [ + ...L2ExecuteCommands.map((c) => registerExecuteCommand(c)), + ...L1ExecuteCommands.map((c) => registerEVMExecuteCommand(c, null)), + ...msigCommands.map((c) => registerExecuteCommand(c)), + ...unregistedInspectionCommands.map(registerInspectionCommand), + ], + loadDefaultFlags: () => ({}), + abstract: { + findPolymorphic: () => undefined, + makeCommand: () => undefined, + }, +} +;(async () => { + try { + const networkPossiblePaths = [ + path.join(process.cwd(), 'networks'), + path.join(__dirname, '../networks'), + ] + const networkPath = networkPossiblePaths.filter((networkPath) => existsSync(networkPath))[0] + const result = await executeCLI(commands, networkPath) + if (result) { + io.saveJSON(result, process.env['REPORT_NAME'] ? process.env['REPORT_NAME'] : 'report') + } + process.exit(0) + } catch (e) { + console.log(e) + console.log('Starknet Command execution error', e.message) + process.exitCode = 1 + } +})() diff --git a/packages-ts/starknet-gauntlet-cli/tsconfig.json b/packages-ts/starknet-gauntlet-cli/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-cli/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/LICENSE b/packages-ts/starknet-gauntlet-emergency-protocol/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/README.md b/packages-ts/starknet-gauntlet-emergency-protocol/README.md new file mode 100644 index 0000000..54ca2bb --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/README.md @@ -0,0 +1,93 @@ +# Starknet Gauntlet Commands to manage the Starknet Emergency Protocol + +This package contains the commands required to manage the contracts related to the Starknet Emergency Protocol + +## Commands + +### StarknetValidator + +- Deploy + +This deploys a new instance of the `StarknetValidator` contract on **L1** + +`` is address of the official Starkware Industries deployed messaging contract (ex: 0xde29d060D45901Fb19ED6C6e959EB22d8626708e on goerli testnet) + +`` is address of access controller which can modify the StarknetValidator config + +`` is adddress of fast gas data feed (ex: 0x169E633A2D1E6c10dD91238Ba11c4A708dfEF37C on mainnet) + +`` is the address of source aggregator. Source aggregator should be added to access control of starknet validator contract to be able to call +`validate` on the starknet validator + +`` is a number that represents l1 gas estimate + +`` is the layer 2 feed + +```bash +yarn gauntlet starknet_validator:deploy --starkNetMessaging= --configAC= --gasPriceL1Feed= --source= --gasEstimate= --l2Feed= --network= +``` + +- Accept Ownership + +Will accept ownership of the contract. This should be done after the current owner transfers ownership. + +```bash +yarn gauntlet starknet_validator:accept_ownership --network= +``` + +- Transfers Ownership + +Will transfer ownership to a new owner. The new owner must accept ownership to take control of the contract. + +```bash +yarn gauntlet starknet_validator:transfer_ownership --to= --network= +``` + +- Add Access + +Allows an address to write to the validator + +```bash +yarn gauntlet starknet_validator:add_access --address=
--network= +``` + +- Validate + +Calls validate on the validator contract + +```bash +yarn gauntlet starknet_validator:validate --previousRoundId= --previousAnswer= --currentRoundId= --currentAnswer= --network= + +``` + +### Sequencer Uptime Feed + +- Deploy + +This deploys a new `sequencer_uptime_feed` contract to L2. + +`` can be 0 or 1. 0 means that feed is healthy and up. + +`--owner` flag can be omitted. In such a case, it will default to the account specified in .env + +```bash +yarn gauntlet sequencer_uptime_feed:deploy --initialStatus= --owner= --network= +``` + +- setL1Sender + +This sets the L1 sender address. This is to control, which L1 address can write new statuses to the uptime feed. + +--address is the L1 sender address, which should be the deployed StarknetValidator.sol contract + +```bash +yarn gauntlet sequencer_uptime_feed:set_l1_sender --network= --address=
+``` + +- Inspect + +Inspect the latest round data + +```bash +yarn gauntlet sequencer_uptime_feed:inspect --network= +``` diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/package.json b/packages-ts/starknet-gauntlet-emergency-protocol/package.json new file mode 100644 index 0000000..2dd4384 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/package.json @@ -0,0 +1,32 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-emergency-protocol", + "version": "0.0.1", + "description": "Starknet Gauntlet Emergency Protocol", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-emergency-protocol --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "lint:format": "yarn prettier --check ./src", + "format": "yarn prettier --write ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/evm-gauntlet": "0.1.0", + "@pluginv3.0/starknet-gauntlet": "*" + } +} diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/index.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/index.ts new file mode 100644 index 0000000..80207ca --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/index.ts @@ -0,0 +1,9 @@ +import { + executionCommands as UptimeFeedCommands, + inspectionCommands as UptimeInspectionCommands, +} from './sequencerUptimeFeed' +import StarknetValidatorCommands from './starknetValidator' + +export const L1Commands = [...StarknetValidatorCommands] +export const L2Commands = [...UptimeFeedCommands] +export const L2InspectionCommands = [...UptimeInspectionCommands] diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/deploy.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/deploy.ts new file mode 100644 index 0000000..af969de --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/deploy.ts @@ -0,0 +1,60 @@ +import { + ExecuteCommandConfig, + isValidAddress, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { CONTRACT_LIST, uptimeFeedContractLoader } from '../../lib/contracts' +import { CATEGORIES } from '../../lib/categories' + +type ContractInput = [initial_status: number, owner_address: string] + +export interface UserInput { + initialStatus: number + owner?: string +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.initialStatus, input.owner] +} + +const validateOwner = async (input) => { + if (!isValidAddress(input.owner)) { + throw new Error(`Invalid Owner Address: ${input.owner}`) + } + return true +} + +const validateInitialStatus = async (input) => { + const status = Number(input.initialStatus) + if (status !== 1 && status !== 0) { + throw new Error(`Invalid Initial Status: ${input.initialStatus}`) + } + return true +} + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return { + owner: flags.owner || env.account, + initialStatus: flags.initialStatus, + } +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.SEQUENCER_UPTIME_FEED, + category: CATEGORIES.SEQUENCER_UPTIME_FEED, + action: 'deploy', + ux: { + description: 'Deploys a SequencerUptimeFeed contract', + examples: [ + `${CATEGORIES.SEQUENCER_UPTIME_FEED}:deploy --initialStatus= --network=`, + `${CATEGORIES.SEQUENCER_UPTIME_FEED}:deploy --initialStatus= --owner= --network=`, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateOwner, validateInitialStatus], + loadContract: uptimeFeedContractLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/index.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/index.ts new file mode 100644 index 0000000..8618d2f --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/index.ts @@ -0,0 +1,7 @@ +import Deploy from './deploy' +import SetL1Sender from './setL1Sender' + +import Inspection from './inspection' + +export const executionCommands = [Deploy, SetL1Sender] +export const inspectionCommands = [...Inspection] diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/index.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/index.ts new file mode 100644 index 0000000..b99d0d0 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/index.ts @@ -0,0 +1,3 @@ +import Inspect from './inspection' + +export default [Inspect] diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/inspection.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/inspection.ts new file mode 100644 index 0000000..c091af3 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/inspection/inspection.ts @@ -0,0 +1,57 @@ +import { + InspectCommandConfig, + IStarknetProvider, + makeInspectionCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { BN } from 'bn.js' +import { CATEGORIES } from '../../../lib/categories' +import { uptimeFeedContractLoader } from '../../../lib/contracts' + +type Round = { + round_id: number + answer: number + block_num: number + started_at: number + updated_at: number +} + +type QueryResult = { + latest_round_data: Round +} + +const makeComparisionData = (provider: IStarknetProvider) => async ( + results: any[], + input: null, + contractAddress: string, +): Promise<{ + toCompare: null + result: QueryResult +}> => { + let [{ round: latest_round_data }]: { round: Round }[] = results + + for (var key in latest_round_data) { + if (latest_round_data.hasOwnProperty(key)) { + latest_round_data[key] = new BN(latest_round_data[key]).toString() + } + } + + return { + toCompare: null, + result: { + latest_round_data: latest_round_data, + }, + } +} + +const commandConfig: InspectCommandConfig = { + ux: { + category: CATEGORIES.SEQUENCER_UPTIME_FEED, + function: 'inspect', + examples: [`${CATEGORIES.SEQUENCER_UPTIME_FEED}:inspect --network=`], + }, + queries: ['latest_round_data'], + makeComparisionData, + loadContract: uptimeFeedContractLoader, +} + +export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/setL1Sender.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/setL1Sender.ts new file mode 100644 index 0000000..f1e135f --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/sequencerUptimeFeed/setL1Sender.ts @@ -0,0 +1,49 @@ +import { + ExecuteCommandConfig, + isValidAddress, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { CONTRACT_LIST, uptimeFeedContractLoader } from '../../lib/contracts' + +type ContractInput = [address: string] + +export interface SetL1SenderInput { + address: string +} + +const validateAddress = async (input) => { + if (!isValidAddress(input.address)) { + throw new Error(`Invalid L1 Sender Address: ${input.address}`) + } + return true +} + +const makeUserInput = async (flags): Promise => { + if (flags.input) return flags.input as SetL1SenderInput + return { + address: flags.address, + } +} + +const makeContractInput = async (input: SetL1SenderInput): Promise => { + return [input.address] +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.SEQUENCER_UPTIME_FEED, + category: CATEGORIES.SEQUENCER_UPTIME_FEED, + action: 'set_l1_sender', + ux: { + description: 'Sets the L1 sender address on the SequencerUptimeFeed contract', + examples: [ + `${CATEGORIES.SEQUENCER_UPTIME_FEED}:set_l1_sender --network= --address= `, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateAddress], + loadContract: uptimeFeedContractLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/acceptOwnership.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/acceptOwnership.ts new file mode 100644 index 0000000..4f408ac --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/acceptOwnership.ts @@ -0,0 +1,34 @@ +import { EVMExecuteCommandConfig, makeEVMExecuteCommand } from '@pluginv3.0/evm-gauntlet' +import { CONTRACT_LIST, starknetValidatorContractLoader } from '../../lib/contracts' +import { CATEGORIES } from '../../lib/categories' + +export type ContractInput = [] + +export interface UserInput {} + +const makeContractInput = async (input: ContractInput): Promise => { + return input +} + +const makeUserInput = async (flags): Promise => { + return {} +} + +const commandConfig: EVMExecuteCommandConfig = { + contractId: CONTRACT_LIST.STARKNET_VALIDATOR, + category: CATEGORIES.STARKNET_VALIDATOR, + action: 'accept_ownership', + internalFunction: 'acceptOwnership', + ux: { + description: 'Accepts ownership of the StarknetValidator contract from the caller address', + examples: [ + `${CATEGORIES.STARKNET_VALIDATOR}:accept_ownership --network=`, + ], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: starknetValidatorContractLoader, +} + +export default makeEVMExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/addAccess.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/addAccess.ts new file mode 100644 index 0000000..4533b25 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/addAccess.ts @@ -0,0 +1,47 @@ +import { EVMExecuteCommandConfig, makeEVMExecuteCommand } from '@pluginv3.0/evm-gauntlet' +import { CONTRACT_LIST, starknetValidatorContractLoader } from '../../lib/contracts' +import { CATEGORIES } from '../../lib/categories' +import { isValidAddress } from '@pluginv3.0/starknet-gauntlet' + +export interface UserInput { + address: string +} + +type ContractInput = [_user: string] + +const makeContractInput = async (input: UserInput): Promise => { + return [input.address] +} + +const validateAddress = async (input) => { + if (!isValidAddress(input.address)) { + throw new Error(`Invalid Address: ${input.address}`) + } + return true +} + +const makeUserInput = async (flags): Promise => { + if (flags.input) return flags.input as UserInput + return { + address: flags.address, + } +} + +const commandConfig: EVMExecuteCommandConfig = { + contractId: CONTRACT_LIST.STARKNET_VALIDATOR, + category: CATEGORIES.STARKNET_VALIDATOR, + action: 'add_access', + internalFunction: 'addAccess', + ux: { + description: 'Allow address to access StarknetValidator', + examples: [ + `${CATEGORIES.STARKNET_VALIDATOR}:add_access --address=
--network= `, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateAddress], + loadContract: starknetValidatorContractLoader, +} + +export default makeEVMExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/deploy.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/deploy.ts new file mode 100644 index 0000000..20ff255 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/deploy.ts @@ -0,0 +1,113 @@ +import { EVMExecuteCommandConfig, makeEVMExecuteCommand } from '@pluginv3.0/evm-gauntlet' +import { CONTRACT_LIST, starknetValidatorContractLoader } from '../../lib/contracts' +import { CATEGORIES } from '../../lib/categories' +import { isValidAddress } from '@pluginv3.0/starknet-gauntlet' + +export interface UserInput { + starkNetMessaging: number + configAC: string + gasPriceL1Feed: string + source: string + gasEstimate: number + l2Feed: string +} + +type ContractInput = [ + starkNetMessaging: number, + configAC: string, + gasPriceL1Feed: string, + source: string, + l2Feed: string, + gasEstimate: number, +] + +const makeContractInput = async (input: UserInput): Promise => { + return [ + input.starkNetMessaging, + input.configAC, + input.gasPriceL1Feed, + input.source, + input.l2Feed, + input.gasEstimate, + ] +} + +const makeUserInput = async (flags): Promise => { + if (flags.input) return flags.input as UserInput + return { + starkNetMessaging: flags.starkNetMessaging, + configAC: flags.configAC, + gasPriceL1Feed: flags.gasPriceL1Feed, + source: flags.source, + gasEstimate: flags.gasEstimate, + l2Feed: flags.l2Feed, + } +} + +const validateStarkNetMessaging = async (input) => { + if (!isValidAddress(input.starkNetMessaging)) { + throw new Error(`Invalid starkNetMessaging Address: ${input.starkNetMessaging}`) + } + return true +} + +const validateConfigAC = async (input) => { + if (!isValidAddress(input.configAC)) { + throw new Error(`Invalid configAC Address: ${input.configAC}`) + } + return true +} + +const validateGasPriceL1Feed = async (input) => { + if (!isValidAddress(input.gasPriceL1Feed)) { + throw new Error(`Invalid gasPriceL1Feed Address: ${input.gasPriceL1Feed}`) + } + return true +} + +const validateSourceAggregator = async (input) => { + if (!isValidAddress(input.source)) { + throw new Error(`Invalid source Address: ${input.source}`) + } + return true +} + +const validateGasEstimate = async (input) => { + if (isNaN(Number(input.gasEstimate))) { + throw new Error(`Invalid gasEstimate (must be number): ${input.gasEstimate}`) + } + return true +} + +const validateL2Feed = async (input) => { + if (!isValidAddress(input.l2Feed)) { + throw new Error(`Invalid l2Feed Address: ${input.l2Feed}`) + } + return true +} + +const commandConfig: EVMExecuteCommandConfig = { + contractId: CONTRACT_LIST.STARKNET_VALIDATOR, + category: CATEGORIES.STARKNET_VALIDATOR, + action: 'deploy', + ux: { + description: + 'Deploys a StarknetValidator contract. Starknet messaging contract is address officially deployed by starkware industries. ', + examples: [ + `${CATEGORIES.STARKNET_VALIDATOR}:deploy --starkNetMessaging=
--configAC=
--gasPriceL1Feed=
--source=
--gasEstimate= --l2Feed=
--network=`, + ], + }, + makeUserInput, + makeContractInput, + validations: [ + validateStarkNetMessaging, + validateConfigAC, + validateGasPriceL1Feed, + validateGasEstimate, + validateSourceAggregator, + validateL2Feed, + ], + loadContract: starknetValidatorContractLoader, +} + +export default makeEVMExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/index.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/index.ts new file mode 100644 index 0000000..19117cd --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/index.ts @@ -0,0 +1,7 @@ +import Deploy from './deploy' +import AddAccess from './addAccess' +import TransferOwnership from './transferOwnership' +import AcceptOwnership from './acceptOwnership' +import Validate from './validate' + +export default [Deploy, AddAccess, TransferOwnership, AcceptOwnership, Validate] diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/transferOwnership.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/transferOwnership.ts new file mode 100644 index 0000000..2efb941 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/transferOwnership.ts @@ -0,0 +1,40 @@ +import { EVMExecuteCommandConfig, makeEVMExecuteCommand } from '@pluginv3.0/evm-gauntlet' +import { CONTRACT_LIST, starknetValidatorContractLoader } from '../../lib/contracts' +import { CATEGORIES } from '../../lib/categories' + +export interface UserInput { + to: string +} + +type ContractInput = [to: string] + +const makeContractInput = async (input: UserInput): Promise => { + return [input.to] +} + +const makeUserInput = async (flags): Promise => { + if (flags.input) return flags.input as UserInput + return { + to: flags.to, + } +} + +const commandConfig: EVMExecuteCommandConfig = { + contractId: CONTRACT_LIST.STARKNET_VALIDATOR, + category: CATEGORIES.STARKNET_VALIDATOR, + action: 'transfer_ownership', + internalFunction: 'transferOwnership', + ux: { + description: + 'Transfers ownership of the StarknetValidator contract. Should be called by current owner', + examples: [ + `${CATEGORIES.STARKNET_VALIDATOR}:transfer_ownership --to= --network=`, + ], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: starknetValidatorContractLoader, +} + +export default makeEVMExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/validate.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/validate.ts new file mode 100644 index 0000000..64f81b6 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/commands/starknetValidator/validate.ts @@ -0,0 +1,90 @@ +import { EVMExecuteCommandConfig, makeEVMExecuteCommand } from '@pluginv3.0/evm-gauntlet' +import { CONTRACT_LIST, starknetValidatorContractLoader } from '../../lib/contracts' +import { CATEGORIES } from '../../lib/categories' + +export interface UserInput { + previousRoundId: number + previousAnswer: number + currentRoundId: number + currentAnswer: number +} + +type ContractInput = [ + previousRoundId: number, + previousAnswer: number, + currentRoundId: number, + currentAnswer: number, +] + +const makeContractInput = async ({ + previousRoundId, + previousAnswer, + currentRoundId, + currentAnswer, +}: UserInput): Promise => { + return [previousRoundId, previousAnswer, currentRoundId, currentAnswer] +} + +const validatePreviousRoundId = async (input) => { + if (isNaN(Number(input.previousRoundId))) { + throw new Error(`Invalid previousRoundId: ${input.previousRoundId}`) + } + return true +} + +const validatePreviousAnswer = async (input) => { + if (isNaN(Number(input.previousAnswer))) { + throw new Error(`Invalid previousAnswer: ${input.previousAnswer}`) + } + return true +} + +const validateCurrentRoundId = async (input) => { + if (isNaN(Number(input.currentRoundId))) { + throw new Error(`Invalid currentRoundId: ${input.currentRoundId}`) + } + return true +} + +const validateCurrentAnswer = async (input) => { + if (isNaN(Number(input.currentAnswer))) { + throw new Error(`Invalid currentAnswer: ${input.currentAnswer}`) + } + return true +} + +const makeUserInput = async (flags): Promise => { + if (flags.input) return flags.input as UserInput + const { previousRoundId, previousAnswer, currentRoundId, currentAnswer } = flags + return { + previousRoundId, + previousAnswer, + currentRoundId, + currentAnswer, + } +} + +const commandConfig: EVMExecuteCommandConfig = { + contractId: CONTRACT_LIST.STARKNET_VALIDATOR, + category: CATEGORIES.STARKNET_VALIDATOR, + action: 'validate', + internalFunction: 'validate', + ux: { + description: + 'Validate the status by sending xDomain L2 tx to Starknet UptimeFeed. Caller must have access to validate.', + examples: [ + `${CATEGORIES.STARKNET_VALIDATOR}:validate --previousRoundId=0 --previousAnswer=0 --currentRoundId=1 --currentAnswer=1 --network= `, + ], + }, + makeUserInput, + makeContractInput, + validations: [ + validateCurrentAnswer, + validateCurrentRoundId, + validatePreviousAnswer, + validatePreviousRoundId, + ], + loadContract: starknetValidatorContractLoader, +} + +export default makeEVMExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/index.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/index.ts new file mode 100644 index 0000000..02ec041 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/index.ts @@ -0,0 +1 @@ +export { L1Commands, L2Commands, L2InspectionCommands } from './commands' diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/lib/categories.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/lib/categories.ts new file mode 100644 index 0000000..cc53c50 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/lib/categories.ts @@ -0,0 +1,6 @@ +import { CONTRACT_LIST } from './contracts' + +export const CATEGORIES = { + SEQUENCER_UPTIME_FEED: CONTRACT_LIST.SEQUENCER_UPTIME_FEED, + STARKNET_VALIDATOR: CONTRACT_LIST.STARKNET_VALIDATOR, +} diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/src/lib/contracts.ts b/packages-ts/starknet-gauntlet-emergency-protocol/src/lib/contracts.ts new file mode 100644 index 0000000..c6e4fa6 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/src/lib/contracts.ts @@ -0,0 +1,29 @@ +import fs from 'fs' +import { CompiledContract, json } from 'starknet' +import { ContractFactory } from 'ethers' + +export enum CONTRACT_LIST { + SEQUENCER_UPTIME_FEED = 'sequencer_uptime_feed', + STARKNET_VALIDATOR = 'starknet_validator', +} + +export const uptimeFeedContractLoader = (): CompiledContract => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/starknet-artifacts/src/plugin/cairo/emergency/SequencerUptimeFeed/sequencer_uptime_feed.cairo/sequencer_uptime_feed.json`, + ) + .toString('ascii'), + ) +} + +export const starknetValidatorContractLoader = (): ContractFactory => { + const abi = JSON.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/artifacts/src/plugin/solidity/emergency/StarknetValidator.sol/StarknetValidator.json`, + ) + .toString('ascii'), + ) + return new ContractFactory(abi?.abi, abi?.bytecode) +} diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/test/commands/sequencerUptimeFeed.test.ts b/packages-ts/starknet-gauntlet-emergency-protocol/test/commands/sequencerUptimeFeed.test.ts new file mode 100644 index 0000000..dcc46b2 --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/test/commands/sequencerUptimeFeed.test.ts @@ -0,0 +1,67 @@ +import deployCommand from '../../src/commands/sequencerUptimeFeed/deploy' +import setL1Sender from '../../src/commands/sequencerUptimeFeed/setL1Sender' +import getLatestRoundData from '../../src/commands/sequencerUptimeFeed/inspection/inspection' +import { + registerExecuteCommand, + registerInspectCommand, + TIMEOUT, + startNetwork, + IntegratedDevnet, +} from '@pluginv3.0/starknet-gauntlet/test/utils' + +describe('Sequencer Uptime Feed Contract', () => { + let network: IntegratedDevnet + let uptimeFeedAddress: string + + beforeAll(async () => { + network = await startNetwork() + }, 15000) + + // deploy uptime feed contract + beforeEach(async () => { + const command = await registerExecuteCommand(deployCommand).create( + { + initialStatus: 0, + }, + [], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + uptimeFeedAddress = report.responses[0].contract + }, TIMEOUT) + + describe('setL1Sender', () => { + it( + 'Sets with a non-Zero valid eth address', + async () => { + const command = await registerExecuteCommand(setL1Sender).create( + { + address: '0x0000000000000000000000000000000000000007', + }, + [uptimeFeedAddress], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + }, + TIMEOUT, + ) + }) + + describe('inspect uptime feed status', () => { + it('Retrieves 0', async () => { + const inspectCommand = await registerInspectCommand(getLatestRoundData).create({}, [ + uptimeFeedAddress, + ]) + + const report = await inspectCommand.execute() + expect(report.data.data.latest_round_data.answer).toEqual('0') + }) + }) + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet-emergency-protocol/tsconfig.json b/packages-ts/starknet-gauntlet-emergency-protocol/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-emergency-protocol/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-example/LICENSE b/packages-ts/starknet-gauntlet-example/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-example/README.md b/packages-ts/starknet-gauntlet-example/README.md new file mode 100644 index 0000000..f177379 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/README.md @@ -0,0 +1,29 @@ +# Starknet Gauntlet Commands for a Sample Contract + +This package contains some commands to serve as an example on how to use Gauntlet with Starknet. The contract can be found on the [Cairo Docs](https://www.cairo-lang.org/docs/hello_starknet/intro.html#your-first-contract) + +## Commands + +- Deploy + +```bash +yarn gauntlet example:deploy --network= +``` + +This will result in a new contract address + +- Increasing balance + +Will increase the current balance with the amount specified with the `--balance` flag + +```bash +yarn gauntlet example:increase_balance --network= --balance= +``` + +- Inspect the contract + +Will prompt the current balance of the contract + +```bash +yarn gauntlet example:inspect --network= +``` diff --git a/packages-ts/starknet-gauntlet-example/contract_artifacts/abi/example.json b/packages-ts/starknet-gauntlet-example/contract_artifacts/abi/example.json new file mode 100644 index 0000000..c212b95 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/contract_artifacts/abi/example.json @@ -0,0 +1,4875 @@ +{ + "abi": [ + { + "inputs": [ + { + "name": "amount", + "type": "felt" + } + ], + "name": "increase_balance", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "get_balance", + "outputs": [ + { + "name": "res", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [], + "EXTERNAL": [ + { + "offset": "0x3a", + "selector": "0x362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320" + }, + { + "offset": "0x5b", + "selector": "0x39e11d48192e4333233c7eb19d10ad67c362bb28580c604d67884c85da39695" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "pedersen", + "range_check" + ], + "compiler_version": "0.10.0", + "data": [ + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x3", + "0x480280027ffc8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x400380027ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x206f38f7e4f15e87567361213c28f235cccdaa1d7fd34c9db1dfe9489c6a091", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe6", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe5", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48287ffd7ffc8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc7", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": { + "file_contents": { + "autogen/starknet/arg_processor/01cba52f8515996bb9d7070bde81ff39281d096d7024a558efcba6e1fd2402cf.cairo": "assert [cast(fp + (-4), felt*)] = __calldata_actual_size;\n", + "autogen/starknet/arg_processor/293368f3a0e12cfcf22314a31e13b9801e95a5b8b2b71822a2fbbdf5a01ea795.cairo": "assert [__return_value_ptr] = ret_value.res;\nlet __return_value_ptr = __return_value_ptr + 1;\n", + "autogen/starknet/arg_processor/73e68c490b7650388f650e9e1ff9b2b3ced88dabf86213d6a0831077eb1a0800.cairo": "let __calldata_arg_amount = [__calldata_ptr];\nlet __calldata_ptr = __calldata_ptr + 1;\n", + "autogen/starknet/arg_processor/c31620b02d4d706f0542c989b2aadc01b0981d1f6a5933a8fe4937ace3d70d92.cairo": "let __calldata_actual_size = __calldata_ptr - cast([cast(fp + (-3), felt**)], felt*);\n", + "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo": "let ret_value = __wrapped_func{syscall_ptr=syscall_ptr, pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr}();\nlet (range_check_ptr, retdata_size, retdata) = get_balance_encode_return(ret_value, range_check_ptr);\n", + "autogen/starknet/external/get_balance/741ea357d6336b0bed7bf0472425acd0311d543883b803388880e60a232040c7.cairo": "let range_check_ptr = [cast([cast(fp + (-5), felt**)] + 2, felt*)];\n", + "autogen/starknet/external/get_balance/9684a85e93c782014ca14293edea4eb2502039a5a7b6538ecd39c56faaf12529.cairo": "let pedersen_ptr = [cast([cast(fp + (-5), felt**)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)];\n", + "autogen/starknet/external/get_balance/b2c52ca2d2a8fc8791a983086d8716c5eacd0c3d62934914d2286f84b98ff4cb.cairo": "let syscall_ptr = [cast([cast(fp + (-5), felt**)] + 0, felt**)];\n", + "autogen/starknet/external/get_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo": "return (syscall_ptr,pedersen_ptr,range_check_ptr,retdata_size,retdata);\n", + "autogen/starknet/external/increase_balance/741ea357d6336b0bed7bf0472425acd0311d543883b803388880e60a232040c7.cairo": "let range_check_ptr = [cast([cast(fp + (-5), felt**)] + 2, felt*)];\n", + "autogen/starknet/external/increase_balance/9684a85e93c782014ca14293edea4eb2502039a5a7b6538ecd39c56faaf12529.cairo": "let pedersen_ptr = [cast([cast(fp + (-5), felt**)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)];\n", + "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo": "let ret_value = __wrapped_func{syscall_ptr=syscall_ptr, pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr}(amount=__calldata_arg_amount,);\n%{ memory[ap] = segments.add() %} // Allocate memory for return value.\ntempvar retdata: felt*;\nlet retdata_size = 0;\n", + "autogen/starknet/external/increase_balance/b2c52ca2d2a8fc8791a983086d8716c5eacd0c3d62934914d2286f84b98ff4cb.cairo": "let syscall_ptr = [cast([cast(fp + (-5), felt**)] + 0, felt**)];\n", + "autogen/starknet/external/increase_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo": "return (syscall_ptr,pedersen_ptr,range_check_ptr,retdata_size,retdata);\n", + "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo": "func get_balance_encode_return(ret_value: (res: felt), range_check_ptr) -> (\n range_check_ptr: felt, data_len: felt, data: felt*) {\n %{ memory[ap] = segments.add() %}\n alloc_locals;\n local __return_value_ptr_start: felt*;\n let __return_value_ptr = __return_value_ptr_start;\n with range_check_ptr {\n }\n return (\n range_check_ptr=range_check_ptr,\n data_len=__return_value_ptr - __return_value_ptr_start,\n data=__return_value_ptr_start);\n}\n", + "autogen/starknet/storage_var/balance/decl.cairo": "namespace balance {\n from starkware.starknet.common.storage import normalize_address\n from starkware.starknet.common.syscalls import storage_read, storage_write\n from starkware.cairo.common.cairo_builtins import HashBuiltin\n from starkware.cairo.common.hash import hash2\n\n func addr{pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (res: felt) {\n let res = 0;\n call hash2;\n call normalize_address;\n }\n\n func read{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (res: felt) {\n let storage_addr = 0;\n call addr;\n call storage_read;\n }\n\n func write{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(value: felt) {\n let storage_addr = 0;\n call addr;\n call storage_write;\n }\n}", + "autogen/starknet/storage_var/balance/impl.cairo": "namespace balance {\n from starkware.starknet.common.storage import normalize_address\n from starkware.starknet.common.syscalls import storage_read, storage_write\n from starkware.cairo.common.cairo_builtins import HashBuiltin\n from starkware.cairo.common.hash import hash2\n\n func addr{pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (res: felt) {\n let res = 916907772491729262376534102982219947830828984996257231353398618781993312401;\n return (res=res);\n }\n\n func read{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (res: felt) {\n let (storage_addr) = addr();\n let (__storage_var_temp0) = storage_read(address=storage_addr + 0);\n\n tempvar syscall_ptr = syscall_ptr;\n tempvar pedersen_ptr = pedersen_ptr;\n tempvar range_check_ptr = range_check_ptr;\n tempvar __storage_var_temp0: felt = __storage_var_temp0;\n return ([cast(&__storage_var_temp0, felt*)],);\n }\n\n func write{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(value: felt) {\n let (storage_addr) = addr();\n storage_write(address=storage_addr + 0, value=[cast(&value, felt) + 0]);\n return ();\n }\n}" + }, + "instruction_locations": { + "0": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 79, + "end_line": 350, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 58, + "start_line": 350 + } + }, + "2": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 98, + "end_line": 350, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 350 + } + }, + "3": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 98, + "end_line": 350, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 350 + } + }, + "4": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": null, + "hints": [ + { + "location": { + "end_col": 87, + "end_line": 351, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 351 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 53, + "end_line": 353, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 37, + "end_line": 348, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 35, + "end_line": 354, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 354 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 19, + "start_line": 348 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 23, + "start_line": 353 + } + }, + "6": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 33, + "end_line": 354, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 19, + "start_line": 354 + } + }, + "7": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 35, + "end_line": 354, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 354 + } + }, + "8": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 40, + "end_line": 368, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 18, + "start_line": 368 + } + }, + "10": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 72, + "end_line": 368, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 367 + } + }, + "11": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 72, + "end_line": 368, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 367 + } + }, + "12": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 72, + "end_line": 368, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 367 + } + }, + "13": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": null, + "hints": [ + { + "location": { + "end_col": 88, + "end_line": 369, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 369 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 54, + "end_line": 370, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 38, + "end_line": 366, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 15, + "end_line": 371, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 371 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 20, + "start_line": 366 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 23, + "start_line": 370 + } + }, + "15": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 15, + "end_line": 371, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 371 + } + }, + "16": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 41, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 41, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 26, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 9 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + } + }, + "17": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 58, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 58, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 26, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 9 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 43, + "start_line": 7 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 43, + "start_line": 7 + } + }, + "18": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 94, + "end_line": 8, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 24, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 21, + "start_line": 9 + }, + "While expanding the reference 'res' in:" + ], + "start_col": 19, + "start_line": 8 + } + }, + "20": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 26, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 9 + } + }, + "21": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 61, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 41, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 13 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 35, + "start_line": 12 + } + }, + "22": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 78, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 58, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 13 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 43, + "start_line": 7 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 63, + "start_line": 12 + } + }, + "23": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 13 + } + }, + "25": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 33, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 37, + "end_line": 348, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 75, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 37, + "start_line": 14 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 19, + "start_line": 348 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 12 + } + }, + "26": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 26, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 70, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 58, + "start_line": 14 + }, + "While expanding the reference 'storage_addr' in:" + ], + "start_col": 14, + "start_line": 13 + } + }, + "27": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 75, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 37, + "start_line": 14 + } + }, + "29": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 37, + "end_line": 348, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 75, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 42, + "end_line": 16, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 31, + "start_line": 16 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 37, + "start_line": 14 + }, + "While trying to update the implicit return value 'syscall_ptr' in:" + ], + "start_col": 19, + "start_line": 348 + } + }, + "30": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 41, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 44, + "end_line": 17, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 32, + "start_line": 17 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 30, + "start_line": 13 + }, + "While trying to update the implicit return value 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + } + }, + "31": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 58, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 50, + "end_line": 18, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 35, + "start_line": 18 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 30, + "start_line": 13 + }, + "While trying to update the implicit return value 'range_check_ptr' in:" + ], + "start_col": 43, + "start_line": 7 + } + }, + "32": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 33, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 64, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 45, + "start_line": 19 + }, + "While expanding the reference '__storage_var_temp0' in:" + ], + "start_col": 14, + "start_line": 14 + } + }, + "33": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 55, + "end_line": 20, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 20 + } + }, + "34": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 62, + "end_line": 23, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 41, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 24 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 36, + "start_line": 23 + } + }, + "35": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 79, + "end_line": 23, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 58, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 24 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 43, + "start_line": 7 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 64, + "start_line": 23 + } + }, + "36": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 24 + } + }, + "38": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 34, + "end_line": 23, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 38, + "end_line": 366, + "input_file": { + "filename": "/home/speed/src/golang/plugin-starknet/.venv/lib/python3.9/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 80, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 25 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 20, + "start_line": 366 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 16, + "start_line": 23 + } + }, + "39": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 26, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 43, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 31, + "start_line": 25 + }, + "While expanding the reference 'storage_addr' in:" + ], + "start_col": 14, + "start_line": 24 + } + }, + "40": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 79, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 55, + "start_line": 25 + } + }, + "41": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 80, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 25 + } + }, + "43": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 41, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 62, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 19, + "end_line": 26, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 26 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 36, + "start_line": 19 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 30, + "start_line": 24 + }, + "While trying to update the implicit return value 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + } + }, + "44": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 58, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 79, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 19, + "end_line": 26, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 26 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 64, + "start_line": 19 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 30, + "start_line": 24 + }, + "While trying to update the implicit return value 'range_check_ptr' in:" + ], + "start_col": 43, + "start_line": 7 + } + }, + "45": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 19, + "end_line": 26, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 26 + } + }, + "46": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 23, + "end_line": 14, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 33, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 18, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 18 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 13 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 5, + "start_line": 14 + } + }, + "47": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 15, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 61, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 18, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 18 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 35, + "start_line": 13 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 5, + "start_line": 15 + } + }, + "48": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 20, + "end_line": 16, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 78, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 18, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 18 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 63, + "start_line": 13 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 5, + "start_line": 16 + } + }, + "49": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 18, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 18 + } + }, + "51": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 33, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 18, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 34, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 32, + "end_line": 19, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 5, + "start_line": 19 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 16, + "start_line": 19 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 17, + "start_line": 18 + }, + "While trying to update the implicit return value 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 13 + } + }, + "52": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 61, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 18, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 62, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 32, + "end_line": 19, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 5, + "start_line": 19 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 36, + "start_line": 19 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 17, + "start_line": 18 + }, + "While trying to update the implicit return value 'pedersen_ptr' in:" + ], + "start_col": 35, + "start_line": 13 + } + }, + "53": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 78, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 18, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 79, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 32, + "end_line": 19, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 5, + "start_line": 19 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 64, + "start_line": 19 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 17, + "start_line": 18 + }, + "While trying to update the implicit return value 'range_check_ptr' in:" + ], + "start_col": 63, + "start_line": 13 + } + }, + "54": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 19, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 19, + "start_line": 19 + } + }, + "55": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 32, + "end_line": 19, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 5, + "start_line": 19 + } + }, + "57": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 15, + "end_line": 20, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 5, + "start_line": 20 + } + }, + "58": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 40, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/arg_processor/73e68c490b7650388f650e9e1ff9b2b3ced88dabf86213d6a0831077eb1a0800.cairo" + }, + "parent_location": [ + { + "end_col": 15, + "end_line": 17, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 45, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/c31620b02d4d706f0542c989b2aadc01b0981d1f6a5933a8fe4937ace3d70d92.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 57, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/01cba52f8515996bb9d7070bde81ff39281d096d7024a558efcba6e1fd2402cf.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While handling calldata of" + ], + "start_col": 35, + "start_line": 1 + }, + "While expanding the reference '__calldata_actual_size' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While handling calldata of" + ], + "start_col": 31, + "start_line": 1 + }, + "While expanding the reference '__calldata_ptr' in:" + ], + "start_col": 3, + "start_line": 17 + }, + "While handling calldata argument 'amount'" + ], + "start_col": 22, + "start_line": 2 + } + }, + "60": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 58, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/01cba52f8515996bb9d7070bde81ff39281d096d7024a558efcba6e1fd2402cf.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While handling calldata of" + ], + "start_col": 1, + "start_line": 1 + } + }, + "61": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 64, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b2c52ca2d2a8fc8791a983086d8716c5eacd0c3d62934914d2286f84b98ff4cb.cairo" + }, + "parent_location": [ + { + "end_col": 23, + "end_line": 14, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 55, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 44, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 5, + "start_line": 14 + }, + "While constructing the external wrapper for:" + ], + "start_col": 19, + "start_line": 1 + } + }, + "62": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 110, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/9684a85e93c782014ca14293edea4eb2502039a5a7b6538ecd39c56faaf12529.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 15, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 82, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 70, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 5, + "start_line": 15 + }, + "While constructing the external wrapper for:" + ], + "start_col": 20, + "start_line": 1 + } + }, + "63": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 67, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/741ea357d6336b0bed7bf0472425acd0311d543883b803388880e60a232040c7.cairo" + }, + "parent_location": [ + { + "end_col": 20, + "end_line": 16, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 115, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 100, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 5, + "start_line": 16 + }, + "While constructing the external wrapper for:" + ], + "start_col": 23, + "start_line": 1 + } + }, + "64": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 45, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/73e68c490b7650388f650e9e1ff9b2b3ced88dabf86213d6a0831077eb1a0800.cairo" + }, + "parent_location": [ + { + "end_col": 15, + "end_line": 17, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 145, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 124, + "start_line": 1 + }, + "While expanding the reference '__calldata_arg_amount' in:" + ], + "start_col": 3, + "start_line": 17 + }, + "While handling calldata argument 'amount'" + ], + "start_col": 29, + "start_line": 1 + } + }, + "65": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + } + }, + "67": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [ + { + "location": { + "end_col": 34, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 2 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 24, + "end_line": 3, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 3 + } + }, + "69": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 55, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 20, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 9, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 44, + "start_line": 1 + } + }, + "70": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 82, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 33, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 21, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 70, + "start_line": 1 + } + }, + "71": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 115, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 49, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 34, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 100, + "start_line": 1 + } + }, + "72": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 21, + "end_line": 4, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 62, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 50, + "start_line": 1 + }, + "While expanding the reference 'retdata_size' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 20, + "start_line": 4 + } + }, + "74": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 16, + "end_line": 3, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/a41d25a92a3a14a71125d51d48dd7398e2839f055f01551b7b1950eafc1187c0.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 70, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 63, + "start_line": 1 + }, + "While expanding the reference 'retdata' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 9, + "start_line": 3 + } + }, + "75": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 72, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 1 + } + }, + "76": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 23, + "end_line": 26, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 33, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 30, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 30 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 13 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 5, + "start_line": 26 + } + }, + "77": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 27, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 61, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 30, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 30 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 35, + "start_line": 13 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 5, + "start_line": 27 + } + }, + "78": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 20, + "end_line": 28, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 78, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 30, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 30 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 63, + "start_line": 13 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 5, + "start_line": 28 + } + }, + "79": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 30, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 17, + "start_line": 30 + } + }, + "81": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 22, + "end_line": 31, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 5, + "start_line": 31 + } + }, + "82": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": null, + "hints": [ + { + "location": { + "end_col": 38, + "end_line": 3, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 5, + "start_line": 3 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 18, + "end_line": 4, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 5, + "start_line": 4 + } + }, + "84": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 45, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/293368f3a0e12cfcf22314a31e13b9801e95a5b8b2b71822a2fbbdf5a01ea795.cairo" + }, + "parent_location": [ + { + "end_col": 18, + "end_line": 29, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 9, + "start_line": 29 + }, + "While handling return value 'res'" + ], + "start_col": 1, + "start_line": 1 + } + }, + "85": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 48, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/arg_processor/293368f3a0e12cfcf22314a31e13b9801e95a5b8b2b71822a2fbbdf5a01ea795.cairo" + }, + "parent_location": [ + { + "end_col": 18, + "end_line": 29, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 11, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 18, + "start_line": 11 + }, + "While expanding the reference '__return_value_ptr' in:" + ], + "start_col": 9, + "start_line": 29 + }, + "While handling return value 'res'" + ], + "start_col": 26, + "start_line": 2 + } + }, + "87": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 71, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 40, + "end_line": 10, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 25, + "start_line": 10 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 56, + "start_line": 1 + } + }, + "88": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 63, + "end_line": 11, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 18, + "start_line": 11 + } + }, + "89": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 35, + "end_line": 5, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 38, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 14, + "start_line": 12 + }, + "While expanding the reference '__return_value_ptr_start' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 11, + "start_line": 5 + } + }, + "90": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 40, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/9ef0a2b9ad0a2e2b202322d7261fff6dada72892e286df2230a9eb8873880a98.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling return value of" + ], + "start_col": 5, + "start_line": 9 + } + }, + "91": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 58, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/01cba52f8515996bb9d7070bde81ff39281d096d7024a558efcba6e1fd2402cf.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While handling calldata of" + ], + "start_col": 1, + "start_line": 1 + } + }, + "92": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 64, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/b2c52ca2d2a8fc8791a983086d8716c5eacd0c3d62934914d2286f84b98ff4cb.cairo" + }, + "parent_location": [ + { + "end_col": 23, + "end_line": 26, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 55, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 44, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 5, + "start_line": 26 + }, + "While constructing the external wrapper for:" + ], + "start_col": 19, + "start_line": 1 + } + }, + "93": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 110, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/9684a85e93c782014ca14293edea4eb2502039a5a7b6538ecd39c56faaf12529.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 27, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 82, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 70, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 5, + "start_line": 27 + }, + "While constructing the external wrapper for:" + ], + "start_col": 20, + "start_line": 1 + } + }, + "94": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 67, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/741ea357d6336b0bed7bf0472425acd0311d543883b803388880e60a232040c7.cairo" + }, + "parent_location": [ + { + "end_col": 20, + "end_line": 28, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 115, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 100, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 5, + "start_line": 28 + }, + "While constructing the external wrapper for:" + ], + "start_col": 23, + "start_line": 1 + } + }, + "95": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + } + }, + "97": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 115, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 100, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 85, + "start_line": 2 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 100, + "start_line": 1 + } + }, + "98": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 101, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 48, + "start_line": 2 + } + }, + "100": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 55, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 20, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 9, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 44, + "start_line": 1 + } + }, + "101": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 82, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 33, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 21, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 70, + "start_line": 1 + } + }, + "102": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 21, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 49, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 34, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 6, + "start_line": 2 + } + }, + "103": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 35, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 62, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 50, + "start_line": 1 + }, + "While expanding the reference 'retdata_size' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 23, + "start_line": 2 + } + }, + "104": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 44, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/2c767dabe8478bfafd38f9fb907f9842d03e3c9d2b355e2af5c59b126fcc8f59.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "parent_location": [ + { + "end_col": 70, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 63, + "start_line": 1 + }, + "While expanding the reference 'retdata' in:" + ], + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 37, + "start_line": 2 + } + }, + "105": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": null, + "hints": [], + "inst": { + "end_col": 72, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/da17921a4e81c09e730800bbf23bfdbe5e9e6bfaedc59d80fbf62087fa43c27d.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 25, + "input_file": { + "filename": "example.cairo" + }, + "start_col": 6, + "start_line": 25 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 1 + } + } + } + }, + "hints": { + "4": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "code": "syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 0 + } + } + } + ], + "13": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "code": "syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 1 + } + } + } + ], + "67": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 52 + }, + "reference_ids": {} + } + } + ], + "82": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 0 + }, + "reference_ids": {} + } + } + ] + }, + "identifiers": { + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.balance": { + "type": "namespace" + }, + "__main__.balance.Args": { + "full_name": "__main__.balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.balance.ImplicitArgs": { + "full_name": "__main__.balance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.balance.addr": { + "decorators": [], + "pc": 16, + "type": "function" + }, + "__main__.balance.addr.Args": { + "full_name": "__main__.balance.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.addr.ImplicitArgs": { + "full_name": "__main__.balance.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.balance.addr.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "__main__.balance.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.balance.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "__main__.balance.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "__main__.balance.read": { + "decorators": [], + "pc": 21, + "type": "function" + }, + "__main__.balance.read.Args": { + "full_name": "__main__.balance.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.read.ImplicitArgs": { + "full_name": "__main__.balance.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.balance.read.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "__main__.balance.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.balance.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.balance.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.balance.write": { + "decorators": [], + "pc": 34, + "type": "function" + }, + "__main__.balance.write.Args": { + "full_name": "__main__.balance.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.balance.write.ImplicitArgs": { + "full_name": "__main__.balance.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.balance.write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.balance.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_balance": { + "decorators": [ + "view" + ], + "pc": 76, + "type": "function" + }, + "__main__.get_balance.Args": { + "full_name": "__main__.get_balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_balance.ImplicitArgs": { + "full_name": "__main__.get_balance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.get_balance.Return": { + "cairo_type": "(res: felt)", + "type": "type_definition" + }, + "__main__.get_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.increase_balance": { + "decorators": [ + "external" + ], + "pc": 46, + "type": "function" + }, + "__main__.increase_balance.Args": { + "full_name": "__main__.increase_balance.Args", + "members": { + "amount": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.increase_balance.ImplicitArgs": { + "full_name": "__main__.increase_balance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.increase_balance.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "__main__.increase_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.get_balance": { + "decorators": [ + "view" + ], + "pc": 91, + "type": "function" + }, + "__wrappers__.get_balance.Args": { + "full_name": "__wrappers__.get_balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_balance.ImplicitArgs": { + "full_name": "__wrappers__.get_balance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_balance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.get_balance.__wrapped_func": { + "destination": "__main__.get_balance", + "type": "alias" + }, + "__wrappers__.get_balance_encode_return": { + "decorators": [], + "pc": 82, + "type": "function" + }, + "__wrappers__.get_balance_encode_return.Args": { + "full_name": "__wrappers__.get_balance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_value": { + "cairo_type": "(res: felt)", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.get_balance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.get_balance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_balance_encode_return.Return": { + "cairo_type": "(range_check_ptr: felt, data_len: felt, data: felt*)", + "type": "type_definition" + }, + "__wrappers__.get_balance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.get_balance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.increase_balance": { + "decorators": [ + "external" + ], + "pc": 58, + "type": "function" + }, + "__wrappers__.increase_balance.Args": { + "full_name": "__wrappers__.increase_balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increase_balance.ImplicitArgs": { + "full_name": "__wrappers__.increase_balance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increase_balance.Return": { + "cairo_type": "(syscall_ptr: felt*, pedersen_ptr: starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr: felt, size: felt, retdata: felt*)", + "type": "type_definition" + }, + "__wrappers__.increase_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.increase_balance.__wrapped_func": { + "destination": "__main__.increase_balance", + "type": "alias" + }, + "__wrappers__.increase_balance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.bool.FALSE": { + "type": "const", + "value": 0 + }, + "starkware.cairo.common.bool.TRUE": { + "type": "const", + "value": 1 + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.KeccakBuiltin", + "members": { + "input": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 0 + }, + "output": { + "cairo_type": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "offset": 8 + } + }, + "size": 16, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.KeccakBuiltinState": { + "destination": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.cairo.common.keccak_state.KeccakBuiltinState": { + "full_name": "starkware.cairo.common.keccak_state.KeccakBuiltinState", + "members": { + "s0": { + "cairo_type": "felt", + "offset": 0 + }, + "s1": { + "cairo_type": "felt", + "offset": 1 + }, + "s2": { + "cairo_type": "felt", + "offset": 2 + }, + "s3": { + "cairo_type": "felt", + "offset": 3 + }, + "s4": { + "cairo_type": "felt", + "offset": 4 + }, + "s5": { + "cairo_type": "felt", + "offset": 5 + }, + "s6": { + "cairo_type": "felt", + "offset": 6 + }, + "s7": { + "cairo_type": "felt", + "offset": 7 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.cairo.common.math.FALSE": { + "destination": "starkware.cairo.common.bool.FALSE", + "type": "alias" + }, + "starkware.cairo.common.math.TRUE": { + "destination": "starkware.cairo.common.bool.TRUE", + "type": "alias" + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DEPLOY_SELECTOR": { + "type": "const", + "value": 75202468540281 + }, + "starkware.starknet.common.syscalls.Deploy": { + "full_name": "starkware.starknet.common.syscalls.Deploy", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.DeployRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.DeployResponse", + "offset": 6 + } + }, + "size": 9, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployRequest": { + "full_name": "starkware.starknet.common.syscalls.DeployRequest", + "members": { + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "constructor_calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "constructor_calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address_salt": { + "cairo_type": "felt", + "offset": 2 + }, + "deploy_from_zero": { + "cairo_type": "felt", + "offset": 5 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 6, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DeployResponse": { + "full_name": "starkware.starknet.common.syscalls.DeployResponse", + "members": { + "constructor_retdata": { + "cairo_type": "felt*", + "offset": 2 + }, + "constructor_retdata_size": { + "cairo_type": "felt", + "offset": 1 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 436233452754198157705746250789557519228244616562 + }, + "starkware.starknet.common.syscalls.LIBRARY_CALL_SELECTOR": { + "type": "const", + "value": 92376026794327011772951660 + }, + "starkware.starknet.common.syscalls.LibraryCall": { + "full_name": "starkware.starknet.common.syscalls.LibraryCall", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.LibraryCallRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.LibraryCallRequest": { + "full_name": "starkware.starknet.common.syscalls.LibraryCallRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "class_hash": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "nonce": { + "cairo_type": "felt", + "offset": 7 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 8, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_read.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_read.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.Return": { + "cairo_type": "(value: felt)", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 4, + "value": "cast([fp + (-4)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write": { + "decorators": [], + "pc": 8, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_write.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.Return": { + "cairo_type": "()", + "type": "type_definition" + }, + "starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 13, + "value": "cast([fp + (-5)] + 3, felt*)" + } + ], + "type": "reference" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-5), felt**)]" + } + ] + } + } +} diff --git a/packages-ts/starknet-gauntlet-example/example.cairo b/packages-ts/starknet-gauntlet-example/example.cairo new file mode 100644 index 0000000..eb7331f --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/example.cairo @@ -0,0 +1,32 @@ +// Declare this file as a Starknet contract. +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin + +// Define a storage variable. +@storage_var +func balance() -> (res: felt) { +} + +// Increases the balance by the given amount. +@external +func increase_balance{ + syscall_ptr: felt*, + pedersen_ptr: HashBuiltin*, + range_check_ptr, +}(amount: felt) { + let (res) = balance.read(); + balance.write(res + amount); + return (); +} + +// Returns the current balance. +@view +func get_balance{ + syscall_ptr: felt*, + pedersen_ptr: HashBuiltin*, + range_check_ptr, +}() -> (res: felt) { + let (res) = balance.read(); + return (res=res); +} \ No newline at end of file diff --git a/packages-ts/starknet-gauntlet-example/package.json b/packages-ts/starknet-gauntlet-example/package.json new file mode 100644 index 0000000..d6b5100 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/package.json @@ -0,0 +1,32 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-example", + "version": "0.0.1", + "description": "Starknet Gauntlet Example", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-example --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/gauntlet-contracts-example": "0.1.1", + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/starknet-gauntlet": "*" + } +} diff --git a/packages-ts/starknet-gauntlet-example/src/commands/example/deploy.ts b/packages-ts/starknet-gauntlet-example/src/commands/example/deploy.ts new file mode 100644 index 0000000..a90d714 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/commands/example/deploy.ts @@ -0,0 +1,45 @@ +import { + ExecuteCommandConfig, + makeExecuteCommand, + BeforeExecute, + AfterExecute, +} from '@pluginv3.0/starknet-gauntlet' +import { DeployExampleBaseConfig, DeployExampleInput } from '@pluginv3.0/gauntlet-contracts-example' +import { tokenContractLoader } from '../../lib/contracts' + +type ContractInput = {} + +const makeContractInput = async (input: DeployExampleInput): Promise => { + return {} +} + +// This is a custom beforeExecute hook executed right before the command action is executed +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info('About to deploy a Sample Contract') +} +// This is a custom afterExecute hook executed right after the command action is executed +const afterExecute: AfterExecute = ( + context, + input, + deps, +) => async (result) => { + deps.logger.info( + `Contract deployed with address: ${result.responses[0].tx.address} at tx hash: ${result.responses[0].tx.hash}`, + ) +} + +const commandConfig: ExecuteCommandConfig = { + ...DeployExampleBaseConfig, + makeContractInput: makeContractInput, + loadContract: tokenContractLoader, + hooks: { + beforeExecute, + afterExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-example/src/commands/example/increaseBalance.ts b/packages-ts/starknet-gauntlet-example/src/commands/example/increaseBalance.ts new file mode 100644 index 0000000..62b68c1 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/commands/example/increaseBalance.ts @@ -0,0 +1,21 @@ +import { ExecuteCommandConfig, makeExecuteCommand, Validation } from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { tokenContractLoader } from '../../lib/contracts' +import { + IncreaseBalanceBaseConfig, + IncreaseBalanceInput, +} from '@pluginv3.0/gauntlet-contracts-example' + +type ContractInput = [number] + +const makeContractInput = async (input: IncreaseBalanceInput): Promise => { + return [Number(input.balance)] +} + +const commandConfig: ExecuteCommandConfig = { + ...IncreaseBalanceBaseConfig, + makeContractInput: makeContractInput, + loadContract: tokenContractLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-example/src/commands/example/index.ts b/packages-ts/starknet-gauntlet-example/src/commands/example/index.ts new file mode 100644 index 0000000..88c948b --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/commands/example/index.ts @@ -0,0 +1,5 @@ +import Deploy from './deploy' +import IncreaseBalance from './increaseBalance' +import Inspection from './inspection' +export const executeCommands = [Deploy, IncreaseBalance] +export const inspectionCommands = [...Inspection] diff --git a/packages-ts/starknet-gauntlet-example/src/commands/example/inspection/index.ts b/packages-ts/starknet-gauntlet-example/src/commands/example/inspection/index.ts new file mode 100644 index 0000000..a8eb612 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/commands/example/inspection/index.ts @@ -0,0 +1,3 @@ +import Inspect from './inspect' + +export default [Inspect] diff --git a/packages-ts/starknet-gauntlet-example/src/commands/example/inspection/inspect.ts b/packages-ts/starknet-gauntlet-example/src/commands/example/inspection/inspect.ts new file mode 100644 index 0000000..ab6abbc --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/commands/example/inspection/inspect.ts @@ -0,0 +1,42 @@ +import { BN } from '@pluginv3.0/gauntlet-core/dist/utils' +import { + InspectCommandConfig, + IStarknetProvider, + makeInspectionCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../../lib/categories' +import { tokenContractLoader } from '../../../lib/contracts' + +type QueryResult = { + balance: string +} + +const makeComparisionData = (provider: IStarknetProvider) => async ( + results: any[], + input: null, + contractAddress: string, +): Promise<{ + toCompare: null + result: QueryResult +}> => { + const [balance] = results + return { + toCompare: null, + result: { + balance: new BN(balance.res).toString(), + }, + } +} + +const commandConfig: InspectCommandConfig = { + ux: { + category: CATEGORIES.EXAMPLE, + function: 'inspect', + examples: ['yarn gauntlet token:inspect --network='], + }, + queries: ['get_balance'], + makeComparisionData, + loadContract: tokenContractLoader, +} + +export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-example/src/commands/index.ts b/packages-ts/starknet-gauntlet-example/src/commands/index.ts new file mode 100644 index 0000000..b458e92 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/commands/index.ts @@ -0,0 +1,7 @@ +import { + executeCommands as executeExampleCommands, + inspectionCommands as inspectionExampleCommands, +} from './example' + +export const executeCommands = [...executeExampleCommands] +export const inspectionCommands = [...inspectionExampleCommands] diff --git a/packages-ts/starknet-gauntlet-example/src/index.ts b/packages-ts/starknet-gauntlet-example/src/index.ts new file mode 100644 index 0000000..8c2064b --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/index.ts @@ -0,0 +1,3 @@ +import { executeCommands, inspectionCommands } from './commands' + +export { executeCommands, inspectionCommands } diff --git a/packages-ts/starknet-gauntlet-example/src/lib/categories.ts b/packages-ts/starknet-gauntlet-example/src/lib/categories.ts new file mode 100644 index 0000000..2ac2ed3 --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/lib/categories.ts @@ -0,0 +1,5 @@ +import { CONTRACT_LIST } from './contracts' + +export const CATEGORIES = { + EXAMPLE: CONTRACT_LIST.EXAMPLE, +} diff --git a/packages-ts/starknet-gauntlet-example/src/lib/contracts.ts b/packages-ts/starknet-gauntlet-example/src/lib/contracts.ts new file mode 100644 index 0000000..c88f21d --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/src/lib/contracts.ts @@ -0,0 +1,14 @@ +import fs from 'fs' +import { CompiledContract, json } from 'starknet' + +export enum CONTRACT_LIST { + EXAMPLE = 'example', +} + +export const loadContract = (name: CONTRACT_LIST): CompiledContract => { + return json.parse( + fs.readFileSync(`${__dirname}/../../contract_artifacts/abi/${name}.json`).toString('ascii'), + ) +} + +export const tokenContractLoader = () => loadContract(CONTRACT_LIST.EXAMPLE) diff --git a/packages-ts/starknet-gauntlet-example/test/commands/example.test.ts b/packages-ts/starknet-gauntlet-example/test/commands/example.test.ts new file mode 100644 index 0000000..33d6aad --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/test/commands/example.test.ts @@ -0,0 +1,102 @@ +import { BN } from '@pluginv3.0/gauntlet-core/dist/utils' +import { makeProvider } from '@pluginv3.0/starknet-gauntlet' +import { Contract } from 'starknet' +import deployCommand from '../../src/commands/example/deploy' +import increaseBalanceCommand from '../../src/commands/example/increaseBalance' +import inspectionCommand from '../../src/commands/example/inspection/inspect' +import { + LOCAL_URL, + registerExecuteCommand, + TIMEOUT, + registerInspectCommand, + startNetwork, + IntegratedDevnet, +} from '@pluginv3.0/starknet-gauntlet/test/utils' +import { loadExampleContract } from '../utils' + +const getBalance = async (address: string) => { + const contract = new Contract( + loadExampleContract().abi, + address, + makeProvider(LOCAL_URL).provider, + ) + const balance = await contract.get_balance() + + return new BN(balance.res).toString() +} + +describe('Example Contract', () => { + let network: IntegratedDevnet + let contractAddress: string + + beforeAll(async () => { + network = await startNetwork() + }, TIMEOUT) + + it( + 'Deployment with default input', + async () => { + const command = await registerExecuteCommand(deployCommand).create({}, []) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + contractAddress = report.responses[0].contract + }, + TIMEOUT, + ) + + it( + 'Increase balance with input flag', + async () => { + const command = await registerExecuteCommand(increaseBalanceCommand).create( + { + input: { balance: '100' }, + }, + [contractAddress], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + const balance = await getBalance(contractAddress) + expect(balance).toEqual('100') + }, + TIMEOUT, + ) + + it( + 'Increase balance with custom flags', + async () => { + const command = await registerExecuteCommand(increaseBalanceCommand).create( + { + balance: '100', + }, + [contractAddress], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + const balance = await getBalance(contractAddress) + expect(balance).toEqual('200') + }, + TIMEOUT, + ) + + it('Inspection of state with no account', async () => { + const command = await registerInspectCommand(inspectionCommand).create({}, [contractAddress]) + + const expectedResult = { + balance: '200', + } + const report = await command.execute() + expect(report.data.data).toEqual(expectedResult) + }, 3000) + + // TODO: Include tests with account contract. Pending on devnet to support predeployed accounts and fee token + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet-example/test/utils/index.ts b/packages-ts/starknet-gauntlet-example/test/utils/index.ts new file mode 100644 index 0000000..ea2336c --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/test/utils/index.ts @@ -0,0 +1,29 @@ +import { CompiledContract, json } from 'starknet' +import fs from 'fs' +import { logger, prompt } from '@pluginv3.0/gauntlet-core/dist/utils' + +export const loadContract = (name: string): CompiledContract => { + return json.parse( + fs.readFileSync(`${__dirname}/../../contract_artifacts/abi/${name}.json`).toString('ascii'), + ) +} + +export const loadExampleContract = () => loadContract('example') + +export const noop = () => {} + +export const noopLogger: typeof logger = { + table: noop, + log: noop, + info: noop, + warn: noop, + success: noop, + error: noop, + loading: noop, + line: noop, + style: () => '', + debug: noop, + time: noop, +} + +export const noopPrompt: typeof prompt = async () => {} diff --git a/packages-ts/starknet-gauntlet-example/tsconfig.json b/packages-ts/starknet-gauntlet-example/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-example/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-ledger/LICENSE b/packages-ts/starknet-gauntlet-ledger/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-ledger/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-ledger/package.json b/packages-ts/starknet-gauntlet-ledger/package.json new file mode 100644 index 0000000..1125f2d --- /dev/null +++ b/packages-ts/starknet-gauntlet-ledger/package.json @@ -0,0 +1,32 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-ledger", + "version": "0.0.1", + "description": "Gauntlet Starknet Ledger Signer", + "keywords": [ + "typescript", + "ledger", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-token --passWithNoTests", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/starknet-gauntlet": "*", + "@ledgerhq/hw-app-starknet": "^2.0.3", + "@ledgerhq/hw-transport-node-hid": "^6.27.6" + } + } + \ No newline at end of file diff --git a/packages-ts/starknet-gauntlet-ledger/src/index.ts b/packages-ts/starknet-gauntlet-ledger/src/index.ts new file mode 100644 index 0000000..58b7258 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ledger/src/index.ts @@ -0,0 +1,140 @@ +import { IStarknetWallet, Env } from '@pluginv3.0/starknet-gauntlet' +import { + SignerInterface, + encode, + DeployAccountSignerDetails, + DeclareSignerDetails, + typedData, + hash, + transaction, + Abi, + Signature, + Call, + InvocationsSignerDetails, + ec, +} from 'starknet' +import { Stark, LedgerError } from '@ledgerhq/hw-app-starknet' + +// EIP-2645 path +// 2645 - EIP number +// 579218131 - layer - 31 lowest bits of sha256("starkex") +// 894929996 - application - 31 lowest bits of sha256("plugin") +export const DEFAULT_LEDGER_PATH = "m/2645'/579218131'/894929996'/0'" +export const LEDGER_PATH_REGEX = /^\s*m\s*\/\s*2645\s*\'\s*\/\s*579218131\s*\'\s*\/\s*(\d+)\s*\'\s*\/\s*(\d+)\s*\'$/ + +// TODO: why are we copying this rather than using https://github.com/yogh333/starknetjs-signer-ledger/blob/main/src/ledger-signer.ts +class LedgerSigner implements SignerInterface { + client: Stark + path: string + publicKey: string + + private constructor(client: Stark, path: string, publicKey: string) { + this.client = client + this.path = path + this.publicKey = publicKey + } + + static create = async (path?: string): Promise => { + if (!path) { + path = DEFAULT_LEDGER_PATH + } else { + const match = LEDGER_PATH_REGEX.exec(path) + if (!match) { + throw new Error( + "Provided ledger path doesn't correspond the expected format m/2645'/579218131'/'/'", + ) + } + } + + // work around jest reimporting the package + // package is only allowed to be imported once + const Transport = (await import('@ledgerhq/hw-transport-node-hid')).default + const transport = await Transport.create() + const ledgerConnector = new Stark(transport) + + const response = await ledgerConnector.getPubKey(path) + if (response.returnCode != LedgerError.NoErrors) { + throw new Error(`Unable to get public key: ${response.errorMessage}. Is Ledger app active?`) + } + + const publicKey = encode.addHexPrefix(encode.buf2hex(response.publicKey).slice(2, 2 + 64)) + const signer = new LedgerSigner(ledgerConnector, path, publicKey) + + return signer + } + + async getPubKey(): Promise { + return this.publicKey + } + + async signTransaction( + transactions: Call[], + transactionsDetail: InvocationsSignerDetails, + abis?: Abi[], + ): Promise { + const calldata = transaction.fromCallsToExecuteCalldataWithNonce( + transactions, + transactionsDetail.nonce, + ) + + const msgHash = hash.calculateTransactionHash( + transactionsDetail.walletAddress, + transactionsDetail.version, + calldata, + transactionsDetail.maxFee, + transactionsDetail.chainId, + transactionsDetail.nonce, + ) + + return this.sign(msgHash) + } + + async signDeployAccountTransaction(transaction: DeployAccountSignerDetails): Promise { + // TODO: implement this + return new ec.starkCurve.Signature(BigInt(0), BigInt(0)) + } + + async signDeclareTransaction(transaction: DeclareSignerDetails): Promise { + // TODO: implement this + return new ec.starkCurve.Signature(BigInt(0), BigInt(0)) + } + + async signMessage(data: typedData.TypedData, accountAddress: string): Promise { + const msgHash = typedData.getMessageHash(data, accountAddress) + return this.sign(msgHash) + } + + async sign(hash: string): Promise { + const response = await this.client.sign(this.path, hash, true) + if (response.returnCode != LedgerError.NoErrors) { + throw new Error(`Unable to sign the message: ${response.errorMessage}`) + } + + return new ec.starkCurve.Signature( + BigInt(encode.addHexPrefix(encode.buf2hex(response.r))), + BigInt(encode.addHexPrefix(encode.buf2hex(response.s))), + ) + } +} + +export class Wallet implements IStarknetWallet { + signer: LedgerSigner + account: string + + private constructor(signer: LedgerSigner, account?: string) { + this.signer = signer + this.account = account + } + + static create = async (ledgerPath?: string, account?: string): Promise => { + const ledgerSigner: LedgerSigner = await LedgerSigner.create(ledgerPath) + return new Wallet(ledgerSigner, account) + } + + getPublicKey = async (): Promise => await this.signer.getPubKey() + getAccountAddress = (): string => this.account +} + +export const makeWallet = async (env: Env): Promise => { + return Wallet.create(env.ledgerPath, env.account) +} diff --git a/packages-ts/starknet-gauntlet-ledger/test/ledger-path-regex.test.ts b/packages-ts/starknet-gauntlet-ledger/test/ledger-path-regex.test.ts new file mode 100644 index 0000000..bfbb0e9 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ledger/test/ledger-path-regex.test.ts @@ -0,0 +1,35 @@ +import { LEDGER_PATH_REGEX, DEFAULT_LEDGER_PATH } from '../src/' + +describe('Ledger Input Path', () => { + const wrongPathFormat1 = 'hola!' + const wrongPathFormat2 = "m/2645'/579218131'/0'/16'/67'/123'" + const wrongPathStartWith1 = "m/4417'/667845903'/894929996'/0'" + const wrongPathStartWith2 = " path 2645'/579218131'/894929996'/0'" + const pathWithSpaces = "m / 2645'/ 579218131' / 0 '/0 '" + + it("Doesn't validate wrong format", async () => { + let res = LEDGER_PATH_REGEX.exec(wrongPathFormat1) + expect(res).toBeFalsy() + + res = LEDGER_PATH_REGEX.exec(wrongPathFormat2) + expect(res).toBeFalsy() + }) + + it("Doesn't validate not starting with m/2645'/579218131'/", async () => { + let res = LEDGER_PATH_REGEX.exec(wrongPathStartWith1) + expect(res).toBeFalsy() + + res = LEDGER_PATH_REGEX.exec(wrongPathStartWith2) + expect(res).toBeFalsy() + }) + + it('Validates path with spaces', async () => { + const res = LEDGER_PATH_REGEX.exec(pathWithSpaces) + expect(res).toBeTruthy() + }) + + it('Validates default path', async () => { + const res = LEDGER_PATH_REGEX.exec(DEFAULT_LEDGER_PATH) + expect(res).toBeTruthy() + }) +}) diff --git a/packages-ts/starknet-gauntlet-ledger/tsconfig.json b/packages-ts/starknet-gauntlet-ledger/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-ledger/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-multisig/LICENSE b/packages-ts/starknet-gauntlet-multisig/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-multisig/README.md b/packages-ts/starknet-gauntlet-multisig/README.md new file mode 100644 index 0000000..f6052af --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/README.md @@ -0,0 +1,72 @@ +# Starknet Gauntlet Commands for Multisig Contract + +## Multisig + +### Deploy the contract + +```bash +yarn gauntlet multisig:deploy --network= --threshold= --signers=<[SIGNERS_LIST]> +``` + +Note that threshold must be equal or higher than the amount of signers + +Examples: + +```bash +yarn gauntlet multisig:deploy --network=local --threshold=2 --signers="[0x26e10005e67c478b373658755749a60f2f31bc955a6a2311eb456b20b8913e9, 0x56bfff7e282d1e023c6268e72dba551a22c1bf816a30334ae43b5c491c99bb8]" +# Or +yarn gauntlet multisig:deploy --network=local --input='{"threshold":2, "signers": ["0x26e10005e67c478b373658755749a60f2f31bc955a6a2311eb456b20b8913e9", "0x56bfff7e282d1e023c6268e72dba551a22c1bf816a30334ae43b5c491c99bb8"]}' +``` + +### Set signers + +Signers can only be updated through a transaction executed from the multisig itself + +```bash +yarn gauntlet multisig:set_signers:multisig --network= --signers=<[SIGNERS_LIST]> +``` + +### Set threshold + +Threshold can only be updated through a transaction executed from the multisig itself. + +```bash +yarn gauntlet multisig:set_thresold:multisig --network= --threshold= +``` + +## Wrapping Gauntlet commands + +A [wrap function](./src/wrapper/index.ts#L30) is exposed from this package. It allows to wrap any Gauntlet command and make its functionality available to be executed from a multisig wallet. The process is the same for every command: + +1. Create proposal + +```bash +yarn gauntlet ::multisig --network= (...) +``` + +This will create a proposal in the multisig contract, that needs to be approved and executed. +The proposal index will be prompted. + +2. Approve proposal + +`T` (threshold) signers need to run this command + +```bash +yarn gauntlet ::multisig --network= (...) --multisigProposal= +``` + +3. Execute proposal + +Once approvals have reached the threshold, the proposal can be executed. + +```bash +yarn gauntlet ::multisig --network= (...) --multisigProposal= +``` + +If you are running these commands from the `starknet-gauntlet-cli`, you'll want to add to your environment the Multisig address: + +```bash +# .env +... +MULTISIG= +``` diff --git a/packages-ts/starknet-gauntlet-multisig/package.json b/packages-ts/starknet-gauntlet-multisig/package.json new file mode 100644 index 0000000..7798fd8 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/package.json @@ -0,0 +1,32 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-multisig", + "version": "0.0.1", + "description": "Starknet Gauntlet Multisig", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-multisig --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "starsign-multisig": "0.3.0", + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/starknet-gauntlet": "*" + } +} diff --git a/packages-ts/starknet-gauntlet-multisig/src/commands/index.ts b/packages-ts/starknet-gauntlet-multisig/src/commands/index.ts new file mode 100644 index 0000000..4c417c5 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/commands/index.ts @@ -0,0 +1 @@ +export { executeCommands, inspectionCommands } from './multisig' diff --git a/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/deploy.ts b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/deploy.ts new file mode 100644 index 0000000..e54e72e --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/deploy.ts @@ -0,0 +1,83 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + ExecutionContext, + isValidAddress, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { num } from 'starknet' +import { CATEGORIES } from '../../lib/categories' +import { contractLoader } from '../../lib/contracts' + +type UserInput = { + signers: string[] + threshold: string +} + +type ContractInput = [signersLen: number, ...signers: string[], threshold: number] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + return { + signers: flags.signers, + threshold: flags.threshold, + } +} + +export const validateThreshold = async (input: UserInput) => { + const threshold = Number(input.threshold) + if (isNaN(threshold)) throw new Error('Threshold is not a number') + if (threshold > input.signers.length) + throw new Error( + `Threshold is higher than signers length: ${threshold} > ${input.signers.length}`, + ) + return true +} + +export const validateSigners = async (input) => { + const areValid = input.signers.every(isValidAddress) + if (!areValid) throw new Error('Signers are not valid accounts') + if (new Set(input.signers).size !== input.signers.length) + throw new Error('Signers are not unique') + return true +} + +const makeContractInput = async ( + input: UserInput, + context: ExecutionContext, +): Promise => { + return [input.signers.length, ...input.signers, parseInt(input.threshold)] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info(`About to deploy an Multisig Contract with the following details: + - Signers: ${input.user.signers} + - Threshold: ${input.user.threshold} + `) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CATEGORIES.MULTISIG, + category: CATEGORIES.MULTISIG, + action: 'deploy', + ux: { + description: 'Deploys Multisig Wallet', + examples: [ + `${CATEGORIES.MULTISIG}:deploy --network= --threshold= --signers=[SIGNERS_LIST]`, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateSigners, validateThreshold], + loadContract: contractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/index.ts b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/index.ts new file mode 100644 index 0000000..53773a0 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/index.ts @@ -0,0 +1,8 @@ +import Deploy from './deploy' +import SetSigners from './setSigners' +import SetThreshold from './setThreshold' + +import Inspection from './inspection' + +export const executeCommands = [Deploy, SetSigners, SetThreshold] +export const inspectionCommands = [...Inspection] diff --git a/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/index.ts b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/index.ts new file mode 100644 index 0000000..b99d0d0 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/index.ts @@ -0,0 +1,3 @@ +import Inspect from './inspection' + +export default [Inspect] diff --git a/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/inspection.ts b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/inspection.ts new file mode 100644 index 0000000..6e5f322 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/inspection/inspection.ts @@ -0,0 +1,44 @@ +import { + InspectCommandConfig, + IStarknetProvider, + makeInspectionCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { num } from 'starknet' +import { CATEGORIES } from '../../../lib/categories' +import { contractLoader } from '../../../lib/contracts' + +type QueryResult = { + signers: string[] + threshold: number +} + +const makeComparisionData = (provider: IStarknetProvider) => async ( + results: any[], + input: null, + contractAddress: string, +): Promise<{ + toCompare: null + result: QueryResult +}> => { + const [signers, threshold] = results + return { + toCompare: null, + result: { + signers: signers.signers.map((o) => num.toHex(o)), + threshold: threshold.confirmations_required, + }, + } +} + +const commandConfig: InspectCommandConfig = { + ux: { + category: CATEGORIES.MULTISIG, + function: 'inspect', + examples: [`${CATEGORIES.MULTISIG}:inspect --network=`], + }, + queries: ['get_signers', 'get_threshold'], + makeComparisionData, + loadContract: contractLoader, +} + +export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setSigners.ts b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setSigners.ts new file mode 100644 index 0000000..a167140 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setSigners.ts @@ -0,0 +1,57 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + ExecutionContext, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { contractLoader } from '../../lib/contracts' +import { validateSigners } from './deploy' + +type UserInput = { + signers: string[] +} + +type ContractInput = [signers: string[]] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + return { + signers: flags.signers, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.signers] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger + .info(`About to set signers on the Multisig Contract (${context.contractAddress}) with the following details: + - New Signers: ${input.user.signers} + `) +} + +const commandConfig: ExecuteCommandConfig = { + ux: { + description: 'Set signers of the multisig account', + examples: [`${CATEGORIES.MULTISIG}:set_signers --network= --signers=[SIGNERS_LIST]`], + }, + category: CATEGORIES.MULTISIG, + action: 'set_signers', + contractId: CATEGORIES.MULTISIG, + makeUserInput, + makeContractInput, + validations: [validateSigners], + loadContract: contractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setThreshold.ts b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setThreshold.ts new file mode 100644 index 0000000..c1f4c5f --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/commands/multisig/setThreshold.ts @@ -0,0 +1,65 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + ExecutionContext, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { contractLoader } from '../../lib/contracts' +import { validateThreshold as validateThresholdWithSigners } from './deploy' + +type UserInput = { + threshold: string +} + +type ContractInput = [threshold: string] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + return { + threshold: flags.threshold, + } +} + +const validateThreshold = async (input: UserInput, context: ExecutionContext) => { + const signers = (await context.contract.get_signers()).signers + return validateThresholdWithSigners({ ...input, signers }) +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.threshold] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger + .info(`About to set a new threshold on the Multisig Contract (${context.contractAddress}) with the following details: + - New Threshold: ${input.user.threshold} + `) +} + +const commandConfig: ExecuteCommandConfig = { + ux: { + description: 'Set threshold of the multisig account', + examples: [ + `${CATEGORIES.MULTISIG}:set_threshold --network= --threshold= `, + ], + }, + category: CATEGORIES.MULTISIG, + contractId: CATEGORIES.MULTISIG, + action: 'set_threshold', + internalFunction: 'set_threshold', + makeUserInput, + makeContractInput, + validations: [validateThreshold], + loadContract: contractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-multisig/src/index.ts b/packages-ts/starknet-gauntlet-multisig/src/index.ts new file mode 100644 index 0000000..938a5fd --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/index.ts @@ -0,0 +1,4 @@ +import { executeCommands, inspectionCommands } from './commands' +import { wrapCommand } from './wrapper' + +export { executeCommands, inspectionCommands, wrapCommand } diff --git a/packages-ts/starknet-gauntlet-multisig/src/lib/categories.ts b/packages-ts/starknet-gauntlet-multisig/src/lib/categories.ts new file mode 100644 index 0000000..5eaa872 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/lib/categories.ts @@ -0,0 +1,3 @@ +export const CATEGORIES = { + MULTISIG: 'multisig', +} diff --git a/packages-ts/starknet-gauntlet-multisig/src/lib/contracts.ts b/packages-ts/starknet-gauntlet-multisig/src/lib/contracts.ts new file mode 100644 index 0000000..e7b3a8e --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/lib/contracts.ts @@ -0,0 +1,18 @@ +import fs from 'fs' +import { CompiledContract, json } from 'starknet' + +export enum CONTRACT_LIST { + MULTISIG = 'Multisig', +} + +export const loadContract = (name: CONTRACT_LIST): CompiledContract => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../node_modules/starsign-multisig/starknet-artifacts/contracts/${name}.cairo/${name}.json`, + ) + .toString('ascii'), + ) +} + +export const contractLoader = () => loadContract(CONTRACT_LIST.MULTISIG) diff --git a/packages-ts/starknet-gauntlet-multisig/src/lib/utils.ts b/packages-ts/starknet-gauntlet-multisig/src/lib/utils.ts new file mode 100644 index 0000000..0740108 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/lib/utils.ts @@ -0,0 +1,13 @@ +import assert from 'assert' + +export const isDeepEqual = (a: any, b: any) => { + try { + assert.deepStrictEqual(a, b) + } catch (error) { + if (error.name === 'AssertionError') { + return false + } + throw error + } + return true +} diff --git a/packages-ts/starknet-gauntlet-multisig/src/wrapper/index.ts b/packages-ts/starknet-gauntlet-multisig/src/wrapper/index.ts new file mode 100644 index 0000000..fdac47c --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/wrapper/index.ts @@ -0,0 +1,288 @@ +import { Result, WriteCommand } from '@pluginv3.0/gauntlet-core' +import { isDeepEqual } from '@pluginv3.0/gauntlet-core/dist/utils/assertions' +import { + CommandCtor, + Dependencies, + ExecuteCommandInstance, + ExecutionContext, + Input, + IStarknetProvider, + IStarknetWallet, +} from '@pluginv3.0/starknet-gauntlet' +import { TransactionResponse } from '@pluginv3.0/starknet-gauntlet/dist/transaction' +import { + Call, + CompiledContract, + Contract, + addAddressPadding, + num, + encode, + hash, + validateAndParseAddress, + InvokeTransactionReceiptResponse, +} from 'starknet' +import { contractLoader } from '../lib/contracts' +import { Action, State } from './types' + +type UserInput = { + proposalId: number +} + +type ContractInput = {} + +type UnregisteredCommand = ( + deps: Dependencies, +) => CommandCtor> + +type ProposalAction = (message: Call, proposalId?: number) => Call + +export const wrapCommand = ( + registeredCommand: CommandCtor>, +): UnregisteredCommand => ( + deps: Dependencies, +): CommandCtor> => { + const id = `${registeredCommand.id}:multisig` + + const msigCommand: CommandCtor> = class MsigCommand + extends WriteCommand + implements ExecuteCommandInstance { + wallet: IStarknetWallet + provider: IStarknetProvider + contractAddress: string + account: string + executionContext: ExecutionContext + contract: CompiledContract + + input: Input + + command: ExecuteCommandInstance + multisigAddress: string + initialState: State + + static id = id + static category = registeredCommand.category + static examples = registeredCommand.examples + + constructor(flags, args) { + super(flags, args) + } + + static create = async (flags, args) => { + const c = new MsigCommand(flags, args) + + const env = deps.makeEnv(flags) + + c.wallet = await deps.makeWallet(env) + c.provider = deps.makeProvider(env.providerUrl, c.wallet) + c.contractAddress = args[0] + c.account = env.account + c.multisigAddress = env.multisig + c.contract = contractLoader() + + c.executionContext = { + provider: c.provider, + wallet: c.wallet, + id, + contractAddress: c.contractAddress, + flags: flags, + contract: new Contract(c.contract.abi, c.multisigAddress, c.provider.provider), + } + + c.input = { + user: flags.input || { + proposalId: Number(flags.proposalId || flags.multisigProposal), + }, + contract: {}, + } + + c.command = await registeredCommand.create(flags, [c.contractAddress]) + + c.initialState = await c.fetchMultisigState(c.multisigAddress, c.input.user.proposalId) + + return c + } + + fetchMultisigState = async (address: string, proposalId?: number): Promise => { + const [{ signers }, { threshold }] = await Promise.all( + ['get_signers', 'get_threshold'].map((func) => { + return this.executionContext.contract[func]() + }), + ) + const multisig = { + address, + threshold, + signers: signers.map((o) => num.toHex(o)), + } + + if (isNaN(proposalId)) return { multisig } + const proposal = await this.executionContext.contract.get_transaction(proposalId) + return { + multisig, + proposal: { + id: proposalId, + confirmations: proposal.tx.confirmations, + data: { + contractAddress: addAddressPadding(proposal.tx.to), + entrypoint: encode.addHexPrefix(num.toHex(num.toBigInt(proposal.tx.function_selector))), + calldata: proposal.tx_calldata.map((v) => num.toBigInt(v).toString()), + }, + nextAction: + Number(num.toBigInt(proposal.tx.executed)) !== 0 + ? Action.NONE + : proposal.tx.confirmations >= multisig.threshold + ? Action.EXECUTE + : Action.APPROVE, + }, + } + } + + isSameProposal = (local: Call, onchain: Call): boolean => { + const localAddress = validateAndParseAddress(local.contractAddress) + const onchainAddress = validateAndParseAddress(onchain.contractAddress) + if (localAddress !== onchainAddress) return false + if (hash.getSelectorFromName(local.entrypoint) !== onchain.entrypoint) return false + if (!isDeepEqual(local.calldata, onchain.calldata)) return false + return true + } + + makeProposeMessage: ProposalAction = (message, proposalId) => { + const invocation = this.executionContext.contract.populate('submit_transaction', [ + this.contractAddress, + hash.getSelectorFromName(message.entrypoint), + message.calldata, + proposalId, + ]) + return invocation + } + + makeAcceptMessage: ProposalAction = (_, proposalId) => { + const invocation = this.executionContext.contract.populate('confirm_transaction', [ + proposalId, + ]) + return invocation + } + + makeExecuteMessage: ProposalAction = (_, proposalId) => { + const invocation = this.executionContext.contract.populate('execute_transaction', [ + proposalId, + ]) + return invocation + } + + makeMessage = async () => { + const operations = { + [Action.APPROVE]: this.makeAcceptMessage, + [Action.EXECUTE]: this.makeExecuteMessage, + [Action.NONE]: () => { + throw new Error('No action needed') + }, + } + const message = await this.command.makeMessage() + if (!this.initialState.proposal) { + const { res: nonce } = await this.executionContext.contract.get_transactions_len() + return [this.makeProposeMessage(message[0], nonce)] + } + + if (!this.isSameProposal(message[0], this.initialState.proposal.data)) { + throw new Error('The transaction generated is different from the proposal provided') + } + + deps.logger.success('Generated proposal matches with the one provided') + + return [ + operations[this.initialState.proposal.nextAction]( + message[0], + this.initialState.proposal.id, + ), + ] + } + + beforeExecute = async () => { + if (!this.initialState.proposal) deps.logger.info('About to CREATE a new multisig proposal') + else + deps.logger.info( + `About to ${ + this.initialState.proposal.nextAction === Action.APPROVE ? 'APPROVE' : 'EXECUTE' + } the multisig proposal with ID: ${this.initialState.proposal.id}`, + ) + await deps.prompt('Continue?') + } + + afterExecute = async (result: Result, proposalId?: number) => { + if (proposalId === undefined) deps.logger.warn('Proposal ID not found') + deps.logger.loading('Fetching latest multisig and proposal state...') + const state = await this.fetchMultisigState(this.multisigAddress, proposalId) + if (!state.proposal) { + deps.logger.error(`Multisig proposal ${proposalId} not found`) + return + } + const approvalsLeft = state.multisig.threshold - state.proposal.confirmations + const messages = { + [Action.EXECUTE]: `The multisig proposal reached the threshold and can be executed. Run the same command with the flag --multisigProposal=${state.proposal.id}`, + [Action.APPROVE]: `The multisig proposal needs ${approvalsLeft} more approvals. Run the same command with the flag --multisigProposal=${state.proposal.id}`, + [Action.NONE]: `The multisig proposal has been executed. No more actions needed`, + } + deps.logger.line() + deps.logger.info(`${messages[state.proposal.nextAction]}`) + deps.logger.line() + return { proposalId } + } + + execute = async () => { + deps.logger.info(`Multisig State: + - Address: ${this.initialState.multisig.address} + - Signers: ${this.initialState.multisig.signers} + - Threshold: ${this.initialState.multisig.threshold} + `) + if (this.initialState.proposal) { + deps.logger.info(`Proposal State: + - ID: ${this.initialState.proposal.id} + - Approvals: ${this.initialState.proposal.confirmations} + - Next action: ${this.initialState.proposal.nextAction} + `) + } + const message = await this.makeMessage() + + // Underlying logger could have different style and probably a disabled prompt + await this.command.beforeExecute() + await this.beforeExecute() + + deps.logger.loading(`Signing and sending transaction...`) + const tx = await this.provider.signAndSend(message) + deps.logger.loading(`Waiting for tx confirmation at ${tx.hash}...`) + const response = await tx.wait() + + if (!response.success) { + deps.logger.error(`Tx was not successful: ${tx.errorMessage}`) + } else { + deps.logger.success(`Tx executed at ${tx.hash}`) + } + + let result = { + responses: [ + { + tx, + contract: tx.address, + }, + ], + } + + let proposalId = this.input.user.proposalId + if (!this.initialState.proposal) { + const txInfo = (await this.provider.provider.getTransactionReceipt( + tx.hash, + )) as InvokeTransactionReceiptResponse + proposalId = Number(num.hexToDecimalString((txInfo.events[0] as any).data[1])) + } + + const data = await this.afterExecute(result, proposalId) + + return !!data ? { ...result, data: { ...data } } : result + } + } + + return msigCommand +} diff --git a/packages-ts/starknet-gauntlet-multisig/src/wrapper/types.ts b/packages-ts/starknet-gauntlet-multisig/src/wrapper/types.ts new file mode 100644 index 0000000..6a12ad0 --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/src/wrapper/types.ts @@ -0,0 +1,21 @@ +import { Call } from 'starknet' + +export enum Action { + APPROVE = 'approve', + EXECUTE = 'execute', + NONE = 'none', +} + +export type State = { + multisig: { + address: string + threshold: number + signers: string[] + } + proposal?: { + id: number + nextAction: Action + data: Call + confirmations: number + } +} diff --git a/packages-ts/starknet-gauntlet-multisig/test/multisig/multisig.test.ts b/packages-ts/starknet-gauntlet-multisig/test/multisig/multisig.test.ts new file mode 100644 index 0000000..f9b76bd --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/test/multisig/multisig.test.ts @@ -0,0 +1,223 @@ +import { makeProvider, makeWallet, Dependencies } from '@pluginv3.0/starknet-gauntlet' +import deployCommand from '../../src/commands/multisig/deploy' +import setSigners from '../../src/commands/multisig/setSigners' +import setThreshold from '../../src/commands/multisig/setThreshold' +import { wrapCommand } from '../../src/wrapper' +import { + registerExecuteCommand, + TIMEOUT, + startNetwork, + IntegratedDevnet, + LOCAL_URL, +} from '@pluginv3.0/starknet-gauntlet/test/utils' +import { logger, prompt } from '@pluginv3.0/gauntlet-core/dist/utils' +import { CONTRACT_LIST, loadContract } from '../../src/lib/contracts' +import { Contract } from 'starknet' + +describe('Multisig', () => { + let network: IntegratedDevnet + let multisigContractAddress: string + const SEED: number = 10 + let accounts: string[] = [ + '0x72ad5b6e5a1c114c370eeabbe700cac4fdd7be47f2ada87ad3b89d346303dec', + '0x467e04fd5fee4f8a0023c5da41dcdfd963f7e4a9f498a29cbc5c8d030924f5d', + '0x77c3cd3e09a70580db713fc0d8da7298a9739dea23d4de561eac2991cb6c300', + ] + let publicKeys: string[] = [ + '0x5366dfa9668f9f51c6f4277455b34881262f12cb6b12b487877d9319a5b48bc', + '0x5ad457b3d822e2f1671c2046038a3bb45e6683895f7a4af266545de03e0d3e9', + '0x1a9dea7b74c0eee5f1873c43cc600a01ec732183d5b230efa9e945495823e9a', + ] + let privateKeys: string[] = [ + '0x7b89296c6dcbac5008577eb1924770d3', + '0x766bad0734c2da8003cc0f2793fdcab8', + '0x470b9805d2d6b8777dc59a3ad035d259', + ] + + let newSignerAccount = { + account: '0x5cdb30a922a2d4f9836877ed76c67564ec32625458884d0f1f2aef1ae023249', + publicKey: '0x6a5f1d67f6b59f3a2a294c3e523731b43fccbb7230985be7399c118498faf03', + privateKey: '0x8ceac392904cdefcf84b683a749f9c5', + } + + beforeAll(async () => { + network = await startNetwork({ seed: SEED }) + }, TIMEOUT) + + it( + 'Deployment', + async () => { + const command = await registerExecuteCommand(deployCommand).create( + { + signers: accounts, + threshold: 1, + pk: privateKeys[0], + publicKey: publicKeys[0], + account: accounts[0], + }, + [], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + multisigContractAddress = report.responses[0].contract + console.log(multisigContractAddress) + }, + TIMEOUT, + ) + + it( + 'Set Threshold with multisig', + async () => { + const deps: Dependencies = { + logger: logger, + prompt: prompt, + makeEnv: (flags) => { + return { + providerUrl: LOCAL_URL, + pk: privateKeys[0], + publicKey: publicKeys[0], + account: accounts[0], + multisig: multisigContractAddress, + } + }, + makeProvider: makeProvider, + makeWallet: makeWallet, + } + + // Create Multisig Proposal + const command = await wrapCommand(registerExecuteCommand(setThreshold))(deps).create( + { + threshold: 2, + }, + [multisigContractAddress], + ) + + let report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + const multisigProposalId = report.data.proposalId + + // Approve Multisig Proposal + const approveCommand = await wrapCommand(registerExecuteCommand(setThreshold))(deps).create( + { + threshold: 2, + multisigProposal: multisigProposalId, + }, + [multisigContractAddress], + ) + + report = await approveCommand.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + // Execute Multisig Proposal + const executeCommand = await wrapCommand(registerExecuteCommand(setThreshold))(deps).create( + { + threshold: 2, + multisigProposal: multisigProposalId, + }, + [multisigContractAddress], + ) + + report = await executeCommand.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + const multisig = loadContract(CONTRACT_LIST.MULTISIG) + const multisigContract = new Contract( + multisig.abi, + multisigContractAddress, + makeProvider(LOCAL_URL).provider, + ) + const { threshold } = await multisigContract.get_threshold() + expect(Number(threshold)).toEqual(2) + }, + TIMEOUT, + ) + + it( + 'Set Signers with multisig', + async () => { + let deps = (index: number): Dependencies => { + return { + logger: logger, + prompt: prompt, + makeEnv: (flags) => { + return { + providerUrl: LOCAL_URL, + pk: privateKeys[index], + publicKey: publicKeys[index], + account: accounts[index], + multisig: multisigContractAddress, + } + }, + makeProvider: makeProvider, + makeWallet: makeWallet, + } + } + + accounts.push(newSignerAccount.account) + + // Create Multisig Proposal + const command = await wrapCommand(registerExecuteCommand(setSigners))(deps(0)).create( + { + signers: accounts, + }, + [multisigContractAddress], + ) + + let report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + const multisigProposalId = report.data.proposalId + + // Approve Multisig Proposal (with account 0) + let approveCommand = await wrapCommand(registerExecuteCommand(setSigners))(deps(0)).create( + { + signers: accounts, + multisigProposal: multisigProposalId, + }, + [multisigContractAddress], + ) + + report = await approveCommand.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + // Approve Multisig Proposal (with account 1) + approveCommand = await wrapCommand(registerExecuteCommand(setSigners))(deps(1)).create( + { + signers: accounts, + multisigProposal: multisigProposalId, + }, + [multisigContractAddress], + ) + + report = await approveCommand.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + // Execute Multisig Proposal + const executeCommand = await wrapCommand(registerExecuteCommand(setSigners))(deps(0)).create( + { + signers: accounts, + multisigProposal: multisigProposalId, + }, + [multisigContractAddress], + ) + + report = await executeCommand.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + const multisig = loadContract(CONTRACT_LIST.MULTISIG) + const multisigContract = new Contract( + multisig.abi, + multisigContractAddress, + makeProvider(LOCAL_URL).provider, + ) + const { signers } = await multisigContract.get_signers() + expect(signers).toHaveLength(4) + }, + TIMEOUT, + ) + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet-multisig/tsconfig.json b/packages-ts/starknet-gauntlet-multisig/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-multisig/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-ocr2/LICENSE b/packages-ts/starknet-gauntlet-ocr2/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-ocr2/README.md b/packages-ts/starknet-gauntlet-ocr2/README.md new file mode 100644 index 0000000..5947467 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/README.md @@ -0,0 +1,57 @@ +# Starknet Gauntlet Commands for Plugin OCR2 Protocol + +## Set up + +Make sure you have your account details set up in your `.env` file + +```bash +# .env +PRIVATE_KEY=0x... +ACCOUNT=0x... +PLI=0x... +``` + +Note: The [token contract](https://github.com/goplugin/plugin-starknet/tree/develop/packages-ts/starknet-gauntlet-token) should only be deployed once and the same contract should be used for very aggregator + +## Deploy an Access Controller Contract + +Run the following command: + +```bash +yarn gauntlet access_controller:deploy --network= +``` + +This command will generate a new Access Controller address and will give the details during the deployment. You can then add this contract address in your `.env` files as `BILLING_ACCESS_CONTROLLER`, or pass it into the command directly (as shown below) + +## Deploy an OCR2 Contract + +Run the following command substituting the following attributes: + +1. with the [deployed token contract](https://github.com/goplugin/plugin-starknet/tree/develop/packages-ts/starknet-gauntlet-token) +2. with the access controller contract you deployed in the previous section + +```bash +yarn gauntlet ocr2:deploy --network= --billingAccessController= --minSubmissionValue= --maxSubmissionValue= --decimals= --name= --link= +``` + +This command will generate a new OCR2 address and will give the details during the deployment + +## Set the Billing Details on OCR2 Contract + +Run the following command substituting with the OCR2 contract address you received in the deploy step: + +``` +yarn gauntlet ocr2:set_billing --observationPaymentGjuels= --transmissionPaymentGjuels= +``` + +This Should set the billing details for this feed on contract address + +## Set the Config Details on OCR2 Contract + +Run the following command substituting with the OCR2 contract address you received in the deploy step: + +``` +yarn gauntlet ocr2:set_config --network= --address=
--f= --signers=[] --transmitters=[] --onchainConfig= --offchainConfig= --offchainConfigVersion= +``` + +This Should set the config for this feed on contract address. diff --git a/packages-ts/starknet-gauntlet-ocr2/package.json b/packages-ts/starknet-gauntlet-ocr2/package.json new file mode 100644 index 0000000..82ea122 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/package.json @@ -0,0 +1,33 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-ocr2", + "version": "0.0.1", + "description": "Starknet Gauntlet OCR2", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-ocr2 --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/gauntlet-contracts-ocr2": "0.2.2", + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/starknet-gauntlet": "*", + "@pluginv3.0/starknet-gauntlet-oz": "*" + } +} diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/deploy.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/deploy.ts new file mode 100644 index 0000000..529e6a8 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/deploy.ts @@ -0,0 +1,36 @@ +import { ExecuteCommandConfig, makeExecuteCommand } from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { accessControllerContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + owner: string +} + +type ContractInput = [owner: string] + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return { + owner: flags.owner || env.account, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.owner] +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.ACCESS_CONTROLLER, + category: CATEGORIES.ACCESS_CONTROLLER, + action: 'deploy', + ux: { + description: 'Deploys an Access Controller Contract', + examples: [`${CATEGORIES.ACCESS_CONTROLLER}:deploy --network=`], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: accessControllerContractLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/index.ts new file mode 100644 index 0000000..e2b8fe4 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/accessController/index.ts @@ -0,0 +1,3 @@ +import Deploy from './deploy' + +export const executeCommands = [Deploy] diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts new file mode 100644 index 0000000..972a1e1 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts @@ -0,0 +1,49 @@ +import { ExecuteCommandConfig, makeExecuteCommand } from '@pluginv3.0/starknet-gauntlet' +import { isValidAddress } from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { CONTRACT_LIST, aggregatorConsumerLoader } from '../../lib/contracts' + +export interface UserInput { + address: string +} + +type ContractInput = [address: string] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + return { + address: flags.address, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.address] +} + +const validateInput = async (input: UserInput): Promise => { + if (!isValidAddress(input.address)) { + throw new Error(`Invalid OCR2 address: ${input.address}`) + } + + return true +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.AGGREGATOR_CONSUMER, + category: CATEGORIES.OCR2, + action: 'deploy', + suffixes: ['consumer'], + ux: { + description: 'Deploys an example Aggregator consumer', + examples: [ + `${CATEGORIES.OCR2}:consumer:deploy --network= --address=[AGGREGATOR_ADDRESS]`, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateInput], + loadContract: aggregatorConsumerLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts new file mode 100644 index 0000000..dd4d013 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts @@ -0,0 +1,5 @@ +import Deploy from './deploy' +import Inspect from './inspect' + +export const executeCommands = [Deploy] +export const inspectionCommands = [Inspect] diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts new file mode 100644 index 0000000..089910f --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts @@ -0,0 +1,75 @@ +import { + InspectCommandConfig, + IStarknetProvider, + makeInspectionCommand, + InspectUserInput, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { aggregatorConsumerLoader } from '../../lib/contracts' +import { uint256 } from 'starknet' + +type UserInput = {} + +type ContractInput = null + +type QueryResult = { + roundId: string + answer: string + decimals: string +} + +const makeUserInput = async (flags, args): Promise> => { + if (flags.input) return flags.input as InspectUserInput + + return { + input: {}, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [] +} + +const makeComparisionData = (provider: IStarknetProvider) => async ( + results: any[], + input: null, + contractAddress: string, +): Promise<{ + toCompare: null + result: QueryResult +}> => { + const [round, decimals] = results + const { round_id, answer } = round[0] + + // workaround proxy returning incorrect round id (0x1 in high register uint256) + // todo: remove/adjust when figured out + const roundIdUint256 = uint256.bnToUint256(round_id) + roundIdUint256.high = 0 + const roundId = uint256.uint256ToBN(roundIdUint256) + + return { + toCompare: null, + result: { + roundId: roundId.toString(), + answer: answer.toString(), + decimals: decimals[0].toString(), + }, + } +} + +const commandConfig: InspectCommandConfig = { + ux: { + category: CATEGORIES.OCR2, + function: 'inspect:consumer', + examples: [ + `${CATEGORIES.OCR2}:inspect:consumer --network= `, + ], + }, + queries: ['readLatestRound', 'readDecimals'], + makeUserInput, + makeContractInput, + makeComparisionData, + loadContract: aggregatorConsumerLoader, +} + +export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts new file mode 100644 index 0000000..19c958b --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts @@ -0,0 +1,27 @@ +// import AccessController from './accessController' + +import { executeCommands as acExecuteCommands } from './accessController' +import { + executeCommands as ocr2ExecuteCommands, + inspectionCommands as ocr2InspectionCommands, +} from './ocr2' +import { + executeCommands as proxyExecuteCommands, + inspectionCommands as proxyInspectionCommands, +} from './proxy' +import { + executeCommands as exampleExecuteCommands, + inspectionCommands as exampleInspectionCommands, +} from './example' + +export const executeCommands = [ + ...acExecuteCommands, + ...ocr2ExecuteCommands, + ...proxyExecuteCommands, + ...exampleExecuteCommands, +] +export const inspectionCommands = [ + ...ocr2InspectionCommands, + ...proxyInspectionCommands, + ...exampleInspectionCommands, +] diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/addAccess.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/addAccess.ts new file mode 100644 index 0000000..85b1d03 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/addAccess.ts @@ -0,0 +1,62 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, + isValidAddress, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { ocr2ContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + address: string +} + +type ContractInput = [address: string] + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return { + address: flags.address, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.address] +} + +const validateAddresses = async (input) => { + if (!isValidAddress(input.address)) throw new Error(`Invalid address: ${input.address}`) + + return true +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info( + `About to add access to ${input.user.address} for aggregator at ${input.contract.join(', ')}`, + ) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.OCR2, + category: CATEGORIES.OCR2, + action: 'add_access', + ux: { + description: 'Add read access to aggregator', + examples: [ + `${CATEGORIES.PROXY}:add_access --network= --address=
`, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateAddresses], + loadContract: ocr2ContractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/deploy.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/deploy.ts new file mode 100644 index 0000000..b5a81c9 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/deploy.ts @@ -0,0 +1,48 @@ +import { ExecuteCommandConfig, makeExecuteCommand } from '@pluginv3.0/starknet-gauntlet' +import { BN } from '@pluginv3.0/gauntlet-core/dist/utils' +import { ocr2ContractLoader } from '../../lib/contracts' +import { shortString, number } from 'starknet' +import { DeployOCR2, DeployOCR2Input } from '@pluginv3.0/gauntlet-contracts-ocr2' + +export interface UserInput extends DeployOCR2Input { + owner: string +} + +type ContractInput = [ + owner: string, + link: string, + min_answer: number, + max_answer: number, + billing_access_controller: string, + decimals: number, + description: string, +] + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return { + ...DeployOCR2.makeUserInput(flags, args, env), + owner: flags.owner || env.account, + } as UserInput +} + +const makeContractInput = async (input: UserInput): Promise => { + return [ + input.owner, + input.linkToken, + input.minAnswer, + input.maxAnswer, + input.billingAccessController, + new BN(input.decimals).toNumber(), + shortString.encodeShortString(input.description), + ] +} + +const commandConfig: ExecuteCommandConfig = { + ...DeployOCR2, + makeUserInput: makeUserInput, + makeContractInput: makeContractInput, + loadContract: ocr2ContractLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/disableAccessCheck.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/disableAccessCheck.ts new file mode 100644 index 0000000..562d812 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/disableAccessCheck.ts @@ -0,0 +1,32 @@ +import { ExecuteCommandConfig, makeExecuteCommand } from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { ocr2ContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = {} + +type ContractInput = [] + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return {} +} + +const makeContractInput = async (input: UserInput): Promise => { + return [] +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.OCR2, + category: CATEGORIES.OCR2, + action: 'disable_access_check', + ux: { + description: 'Disable access check at aggregator', + examples: [`${CATEGORIES.OCR2}:disable_access_check --network= `], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: ocr2ContractLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/index.ts new file mode 100644 index 0000000..d1b70ca --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/index.ts @@ -0,0 +1,9 @@ +import Deploy from './deploy' +import inspect from './inspection/inspect' +import SetBilling from './setBilling' +import SetConfig from './setConfig' +import AddAccess from './addAccess' +import DisableAccessCheck from './disableAccessCheck' + +export const executeCommands = [Deploy, AddAccess, DisableAccessCheck, SetBilling, SetConfig] +export const inspectionCommands = [inspect] diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/inspect.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/inspect.ts new file mode 100644 index 0000000..af087f8 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/inspect.ts @@ -0,0 +1,41 @@ +import { + InspectCommandConfig, + IStarknetProvider, + makeInspectionCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { InvokeTransactionReceiptResponse } from 'starknet' +import { CATEGORIES } from '../../../lib/categories' +import { ocr2ContractLoader } from '../../../lib/contracts' + +type QueryResult = {} + +const makeComparisionData = (provider: IStarknetProvider) => async ( + results: any[], + input: null, + contractAddress: string, +): Promise<{ + toCompare: null + result: QueryResult +}> => { + const tx = (await provider.provider.getTransactionReceipt( + '0x475c15d6836972234c0542044fce7784cc61e8c5654d050aacadb918d8f3021', + )) as InvokeTransactionReceiptResponse + console.log(tx.events) + return { + toCompare: null, + result: {}, + } +} + +const commandConfig: InspectCommandConfig = { + ux: { + category: CATEGORIES.OCR2, + function: 'inspect', + examples: ['yarn gauntlet ocr2:inspect --network='], + }, + queries: [], + makeComparisionData, + loadContract: ocr2ContractLoader, +} + +export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setBilling.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setBilling.ts new file mode 100644 index 0000000..b6699cd --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setBilling.ts @@ -0,0 +1,43 @@ +import { ExecuteCommandConfig, makeExecuteCommand } from '@pluginv3.0/starknet-gauntlet' +import { BN } from '@pluginv3.0/gauntlet-core/dist/utils' +import { ocr2ContractLoader } from '../../lib/contracts' +import { SetBilling, SetBillingInput } from '@pluginv3.0/gauntlet-contracts-ocr2' + +type StarknetSetBillingInput = SetBillingInput & { gasBase: number; gasPerSignature: number } + +type ContractInput = [ + { + observation_payment_gjuels: number + transmission_payment_gjuels: number + gas_base: number + gas_per_signature: number + }, +] + +const makeContractInput = async (input: StarknetSetBillingInput): Promise => { + return [ + { + observation_payment_gjuels: new BN(input.observationPaymentGjuels).toNumber(), + transmission_payment_gjuels: new BN(input.transmissionPaymentGjuels).toNumber(), + gas_base: new BN(input.gasBase).toNumber(), + gas_per_signature: new BN(input.gasPerSignature).toNumber(), + }, + ] +} + +const commandConfig: ExecuteCommandConfig = { + ...SetBilling, + makeUserInput: (flags: any, args: any): StarknetSetBillingInput => { + if (flags.input) return flags.input as StarknetSetBillingInput + return { + observationPaymentGjuels: flags.observationPaymentGjuels, + transmissionPaymentGjuels: flags.transmissionPaymentGjuels, + gasBase: flags.gasBase, + gasPerSignature: flags.gasPerSignature, + } + }, + makeContractInput: makeContractInput, + loadContract: ocr2ContractLoader, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts new file mode 100644 index 0000000..82855e7 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts @@ -0,0 +1,89 @@ +import { + AfterExecute, + ExecuteCommandConfig, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { BN } from '@pluginv3.0/gauntlet-core/dist/utils' +import { ocr2ContractLoader } from '../../lib/contracts' +import { SetConfig, encoding, SetConfigInput } from '@pluginv3.0/gauntlet-contracts-ocr2' +import { bytesToFelts, decodeOffchainConfigFromEventData } from '../../lib/encoding' +import assert from 'assert' +import { InvokeTransactionReceiptResponse } from 'starknet' + +type Oracle = { + signer: string + transmitter: string +} + +type ContractInput = [ + oracles: Oracle[], + f: number, + onchain_config: string[], + offchain_config_version: number, + offchain_config: string[], +] + +const makeContractInput = async (input: SetConfigInput): Promise => { + const oracles: Oracle[] = input.signers.map((o, i) => { + // standard format from plugin node ocr2on_starknet_ (no 0x prefix) + let signer = input.signers[i].replace('ocr2on_starknet_', '') // replace prefix if present + signer = signer.startsWith('0x') ? signer : '0x' + signer // prepend 0x if missing + + return { + signer, + transmitter: input.transmitters[i], + } + }) + + // remove prefix if present on offchain key + input.offchainConfig.offchainPublicKeys = input.offchainConfig.offchainPublicKeys.map((k) => + k.replace('ocr2off_starknet_', ''), + ) + input.offchainConfig.configPublicKeys = input.offchainConfig.configPublicKeys.map((k) => + k.replace('ocr2cfg_starknet_', ''), + ) + + const { offchainConfig } = await encoding.serializeOffchainConfig( + input.offchainConfig, + input.secret, + ) + let onchainConfig = [] // onchain config should be empty array for input (generate onchain) + return [oracles, new BN(input.f).toNumber(), onchainConfig, 2, bytesToFelts(offchainConfig)] +} + +const afterExecute: AfterExecute = (context, input, deps) => async ( + result, +) => { + const txHash = result.responses[0].tx.hash + const txInfo = (await context.provider.provider.getTransactionReceipt( + txHash, + )) as InvokeTransactionReceiptResponse + if (txInfo.status === 'REJECTED') { + return { successfulConfiguration: false } + } + const eventData = txInfo.events[0].data + + const offchainConfig = decodeOffchainConfigFromEventData(eventData) + try { + // remove cfg keys from user input + delete input.user.offchainConfig.configPublicKeys + assert.deepStrictEqual(offchainConfig, input.user.offchainConfig) + deps.logger.success('Configuration was successfully set') + return { successfulConfiguration: true } + } catch (e) { + deps.logger.error('Configuration set is different than provided') + deps.logger.log(offchainConfig) + return { successfulConfiguration: false } + } +} + +const commandConfig: ExecuteCommandConfig = { + ...SetConfig, + makeContractInput: makeContractInput, + loadContract: ocr2ContractLoader, + hooks: { + afterExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/confirmAggregator.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/confirmAggregator.ts new file mode 100644 index 0000000..e6eb629 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/confirmAggregator.ts @@ -0,0 +1,63 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, + isValidAddress, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { ocr2ProxyLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + address: string +} + +type ContractInput = [address: string] + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return { + address: flags.address, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.address] +} + +const validateAddresses = async (input) => { + if (!isValidAddress(input.address)) + throw new Error(`Invalid aggregator address: ${input.address}`) + + return true +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info( + `About to confirm aggregator ${input.user.address} for proxy at ${input.contract.join(', ')}`, + ) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.PROXY, + category: CATEGORIES.PROXY, + action: 'confirm_aggregator', + ux: { + description: 'Confirm new aggregator for OCR2 proxy', + examples: [ + `${CATEGORIES.PROXY}:confirm_aggregator --network= --address= `, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateAddresses], + loadContract: ocr2ProxyLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/deploy.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/deploy.ts new file mode 100644 index 0000000..b40d6ff --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/deploy.ts @@ -0,0 +1,65 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, + isValidAddress, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { ocr2ProxyLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + owner: string + address: string +} + +type ContractInput = [owner: string, address: string] + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return { + owner: flags.owner || env.account, + address: flags.address, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.owner, input.address] +} + +const validateAddresses = async (input) => { + if (!isValidAddress(input.owner)) throw new Error(`Invalid owner address: ${input.owner}`) + + if (!isValidAddress(input.address)) + throw new Error(`Invalid aggregator address: ${input.address}`) + + return true +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info( + `About to deploy proxy for aggregator at ${input.user.address} with owner ${input.user.owner}`, + ) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.PROXY, + category: CATEGORIES.PROXY, + action: 'deploy', + ux: { + description: 'Deploys an OCR2 aggregator proxy', + examples: [`${CATEGORIES.PROXY}:deploy --network= --address=`], + }, + makeUserInput, + makeContractInput, + validations: [validateAddresses], + loadContract: ocr2ProxyLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/index.ts new file mode 100644 index 0000000..5930b6f --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/index.ts @@ -0,0 +1,7 @@ +import Deploy from './deploy' +import Inspect from './inspection/inspect' +import ProposeAggregator from './proposeAggregator' +import ConfirmAggregator from './confirmAggregator' + +export const executeCommands = [Deploy, ProposeAggregator, ConfirmAggregator] +export const inspectionCommands = [Inspect] diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/inspection/inspect.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/inspection/inspect.ts new file mode 100644 index 0000000..c0a4bc3 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/inspection/inspect.ts @@ -0,0 +1,61 @@ +import { + InspectCommandConfig, + IStarknetProvider, + makeInspectionCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { validateAndParseAddress, shortString } from 'starknet' +import { CATEGORIES } from '../../../lib/categories' +import { ocr2ProxyLoader } from '../../../lib/contracts' + +type QueryResult = { + round: any + aggregator: string + phaseId: string + description: string + decimals: number + typeAndVersion: string +} + +const makeComparisionData = (provider: IStarknetProvider) => async ( + results: any[], + input: null, + contractAddress: string, +): Promise<{ + toCompare: null + result: QueryResult +}> => { + return { + toCompare: null, + result: { + round: results[0][0], + aggregator: validateAndParseAddress(results[1][0]), + phaseId: results[2][0].toString(10), + description: shortString.decodeShortString(results[3][0].toJSON()), + decimals: results[4][0].toNumber(), + typeAndVersion: shortString.decodeShortString(results[5][0].toJSON()), + }, + } +} + +// TODO: make inspection for proposed aggregator +// causes sequencer to throw 500 error and whole inspection to fail if proposed aggregator not set + +const commandConfig: InspectCommandConfig = { + ux: { + category: CATEGORIES.PROXY, + function: 'inspect', + examples: ['yarn gauntlet proxy:inspect --network= '], + }, + queries: [ + 'latest_round_data', + 'aggregator', + 'phase_id', + 'description', + 'decimals', + 'type_and_version', + ], + makeComparisionData, + loadContract: ocr2ProxyLoader, +} + +export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/proposeAggregator.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/proposeAggregator.ts new file mode 100644 index 0000000..fe54772 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/proxy/proposeAggregator.ts @@ -0,0 +1,63 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, + isValidAddress, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { ocr2ProxyLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + address: string +} + +type ContractInput = [address: string] + +const makeUserInput = async (flags, args, env): Promise => { + if (flags.input) return flags.input as UserInput + return { + address: flags.address, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.address] +} + +const validateAddresses = async (input) => { + if (!isValidAddress(input.address)) + throw new Error(`Invalid aggregator address: ${input.address}`) + + return true +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info( + `About to propose aggregator ${input.user.address} for proxy at ${input.contract.join(', ')}`, + ) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.PROXY, + category: CATEGORIES.PROXY, + action: 'propose_aggregator', + ux: { + description: 'Propose new aggregator for OCR2 proxy', + examples: [ + `${CATEGORIES.PROXY}:propose_aggregator --network= --address= `, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateAddresses], + loadContract: ocr2ProxyLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/index.ts new file mode 100644 index 0000000..8c2064b --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/index.ts @@ -0,0 +1,3 @@ +import { executeCommands, inspectionCommands } from './commands' + +export { executeCommands, inspectionCommands } diff --git a/packages-ts/starknet-gauntlet-ocr2/src/lib/categories.ts b/packages-ts/starknet-gauntlet-ocr2/src/lib/categories.ts new file mode 100644 index 0000000..6001891 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/lib/categories.ts @@ -0,0 +1,5 @@ +export const CATEGORIES = { + ACCESS_CONTROLLER: 'access_controller', + OCR2: 'ocr2', + PROXY: 'proxy', +} diff --git a/packages-ts/starknet-gauntlet-ocr2/src/lib/contracts.ts b/packages-ts/starknet-gauntlet-ocr2/src/lib/contracts.ts new file mode 100644 index 0000000..c9929c9 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/lib/contracts.ts @@ -0,0 +1,46 @@ +import fs from 'fs' +import { CompiledContract, json } from 'starknet' + +export enum CONTRACT_LIST { + OCR2 = 'aggregator', + ACCESS_CONTROLLER = 'simple_write_access_controller', + PROXY = 'aggregator_proxy', + AGGREGATOR_CONSUMER = 'Aggregator_consumer', +} + +export const loadContract_Ocr2 = (name: CONTRACT_LIST): CompiledContract => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/starknet-artifacts/src/plugin/cairo/ocr2/${name}.cairo/${name}.json`, + ) + .toString('ascii'), + ) +} + +export const loadContract_Example = (name: CONTRACT_LIST): CompiledContract => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/starknet-artifacts/src/plugin/cairo/example/${name}.cairo/${name}.json`, + ) + .toString('ascii'), + ) +} + +export const loadContract_AccessController = (name: CONTRACT_LIST): CompiledContract => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/starknet-artifacts/src/plugin/cairo/access/SimpleWriteAccessController/${name}.cairo/${name}.json`, + ) + .toString('ascii'), + ) +} + +export const ocr2ContractLoader = () => loadContract_Ocr2(CONTRACT_LIST.OCR2) +export const ocr2ProxyLoader = () => loadContract_Ocr2(CONTRACT_LIST.PROXY) +export const aggregatorConsumerLoader = () => + loadContract_Example(CONTRACT_LIST.AGGREGATOR_CONSUMER) +export const accessControllerContractLoader = () => + loadContract_AccessController(CONTRACT_LIST.ACCESS_CONTROLLER) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts b/packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts new file mode 100644 index 0000000..f0d1828 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts @@ -0,0 +1,98 @@ +import { num, constants, cairo } from 'starknet' +import BN from 'bn.js' +import { encoding } from '@pluginv3.0/gauntlet-contracts-ocr2' + +const CHUNK_SIZE = 31 + +function packUint8Array(data: Uint8Array | Buffer): bigint { + let result: bigint = BigInt(0) + for (let i = 0; i < data.length; i++) { + result = (result << BigInt(8)) | BigInt(data[i]) + } + return result +} + +export function bytesToFelts(data: Uint8Array | Buffer): string[] { + const felts: string[] = [] + + // prefix with data length + felts.push(cairo.felt(data.byteLength)) + + // chunk every 31 bytes + for (let i = 0; i < data.length; i += CHUNK_SIZE) { + const chunk = data.slice(i, i + CHUNK_SIZE) + // cairo.felt() does not support packing a Uint8Array natively. + const packedValue = packUint8Array(chunk) + felts.push(cairo.felt(packedValue)) + } + return felts +} + +export function bytesToFeltsDeprecated(data: Uint8Array): string[] { + let felts: string[] = [] + // prefix with len + let len = data.byteLength + felts.push(num.toBigInt(len).toString()) + // chunk every 31 bytes + for (let i = 0; i < data.length; i += CHUNK_SIZE) { + const chunk = data.slice(i, i + CHUNK_SIZE) + // cast to int + felts.push(new BN(chunk, 'be').toString()) + } + return felts +} + +const MAX_LEN: bigint = (BigInt(1) << BigInt(54)) - BigInt(1) + +export function feltsToBytes(felts: string[]): Buffer { + const data: number[] = [] + + if (!felts.length) { + throw new Error('Felt string is empty') + } + + const remainingLengthBigInt = BigInt(felts.shift()) + if (remainingLengthBigInt > MAX_LEN) { + throw new Error('Length does not fit in 54 bits') + } + + let remainingLength = Number(remainingLengthBigInt) + for (let felt of felts) { + if (remainingLength <= 0) { + throw new Error( + `Too many felts (${felts.length}) for length ${remainingLengthBigInt.toString()}`, + ) + } + const chunkSize = Math.min(CHUNK_SIZE, remainingLength) + let packedValue: bigint = BigInt(felt) + const unpackedValues: number[] = [] + for (let i = 0; i < chunkSize; i++) { + unpackedValues.push(Number(packedValue & BigInt(0xff))) + packedValue = packedValue >> BigInt(8) + } + unpackedValues.reverse() + data.push(...unpackedValues) + remainingLength -= chunkSize + } + + return Buffer.from(data) +} + +export const decodeOffchainConfigFromEventData = (data: string[]): encoding.OffchainConfig => { + const oraclesLen = Number(num.toBigInt(data[3])) + /** SetConfig event data has the following info: + 0 : previous_config_block_number=prev_block_num, + 1 : latest_config_digest=digest, + 2 : config_count=config_count, + 3 : oracles_len=oracles_len, // It includes both signer and transmitter addresses + 3 + 2X : oracles=oracles, + 3 + 2X + 1 : f=f, + 3 + 2X + 2 + 3 : onchain_config_len=OnchainConfig.SIZE = 3 + onchain_config=onchain_config, + 3 + 2X + 2 + 3 + 1 : offchain_config_version=offchain_config_version, + 3 + 2X + 2 + 3 + 2 : offchain_config_len=offchain_config_len, + 3 + 2X + 2 + 3 + 3 : offchain_config=offchain_config + */ + const offchainConfigFelts = data.slice(3 + oraclesLen * 2 + 8) + return encoding.deserializeConfig(feltsToBytes(offchainConfigFelts)) +} diff --git a/packages-ts/starknet-gauntlet-ocr2/test/commands/access_controller.test.ts b/packages-ts/starknet-gauntlet-ocr2/test/commands/access_controller.test.ts new file mode 100644 index 0000000..d404eb0 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/test/commands/access_controller.test.ts @@ -0,0 +1,30 @@ +import deployCommand from '../../src/commands/accessController/deploy' +import { + registerExecuteCommand, + TIMEOUT, + startNetwork, + IntegratedDevnet, +} from '@pluginv3.0/starknet-gauntlet/test/utils' + +describe('Access Controller Contract', () => { + let network: IntegratedDevnet + + beforeAll(async () => { + network = await startNetwork() + }, 15000) + + it( + 'Deployment', + async () => { + const command = await registerExecuteCommand(deployCommand).create({}, []) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + }, + TIMEOUT, + ) + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet-ocr2/test/commands/ocr2.test.ts b/packages-ts/starknet-gauntlet-ocr2/test/commands/ocr2.test.ts new file mode 100644 index 0000000..6ffc09f --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/test/commands/ocr2.test.ts @@ -0,0 +1,199 @@ +import { makeProvider } from '@pluginv3.0/starknet-gauntlet' +import deployCommand from '../../src/commands/ocr2/deploy' +import setBillingCommand from '../../src/commands/ocr2/setBilling' +import setConfigCommand from '../../src/commands/ocr2/setConfig' +import deployACCommand from '../../src/commands/accessController/deploy' +import { + registerExecuteCommand, + TIMEOUT, + LOCAL_URL, + startNetwork, + IntegratedDevnet, + devnetAccount0Address, +} from '@pluginv3.0/starknet-gauntlet/test/utils' +import { loadContract_Ocr2, CONTRACT_LIST } from '../../src/lib/contracts' +import { Contract, InvokeTransactionReceiptResponse } from 'starknet' +import { BN } from '@pluginv3.0/gauntlet-core/dist/utils' + +let account = devnetAccount0Address + +const signers = [ + 'ocr2on_starknet_04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603730', // ocr2on_starknet_ + 'ocr2on_starknet_0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603731', // ocr2on_starknet_0x + '0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603732', // 0x + '04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603733', // +] + +const transmitters = [ + '0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603734', + '0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603735', + '0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603736', + '0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603737', +] + +const validInput = { + f: 1, + signers, + transmitters, + onchainConfig: '', + offchainConfig: { + deltaProgressNanoseconds: 8000000000, + deltaResendNanoseconds: 30000000000, + deltaRoundNanoseconds: 3000000000, + deltaGraceNanoseconds: 500000000, + deltaStageNanoseconds: 20000000000, + rMax: 5, + s: [1, 2], + offchainPublicKeys: [ + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852090', + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852091', + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852092', + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852093', + ], + peerIds: signers, + reportingPluginConfig: { + alphaReportInfinite: false, + alphaReportPpb: 0, + alphaAcceptInfinite: false, + alphaAcceptPpb: 0, + deltaCNanoseconds: 0, + }, + maxDurationQueryNanoseconds: 0, + maxDurationObservationNanoseconds: 1000000000, + maxDurationReportNanoseconds: 200000000, + maxDurationShouldAcceptFinalizedReportNanoseconds: 200000000, + maxDurationShouldTransmitAcceptedReportNanoseconds: 200000000, + configPublicKeys: [ + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852094', + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852095', + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852096', + 'af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852097', + ], + }, + offchainConfigVersion: 2, + secret: 'awe accuse polygon tonic depart acuity onyx inform bound gilbert expire', +} + +describe('OCR2 Contract', () => { + let network: IntegratedDevnet + let contractAddress: string + let accessController: string + + beforeAll(async () => { + network = await startNetwork() + }, TIMEOUT) + + it( + 'Deploy AC', + async () => { + // TODO: owner can't be 0 anymore + const command = await registerExecuteCommand(deployACCommand).create({}, []) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + accessController = report.responses[0].contract + }, + TIMEOUT, + ) + + it( + 'Deployment', + async () => { + const command = await registerExecuteCommand(deployCommand).create( + { + input: { + owner: account, + maxAnswer: 10000, + minAnswer: 1, + decimals: 18, + description: 'Test Feed', + billingAccessController: accessController, + linkToken: '0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603730', + }, + }, + [], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + contractAddress = report.responses[0].contract + }, + TIMEOUT, + ) + + it( + 'Set billing', + async () => { + // transfer overflow on set billing + const command = await registerExecuteCommand(setBillingCommand).create( + { + input: { + observationPaymentGjuels: 1, + transmissionPaymentGjuels: 1, + gasBase: 14951, + gasPerSignature: 13, + }, + }, + [contractAddress], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + const ocr2 = loadContract_Ocr2(CONTRACT_LIST.OCR2) + const ocr2Contract = new Contract(ocr2.abi, contractAddress, makeProvider(LOCAL_URL).provider) + const response = await ocr2Contract.billing() + const { config: billing } = response + expect(billing.observation_payment_gjuels).toEqual(BigInt(1)) + expect(billing.transmission_payment_gjuels).toEqual(BigInt(1)) + }, + TIMEOUT, + ) + + it( + 'Set config using --input', + async () => { + const command = await registerExecuteCommand(setConfigCommand).create( + { + input: validInput, + }, + [contractAddress], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + const provider = makeProvider(LOCAL_URL).provider + const ocr2 = loadContract_Ocr2(CONTRACT_LIST.OCR2) + const ocr2Contract = new Contract(ocr2.abi, contractAddress, provider) + const response = await ocr2Contract.transmitters() + const { transmitters: resultTransmitters } = response + + // retrieve signer keys from transaction event + // based on event struct: https://github.com/goplugin/plugin-starknet/blob/develop/contracts/src/plugin/ocr2/aggregator.cairo#L260 + const receipt = (await provider.getTransactionReceipt( + report.responses[0].tx.hash, + )) as InvokeTransactionReceiptResponse + + // TODO: use StarknetContract decodeEvents from starknet-hardhat-plugin instead + const eventData = receipt.events[0].data + // reconstruct signers array from event + let eventSigners = [] + for (let i = 0; i < signers.length; i++) { + const signer = new BN(eventData[4 + 2 * i].replace('0x', ''), 16) // split according to event structure + eventSigners.push(signer) + } + + expect(eventSigners).toEqual( + signers.map((s) => new BN(s.replace('ocr2on_starknet_', '').replace('0x', ''), 16)), + ) // remove all prefixes + expect(resultTransmitters).toEqual(transmitters.map((transmitter) => BigInt(transmitter))) + }, + TIMEOUT, + ) + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet-ocr2/test/commands/proxy.test.ts b/packages-ts/starknet-gauntlet-ocr2/test/commands/proxy.test.ts new file mode 100644 index 0000000..539de78 --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/test/commands/proxy.test.ts @@ -0,0 +1,125 @@ +import deployOCR2Command from '../../src/commands/ocr2/deploy' +import deployACCommand from '../../src/commands/accessController/deploy' +import deployProxyCommand from '../../src/commands/proxy/deploy' +import proposeAggregatorCommand from '../../src/commands/proxy/proposeAggregator' +import confirmAggregatorCommand from '../../src/commands/proxy/confirmAggregator' +import { + registerExecuteCommand, + TIMEOUT, + startNetwork, + IntegratedDevnet, + devnetAccount0Address, +} from '@pluginv3.0/starknet-gauntlet/test/utils' + +let account = devnetAccount0Address + +describe('Proxy Contract', () => { + let network: IntegratedDevnet + let contractAddress: string + let accessController: string + let proxy: string + + beforeAll(async () => { + network = await startNetwork() + }, TIMEOUT) + + afterAll(async () => { + network.stop() + }) + + it( + 'Deploy AC', + async () => { + // TODO: owner can't be 0 anymore + const command = await registerExecuteCommand(deployACCommand).create({}, []) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + accessController = report.responses[0].contract + }, + TIMEOUT, + ) + + it( + 'Deploy OCR2', + async () => { + const command = await registerExecuteCommand(deployOCR2Command).create( + { + input: { + owner: account, + maxAnswer: 10000, + minAnswer: 1, + decimals: 18, + description: 'Test Feed', + billingAccessController: accessController, + linkToken: '0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603730', + }, + }, + [], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + contractAddress = report.responses[0].contract + }, + TIMEOUT, + ) + + it( + 'Deploy Proxy', + async () => { + const command = await registerExecuteCommand(deployProxyCommand).create( + { + input: { + owner: account, + address: contractAddress, + }, + }, + [], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + proxy = report.responses[0].contract + }, + TIMEOUT, + ) + + it( + 'Propose Proxy Aggregator', + async () => { + const command = await registerExecuteCommand(proposeAggregatorCommand).create( + { + input: { + owner: account, + address: contractAddress, + }, + }, + [proxy], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + }, + TIMEOUT, + ) + + it( + 'Confirm Proxy Aggregator', + async () => { + const command = await registerExecuteCommand(confirmAggregatorCommand).create( + { + input: { + owner: account, + address: contractAddress, + }, + }, + [proxy], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + }, + TIMEOUT, + ) +}) diff --git a/packages-ts/starknet-gauntlet-ocr2/test/lib/encoding.test.ts b/packages-ts/starknet-gauntlet-ocr2/test/lib/encoding.test.ts new file mode 100644 index 0000000..dac738a --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/test/lib/encoding.test.ts @@ -0,0 +1,25 @@ +import { bytesToFelts, bytesToFeltsDeprecated, feltsToBytes } from '../../src/lib/encoding' + +function createUint8Array(len: number): Uint8Array { + const ret: Uint8Array = new Uint8Array(len) + for (let i = 1; i <= len; i++) { + ret[i - 1] = i + } + return ret +} + +describe('bytesToFelts', () => { + it('matches the deprecated BN function', async () => { + for (let testLength = 0; testLength < 256; testLength++) { + const testArray = createUint8Array(testLength) + expect(bytesToFelts(testArray)).toEqual(bytesToFeltsDeprecated(testArray)) + } + }) + + it('converts to felts and back successfully', async () => { + for (let testLength = 0; testLength < 256; testLength++) { + const testArray = createUint8Array(testLength) + expect(new Uint8Array(feltsToBytes(bytesToFelts(testArray)))).toEqual(testArray) + } + }) +}) diff --git a/packages-ts/starknet-gauntlet-ocr2/tsconfig.json b/packages-ts/starknet-gauntlet-ocr2/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-ocr2/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-oz/LICENSE b/packages-ts/starknet-gauntlet-oz/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-oz/README.md b/packages-ts/starknet-gauntlet-oz/README.md new file mode 100644 index 0000000..0c71b97 --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/README.md @@ -0,0 +1,23 @@ +# Starknet Gauntlet Commands for the Open Zeppelin Contracts + +## Account + +### Deploy + +```bash +yarn gauntlet account:deploy --network= +``` + +This command will generate a new Keypair and will give the details during the execution. If you already have a Keypair and want to use it as signer on your Account contract, use: + +```bash +yarn gauntlet account:deploy --network= --publicKey= +``` + +After the execution is finished, you will want to include the account contract and the private key to your `.env` configuration file. + +```bash +# .env +PRIVATE_KEY=0x... +ACCOUNT=0x... +``` diff --git a/packages-ts/starknet-gauntlet-oz/package.json b/packages-ts/starknet-gauntlet-oz/package.json new file mode 100644 index 0000000..2f0b74e --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/package.json @@ -0,0 +1,32 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-oz", + "version": "0.0.1", + "description": "Starknet Gauntlet Open Zeppelin Contracts", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-oz --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0-dev/starkgate-open-zeppelin": "^0.5.0", + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/starknet-gauntlet": "*" + } +} diff --git a/packages-ts/starknet-gauntlet-oz/src/commands/account/deploy.ts b/packages-ts/starknet-gauntlet-oz/src/commands/account/deploy.ts new file mode 100644 index 0000000..2fa1bf8 --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/src/commands/account/deploy.ts @@ -0,0 +1,91 @@ +import { + AfterExecute, + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { ec } from 'starknet' +import { CATEGORIES } from '../../lib/categories' +import { accountContractLoader, CONTRACT_LIST, equalAddress } from '../../lib/contracts' + +type UserInput = { + publicKey: string + privateKey?: string + salt?: number +} + +type ContractInput = [publicKey: string] + +const makeUserInput = async (flags, _, env): Promise => { + if (flags.input) return flags.input as UserInput + + // If public key is not provided, generate a new address + const keypair = ec.starkCurve.utils.randomPrivateKey() + const generatedPK = '0x' + Buffer.from(keypair).toString('hex') + const pubkey = flags.publicKey || env.publicKey || ec.starkCurve.getStarkKey(keypair) + const salt: number = flags.salt ? +flags.salt : undefined + return { + publicKey: pubkey, + privateKey: (!flags.publicKey || !env.account) && generatedPK, + salt, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.publicKey] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info(`About to deploy an Account Contract with: + public key: ${input.contract[0]} + salt: ${input.user.salt || 'randomly generated'}`) + if (input.user.privateKey) { + await deps.prompt(`The generated private key will be shown next, continue?`) + deps.logger.line() + + deps.logger.info(`To sign future transactions, store the Private Key`) + deps.logger.info(`PRIVATE_KEY: ${input.user.privateKey}`) + + deps.logger.line() + } +} + +const afterExecute: AfterExecute = (context, input, deps) => async ( + result, +) => { + const contract = result.responses[0].tx.address + contract + ? deps.logger.success(`Account contract located at ${contract}`) + : deps.logger.error('Account contract deployment failed') + + return { + publicKey: input.user.publicKey, + privateKey: input.user.privateKey, + } +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.ACCOUNT, + category: CATEGORIES.ACCOUNT, + action: 'deploy', + ux: { + description: 'Deploys an OpenZeppelin Account contract', + examples: [ + `${CATEGORIES.ACCOUNT}:deploy --network= --address=
`, + ], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: accountContractLoader, + hooks: { + beforeExecute, + afterExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-oz/src/commands/account/index.ts b/packages-ts/starknet-gauntlet-oz/src/commands/account/index.ts new file mode 100644 index 0000000..2a9000a --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/src/commands/account/index.ts @@ -0,0 +1,2 @@ +import Deploy from './deploy' +export default [Deploy] diff --git a/packages-ts/starknet-gauntlet-oz/src/commands/index.ts b/packages-ts/starknet-gauntlet-oz/src/commands/index.ts new file mode 100644 index 0000000..4924c4a --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/src/commands/index.ts @@ -0,0 +1,3 @@ +import Account from './account' + +export default [...Account] diff --git a/packages-ts/starknet-gauntlet-oz/src/index.ts b/packages-ts/starknet-gauntlet-oz/src/index.ts new file mode 100644 index 0000000..66ccd58 --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/src/index.ts @@ -0,0 +1,3 @@ +import Commands from './commands' + +export { Commands } diff --git a/packages-ts/starknet-gauntlet-oz/src/lib/categories.ts b/packages-ts/starknet-gauntlet-oz/src/lib/categories.ts new file mode 100644 index 0000000..db5f263 --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/src/lib/categories.ts @@ -0,0 +1,3 @@ +export const CATEGORIES = { + ACCOUNT: 'account', +} diff --git a/packages-ts/starknet-gauntlet-oz/src/lib/contracts.ts b/packages-ts/starknet-gauntlet-oz/src/lib/contracts.ts new file mode 100644 index 0000000..6565420 --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/src/lib/contracts.ts @@ -0,0 +1,32 @@ +import fs from 'fs' +import { CompiledContract, json, hash } from 'starknet' +import BN from 'bn.js' + +export enum CONTRACT_LIST { + ACCOUNT = 'Account', +} + +export const loadContract = (name: CONTRACT_LIST): CompiledContract => { + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../node_modules/@pluginv3.0-dev/starkgate-open-zeppelin/artifacts/0.5.0/${name}.cairo/${name}.json`, + ) + .toString('ascii'), + ) +} + +export const accountContractLoader = () => loadContract(CONTRACT_LIST.ACCOUNT) + +// use bignumber libraries to assert addresses are equal +// handles prepending 0s +export const equalAddress = (addr0: string, addr1: string): boolean => { + let a0 = new BN(removePrefix(addr0), 16) + let a1 = new BN(removePrefix(addr1), 16) + + return a0.cmp(a1) == 0 +} + +const removePrefix = (addr: string): string => { + return addr.replace(/^(0x)/, '') +} diff --git a/packages-ts/starknet-gauntlet-oz/test/commands/account.test.ts b/packages-ts/starknet-gauntlet-oz/test/commands/account.test.ts new file mode 100644 index 0000000..81a6855 --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/test/commands/account.test.ts @@ -0,0 +1,44 @@ +import { makeProvider } from '@pluginv3.0/starknet-gauntlet' +import deployCommand from '../../src/commands/account/deploy' +import { + registerExecuteCommand, + TIMEOUT, + LOCAL_URL, + startNetwork, + IntegratedDevnet, +} from '@pluginv3.0/starknet-gauntlet/test/utils' +import { loadContract, CONTRACT_LIST, equalAddress } from '../../src/lib/contracts' +import { Contract } from 'starknet' + +describe('OZ Account Contract', () => { + let network: IntegratedDevnet + let publicKey: string + let contractAddress: string + + beforeAll(async () => { + network = await startNetwork() + }, 15000) + + it( + 'Deployment', + async () => { + const command = await registerExecuteCommand(deployCommand).create({}, []) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + contractAddress = report.responses[0].contract + publicKey = report.data.publicKey + + const oz = loadContract(CONTRACT_LIST.ACCOUNT) + const ozContract = new Contract(oz.abi, contractAddress, makeProvider(LOCAL_URL).provider) + const { publicKey: onChainPubKey } = await ozContract.getPublicKey() + expect(onChainPubKey).toEqual(BigInt(publicKey)) + }, + TIMEOUT, + ) + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet-oz/tsconfig.json b/packages-ts/starknet-gauntlet-oz/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-oz/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet-token/LICENSE b/packages-ts/starknet-gauntlet-token/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet-token/README.md b/packages-ts/starknet-gauntlet-token/README.md new file mode 100644 index 0000000..12383b9 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/README.md @@ -0,0 +1,31 @@ +# Gauntlet Starknet Commands for PLI Token + +## Token + +### Deploy + +The contract is pre-configured to be the PLI token contract. + +```bash +yarn gauntlet token:deploy --network= --owner= +``` + +IMPORTANT: For the token contract to be used in L1<>L2 bridging the `owner` must be the L2 Bridge address. + +### Mint + +```bash +yarn gauntlet token:mint --network= --recipient= --amount= +``` + +### Transfer + +```bash +yarn gauntlet token:transfer --network= --recipient= --amount= +``` + +### Check balance + +```bash +yarn gauntlet token:balance_of --network= --address= +``` diff --git a/packages-ts/starknet-gauntlet-token/package.json b/packages-ts/starknet-gauntlet-token/package.json new file mode 100644 index 0000000..ac48352 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/package.json @@ -0,0 +1,34 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet-token", + "version": "0.0.1", + "description": "Gauntlet Starknet Starkgate contracts", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet-token --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/evm-gauntlet": "^0.4.0", + "@pluginv3.0/gauntlet-core": "0.3.1", + "@pluginv3.0/starknet-gauntlet": "*", + "@pluginv3.0/starknet-gauntlet-oz": "*", + "ethers": "^5.6.9" + } +} diff --git a/packages-ts/starknet-gauntlet-token/src/commands/index.ts b/packages-ts/starknet-gauntlet-token/src/commands/index.ts new file mode 100644 index 0000000..a42b7c6 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/commands/index.ts @@ -0,0 +1,5 @@ +import Token from './token' +import Inspection from './inspection' + +export const L2Commands = [...Token] +export const InspectionCommands = [...Inspection] diff --git a/packages-ts/starknet-gauntlet-token/src/commands/inspection/balanceOf.ts b/packages-ts/starknet-gauntlet-token/src/commands/inspection/balanceOf.ts new file mode 100644 index 0000000..3ab01af --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/commands/inspection/balanceOf.ts @@ -0,0 +1,71 @@ +import { + InspectCommandConfig, + IStarknetProvider, + makeInspectionCommand, + InspectUserInput, + isValidAddress, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { tokenContractLoader } from '../../lib/contracts' +import { uint256 } from 'starknet' + +type UserInput = { + address: string +} + +type ContractInput = string + +type QueryResult = { + balance: string +} + +const makeUserInput = async (flags, args): Promise> => { + if (flags.input) return flags.input as InspectUserInput + + return { + input: { + address: flags.address, + }, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + if (!isValidAddress(input.address)) throw new Error(`Invalid account address: ${input.address}`) + return [input.address] +} + +const makeComparisionData = (provider: IStarknetProvider) => async ( + results: any[], + input: null, + contractAddress: string, +): Promise<{ + toCompare: null + result: QueryResult +}> => { + const [queryRes] = results + const { balance } = queryRes + + return { + toCompare: null, + result: { + balance: uint256.uint256ToBN(balance).toString(), + }, + } +} + +const commandConfig: InspectCommandConfig = { + ux: { + category: CATEGORIES.TOKEN, + function: 'balance_of', + examples: [ + `${CATEGORIES.TOKEN}:balance_of --network= --address= `, + ], + }, + queries: ['balanceOf'], + makeUserInput, + makeContractInput, + makeComparisionData, + loadContract: tokenContractLoader, +} + +export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-token/src/commands/inspection/index.ts b/packages-ts/starknet-gauntlet-token/src/commands/inspection/index.ts new file mode 100644 index 0000000..1d2cde3 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/commands/inspection/index.ts @@ -0,0 +1,3 @@ +import BalanceOf from './balanceOf' + +export default [BalanceOf] diff --git a/packages-ts/starknet-gauntlet-token/src/commands/token/deploy.ts b/packages-ts/starknet-gauntlet-token/src/commands/token/deploy.ts new file mode 100644 index 0000000..fc90893 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/commands/token/deploy.ts @@ -0,0 +1,62 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + ExecutionContext, + makeExecuteCommand, +} from '@pluginv3.0/starknet-gauntlet' +import { CATEGORIES } from '../../lib/categories' +import { tokenContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + owner?: string +} + +type ContractInput = [owner: string] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + return { + owner: flags.owner, + } +} + +const makeContractInput = async ( + input: UserInput, + context: ExecutionContext, +): Promise => { + const defaultWallet = context.wallet.getAccountAddress() + return [input.owner || defaultWallet] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info(`About to deploy the PLI Token Contract with the following details: + ${input.contract} + `) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.TOKEN, + category: CATEGORIES.TOKEN, + action: 'deploy', + ux: { + description: 'Deploys the PLI Token contract', + examples: [ + `${CATEGORIES.TOKEN}:deploy --network=`, + `${CATEGORIES.TOKEN}:deploy --network= --owner=`, + ], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: tokenContractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-token/src/commands/token/index.ts b/packages-ts/starknet-gauntlet-token/src/commands/token/index.ts new file mode 100644 index 0000000..96b3b59 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/commands/token/index.ts @@ -0,0 +1,5 @@ +import Deploy from './deploy' +import Mint from './mint' +import Transfer from './transfer' + +export default [Deploy, Mint, Transfer] diff --git a/packages-ts/starknet-gauntlet-token/src/commands/token/mint.ts b/packages-ts/starknet-gauntlet-token/src/commands/token/mint.ts new file mode 100644 index 0000000..be07a22 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/commands/token/mint.ts @@ -0,0 +1,72 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, + isValidAddress, +} from '@pluginv3.0/starknet-gauntlet' +import { uint256 } from 'starknet' +import { CATEGORIES } from '../../lib/categories' +import { tokenContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + recipient: string + amount: string +} + +type ContractInput = [recipient: string, amount: any] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + return { + recipient: flags.recipient, + amount: flags.amount, + } +} + +const validateRecipient = async (input) => { + if (!isValidAddress(input.recipient)) + throw new Error(`Invalid recipient address: ${input.recipient}`) + return true +} + +const validateAmount = async (input) => { + if (isNaN(Number(input.amount))) throw new Error(`Invalid amount: ${input.amount}`) + return true +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.recipient, uint256.bnToUint256(input.amount)] +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info(`About to mint an ERC20 Token Contract with the following details: + ${input.contract} + `) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.TOKEN, + category: CATEGORIES.TOKEN, + action: 'mint', + ux: { + description: 'Mints a set amount of tokens from contract to recipient', + examples: [ + `${CATEGORIES.TOKEN}:mint --network= --recipient= --amount= `, + ], + }, + internalFunction: 'permissionedMint', + makeUserInput, + makeContractInput, + validations: [validateRecipient, validateAmount], + loadContract: tokenContractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-token/src/commands/token/transfer.ts b/packages-ts/starknet-gauntlet-token/src/commands/token/transfer.ts new file mode 100644 index 0000000..2060d68 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/commands/token/transfer.ts @@ -0,0 +1,69 @@ +import { + BeforeExecute, + ExecuteCommandConfig, + makeExecuteCommand, + isValidAddress, +} from '@pluginv3.0/starknet-gauntlet' +import { uint256 } from 'starknet' +import { CATEGORIES } from '../../lib/categories' +import { tokenContractLoader, CONTRACT_LIST } from '../../lib/contracts' + +type UserInput = { + recipient: string + amount: string +} + +type ContractInput = [recipient: string, amount: any] + +const makeUserInput = async (flags, args): Promise => { + if (flags.input) return flags.input as UserInput + + return { + recipient: flags.recipient, + amount: flags.amount, + } +} + +const makeContractInput = async (input: UserInput): Promise => { + return [input.recipient, uint256.bnToUint256(input.amount)] +} + +const validateRecipient = async (input) => { + if (!isValidAddress(input.recipient)) + throw new Error(`Invalid recipient address: ${input.recipient}`) + return true +} + +const validateAmount = async (input) => { + if (isNaN(Number(input.amount))) throw new Error(`Invalid amount: ${input.amount}`) + return true +} + +const beforeExecute: BeforeExecute = ( + context, + input, + deps, +) => async () => { + deps.logger.info(`About to tranfer ${input.user.amount} ERC20 tokens to ${input.user.recipient}`) +} + +const commandConfig: ExecuteCommandConfig = { + contractId: CONTRACT_LIST.TOKEN, + category: CATEGORIES.TOKEN, + action: 'transfer', + ux: { + description: 'Transfers a set amount of tokens from caller to recipient', + examples: [ + `${CATEGORIES.TOKEN}:transfer --network= --recipient= --amount= `, + ], + }, + makeUserInput, + makeContractInput, + validations: [validateRecipient, validateAmount], + loadContract: tokenContractLoader, + hooks: { + beforeExecute, + }, +} + +export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-token/src/index.ts b/packages-ts/starknet-gauntlet-token/src/index.ts new file mode 100644 index 0000000..680f5a6 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/index.ts @@ -0,0 +1,3 @@ +import { L2Commands, InspectionCommands } from './commands' + +export { L2Commands, InspectionCommands } diff --git a/packages-ts/starknet-gauntlet-token/src/lib/categories.ts b/packages-ts/starknet-gauntlet-token/src/lib/categories.ts new file mode 100644 index 0000000..c4061c4 --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/lib/categories.ts @@ -0,0 +1,5 @@ +import { CONTRACT_LIST } from './contracts' + +export const CATEGORIES = { + TOKEN: CONTRACT_LIST.TOKEN, +} diff --git a/packages-ts/starknet-gauntlet-token/src/lib/contracts.ts b/packages-ts/starknet-gauntlet-token/src/lib/contracts.ts new file mode 100644 index 0000000..2a83fcf --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/src/lib/contracts.ts @@ -0,0 +1,37 @@ +import fs from 'fs' +import { CompiledContract, json } from 'starknet' +import { ContractFactory } from 'ethers' + +export enum CONTRACT_LIST { + TOKEN = 'token', +} + +// todo: remove when stable contract artifacts release available +const CONTRACT_NAME_TO_ARTIFACT_NAME = { + [CONTRACT_LIST.TOKEN]: 'link_token', +} + +export const loadTokenContract = (name: CONTRACT_LIST): CompiledContract => { + const artifactName = CONTRACT_NAME_TO_ARTIFACT_NAME[name] + return json.parse( + fs + .readFileSync( + `${__dirname}/../../../../contracts/starknet-artifacts/src/plugin/cairo/token/starkgate/presets/${artifactName}.cairo/${artifactName}.json`, + ) + .toString('ascii'), + ) +} + +export const loadOZContract = (name: CONTRACT_LIST): any => { + const artifactName = CONTRACT_NAME_TO_ARTIFACT_NAME[name] + const abi = json.parse( + fs + .readFileSync( + `${__dirname}/../../../../node_modules/@openzeppelin/contracts/build/contracts/${artifactName}.json`, + ) + .toString('ascii'), + ) + return new ContractFactory(abi?.abi, abi?.bytecode) +} + +export const tokenContractLoader = () => loadTokenContract(CONTRACT_LIST.TOKEN) diff --git a/packages-ts/starknet-gauntlet-token/test/commands/token.test.ts b/packages-ts/starknet-gauntlet-token/test/commands/token.test.ts new file mode 100644 index 0000000..53f12cc --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/test/commands/token.test.ts @@ -0,0 +1,135 @@ +import deployOZCommand from '@pluginv3.0/starknet-gauntlet-oz/src/commands/account/deploy' +import deployTokenCommand from '../../src/commands/token/deploy' +import mintTokensCommand from '../../src/commands/token/mint' +import transferTokensCommand from '../../src/commands/token/transfer' +import balanceOfCommand from '../../src/commands/inspection/balanceOf' + +import { + registerExecuteCommand, + registerInspectCommand, + TIMEOUT, + startNetwork, + IntegratedDevnet, +} from '@pluginv3.0/starknet-gauntlet/test/utils' + +describe('Token Contract', () => { + let network: IntegratedDevnet + + let defaultAccount: string + let defaultPk: string + let defaultBalance: number + + let ozAccount: string + let ozPk: string + let ozBalance: number + + let tokenContractAddress: string + + beforeAll(async () => { + network = await startNetwork({ seed: 0 }) + + // account #0 with seed 0 + defaultAccount = '0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a' + defaultPk = '0xe3e70682c2094cac629f6fbed82c07cd' + defaultBalance = 0 + }, 15000) + + it( + 'Deploy OZ Account', + async () => { + const command = await registerExecuteCommand(deployOZCommand).create({}, []) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + ozAccount = report.responses[0].contract + ozPk = report.data.privateKey + ozBalance = 0 + }, + TIMEOUT, + ) + + it( + 'Deploy Token', + async () => { + const command = await registerExecuteCommand(deployTokenCommand).create( + { + account: defaultAccount, + pk: defaultPk, + link: true, + }, + [], + ) + + const report = await command.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + tokenContractAddress = report.responses[0].contract + }, + TIMEOUT, + ) + + it( + 'Mint tokens for Default account', + async () => { + const amount = 10000000 + + const executeCommand = await registerExecuteCommand(mintTokensCommand).create( + { + account: defaultAccount, + pk: defaultPk, + recipient: defaultAccount, + amount, + }, + [tokenContractAddress], + ) + let report = await executeCommand.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + defaultBalance = amount + + const inspectCommand = await registerInspectCommand(balanceOfCommand).create( + { + address: defaultAccount, + }, + [tokenContractAddress], + ) + report = await inspectCommand.execute() + expect(report.data?.data?.balance).toEqual(defaultBalance.toString()) + }, + TIMEOUT, + ) + + it( + 'Transfer tokens to OZ account', + async () => { + const amount = 50 + + const executeCommand = await registerExecuteCommand(transferTokensCommand).create( + { + account: defaultAccount, + pk: defaultPk, + recipient: ozAccount, + amount, + }, + [tokenContractAddress], + ) + let report = await executeCommand.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + ozBalance = amount + + const inspectCommand = await registerInspectCommand(balanceOfCommand).create( + { + address: ozAccount, + }, + [tokenContractAddress], + ) + report = await inspectCommand.execute() + expect(report.data?.data?.balance).toEqual(ozBalance.toString()) + }, + TIMEOUT, + ) + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet-token/tsconfig.json b/packages-ts/starknet-gauntlet-token/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet-token/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet-gauntlet/LICENSE b/packages-ts/starknet-gauntlet/LICENSE new file mode 100644 index 0000000..fad7f7c --- /dev/null +++ b/packages-ts/starknet-gauntlet/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 SmartContract Plugin, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages-ts/starknet-gauntlet/README.md b/packages-ts/starknet-gauntlet/README.md new file mode 100644 index 0000000..715073e --- /dev/null +++ b/packages-ts/starknet-gauntlet/README.md @@ -0,0 +1 @@ +# Starknet Gauntlet diff --git a/packages-ts/starknet-gauntlet/package.json b/packages-ts/starknet-gauntlet/package.json new file mode 100644 index 0000000..fdef001 --- /dev/null +++ b/packages-ts/starknet-gauntlet/package.json @@ -0,0 +1,32 @@ +{ + "name": "@pluginv3.0/starknet-gauntlet", + "version": "0.0.1", + "description": "Starknet Gauntlet", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "gauntlet": "ts-node ./src/index.ts", + "lint": "tsc", + "test": "SKIP_PROMPTS=true jest --runInBand --config ../../jest.config.ts --selectProjects starknet-gauntlet --passWithNoTests", + "test:coverage": "yarn test --collectCoverage", + "test:ci": "yarn test --ci", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "dependencies": { + "@pluginv3.0/evm-gauntlet": "^0.0.2", + "@pluginv3.0/gauntlet-core": "0.3.1", + "cross-fetch": "^3.1.5" + } +} diff --git a/packages-ts/starknet-gauntlet/src/commands/base/command.ts b/packages-ts/starknet-gauntlet/src/commands/base/command.ts new file mode 100644 index 0000000..5dec706 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/commands/base/command.ts @@ -0,0 +1,28 @@ +export interface CommandCtor { + id: string + category: string + examples: string[] + create: (flags, args) => Promise +} + +export type Validation = ( + input: UI, + executionContext: ExecutionContext, +) => Promise + +export interface CommandUX { + category: string + function: string + suffixes?: string[] + examples: string[] +} + +export interface Input { + user: UI + contract: CI | CI[] +} + +export const makeCommandId = (category: string, fn: string, suffixes?: string[]): string => { + const base = `${category}:${fn}` + return suffixes?.length > 0 ? `${base}:${suffixes.join(':')}` : base +} diff --git a/packages-ts/starknet-gauntlet/src/commands/base/executeCommand.ts b/packages-ts/starknet-gauntlet/src/commands/base/executeCommand.ts new file mode 100644 index 0000000..d057d90 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/commands/base/executeCommand.ts @@ -0,0 +1,237 @@ +import { Result, WriteCommand, BaseConfig } from '@pluginv3.0/gauntlet-core' +import { CompiledContract, Contract, Call } from 'starknet' +import { CommandCtor } from '.' +import { Dependencies, Env } from '../../dependencies' +import { IStarknetProvider, wrapResponse } from '../../provider' +import { TransactionResponse } from '../../transaction' +import { IStarknetWallet } from '../../wallet' +import { makeCommandId, Validation, Input } from './command' + +export interface ExecutionContext { + id: string + contractAddress: string + wallet: IStarknetWallet + provider: IStarknetProvider + flags: any + contract: Contract +} + +export type BeforeExecute = ( + context: ExecutionContext, + input: Input, + deps: Pick, +) => () => Promise + +export type AfterExecute = ( + context: ExecutionContext, + input: Input, + deps: Pick, +) => (result: Result) => Promise + +export interface ExecuteCommandConfig extends BaseConfig { + hooks?: { + beforeExecute?: BeforeExecute + afterExecute?: AfterExecute + } + internalFunction?: string + makeContractInput: (userInput: UI, context: ExecutionContext) => Promise + loadContract: () => CompiledContract +} + +export interface ExecuteCommandInstance { + wallet: IStarknetWallet + provider: IStarknetProvider + contractAddress: string + account: string + executionContext: ExecutionContext + contract: CompiledContract + + input: Input + + makeMessage: () => Promise + execute: () => Promise> + simulate?: () => boolean + + beforeExecute: () => Promise + afterExecute: (response: Result) => Promise +} + +export const makeExecuteCommand = (config: ExecuteCommandConfig) => ( + deps: Dependencies, +) => { + const command: CommandCtor> = class ExecuteCommand + extends WriteCommand + implements ExecuteCommandInstance { + wallet: IStarknetWallet + provider: IStarknetProvider + contractAddress: string + account: string + executionContext: ExecutionContext + contract: CompiledContract + + input: Input + + beforeExecute: () => Promise + afterExecute: (response: Result) => Promise + + static id = makeCommandId(config.category, config.action, config.suffixes) + static category = config.category + static examples = config.ux.examples + + static create = async (flags, args) => { + const c = new ExecuteCommand(flags, args) + + const env = deps.makeEnv(flags) + + c.wallet = await deps.makeWallet(env) + c.provider = deps.makeProvider(env.providerUrl, c.wallet) + c.contractAddress = args[0] + c.account = env.account + c.contract = config.loadContract() + + c.executionContext = { + provider: c.provider, + wallet: c.wallet, + id: makeCommandId(config.category, config.action, config.suffixes), + contractAddress: c.contractAddress, + flags: flags, + contract: new Contract(c.contract.abi, c.contractAddress ?? '', c.provider.provider), + } + + c.input = await c.buildCommandInput(flags, args, env) + + c.beforeExecute = config.hooks?.beforeExecute + ? config.hooks.beforeExecute(c.executionContext, c.input, { + logger: deps.logger, + prompt: deps.prompt, + }) + : c.defaultBeforeExecute(c.executionContext, c.input) + + c.afterExecute = config.hooks?.afterExecute + ? config.hooks.afterExecute(c.executionContext, c.input, { + logger: deps.logger, + prompt: deps.prompt, + }) + : c.defaultAfterExecute() + + return c + } + + runValidations = async (validations: Validation[], input: UI) => { + const result = await Promise.all( + validations.map((validation) => validation(input, this.executionContext)), + ) + return result + } + + defaultBeforeExecute = ( + context: ExecutionContext, + input: Input, + ) => async () => { + deps.logger.loading(`Executing ${context.id} from contract ${context.contractAddress}`) + deps.logger.log('Contract Input Params:', input.contract) + } + + defaultAfterExecute = () => async (response: Result): Promise => { + deps.logger.info(`Execution finished at transaction: ${response.responses[0].tx.hash}`) + } + + buildCommandInput = async (flags, args, env): Promise> => { + const userInput = await config.makeUserInput(flags, args, env) + + // Validation + if (config.validations.length > 0) { + await this.runValidations(config.validations, userInput) + } + + const contractInput = await config.makeContractInput(userInput, this.executionContext) + + return { + user: userInput, + contract: contractInput, + } + } + + simulate = () => true + + // TODO: This will be required for Multisig + makeMessage = async (): Promise => { + const contract = new Contract(this.contract.abi, this.contractAddress, this.provider.provider) + const invocation = contract.populate( + config.internalFunction || config.action, + this.input.contract as any, + ) + + return [invocation] + } + + deployContract = async (): Promise => { + deps.logger.info(`Deploying contract ${config.category}`) + await deps.prompt('Continue?') + deps.logger.loading(`Sending transaction...`) + + const tx = await this.provider.deployContract( + this.contract, + this.input.contract, + false, + this.input?.user?.['salt'], + ) + if (tx.hash === undefined) { + deps.logger.error(`No tx hash found:\n${JSON.stringify(tx, null, 2)}`) + return tx + } + + deps.logger.loading(`Waiting for tx confirmation at ${tx.hash}...`) + const response = await tx.wait() + if (!response.success) { + deps.logger.error(`Contract was not deployed: ${tx.errorMessage}`) + return tx + } + deps.logger.success(`Contract deployed on ${tx.hash} with address ${tx.address}`) + return tx + } + + executeWithSigner = async (): Promise => { + const pubkey = await this.wallet.getPublicKey() + deps.logger.info(`Using wallet: ${pubkey}`) + const messages = await this.makeMessage() + await deps.prompt(`Continue?`) + deps.logger.loading(`Signing and sending transaction...`) + const tx = await this.provider.signAndSend(messages) + deps.logger.loading(`Waiting for tx confirmation at ${tx.hash}...`) + const response = await tx.wait() + if (!response.success) { + deps.logger.error(`Tx was not successful: ${tx.errorMessage}`) + return tx + } + deps.logger.success(`Tx executed at ${tx.hash}`) + return tx + } + + execute = async () => { + let tx: TransactionResponse + + await this.beforeExecute() + + if (config.action === 'deploy') { + tx = await this.deployContract() + } else { + tx = await this.executeWithSigner() + } + + let result = { + responses: [ + { + tx, + contract: tx.address, + }, + ], + } + const data = await this.afterExecute(result) + + return !!data ? { ...result, data: { ...data } } : result + } + } + + return command +} diff --git a/packages-ts/starknet-gauntlet/src/commands/base/index.ts b/packages-ts/starknet-gauntlet/src/commands/base/index.ts new file mode 100644 index 0000000..cfccbce --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/commands/base/index.ts @@ -0,0 +1,3 @@ +export * from './command' +export * from './executeCommand' +export * from './inspectionCommand' diff --git a/packages-ts/starknet-gauntlet/src/commands/base/inspectionCommand.ts b/packages-ts/starknet-gauntlet/src/commands/base/inspectionCommand.ts new file mode 100644 index 0000000..6229e20 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/commands/base/inspectionCommand.ts @@ -0,0 +1,156 @@ +import BaseCommand from '@pluginv3.0/gauntlet-core/dist/commands/internal/base' +import { CompiledContract, Contract } from 'starknet' +import { CommandCtor, Input } from '.' +import { InspectionDependencies } from '../../dependencies' +import { IStarknetProvider } from '../../provider' +import { CommandUX, makeCommandId } from './command' + +export interface InspectUserInput { + input: UI + toCompare?: CompareInput +} + +// TODO: Temporary inspection report. +export interface InspectionReport { + data: QueryResult + contract: string + inspection: { + id: string + message: string + resultType: 'success' | 'failed' + }[] +} + +export interface InspectCommandConfig { + ux: CommandUX + // List of query functions to call + queries: string[] + makeUserInput?: (flags: any, args: string[]) => Promise> + /** + * Given the user input, translate to every contract input required for each query + */ + makeContractInput?: (userInput: UI) => Promise + /** + * After doing every query, convert the results into the type we want (QueryResult) and if toCompare is given, match result into it + */ + makeComparisionData: ( + provider: IStarknetProvider, + ) => ( + results: any[], + input: UI, + contractAddress: string, + ) => Promise<{ + toCompare: CompareInput + result: QueryResult + }> + inspect?: ( + expected: InspectUserInput, + data: { + toCompare: CompareInput + result: QueryResult + }, + ) => { + id: string + message: string + resultType: 'success' | 'failed' + }[] + loadContract: () => CompiledContract +} + +export interface InspectCommandInstance { + execute: () => Promise<{ + data: InspectionReport + responses: any[] + }> +} + +export const makeInspectionCommand = ( + config: InspectCommandConfig, +) => (deps: InspectionDependencies) => { + const command: CommandCtor> = class InspectionCommand + extends BaseCommand + implements InspectCommandInstance { + // Props + provider: IStarknetProvider + contractAddress: string + + input: Input, CI> + + contract: CompiledContract + + // UX + static id = makeCommandId(config.ux.category, config.ux.function, config.ux.suffixes) + static category = config.ux.category + static examples = config.ux.examples + + static create = async (flags, args) => { + const c = new InspectionCommand(flags, args) + + const env = deps.makeEnv(flags) + + c.provider = deps.makeProvider(env.providerUrl) + c.contractAddress = args[0] + + c.input = await c.buildCommandInput(flags, args) + c.contract = config.loadContract() + + return c + } + + buildCommandInput = async ( + flags, + args, + ): Promise, CI>> => { + const userInput = config.makeUserInput && (await config.makeUserInput(flags, args)) + const contractInput = + config.makeContractInput && (await config.makeContractInput(userInput.input)) + + return { + user: userInput || { + input: null, + toCompare: null, + }, + contract: contractInput || [], + } + } + + runQueries = async (functions: string[], contractInputs: CI | CI[]): Promise => { + const inputs = Array.isArray(contractInputs) ? contractInputs : [contractInputs] + const contract = new Contract(this.contract.abi, this.contractAddress, this.provider.provider) + const results = await Promise.all( + functions.map((func, i) => { + deps.logger.loading(`Fetching ${func} of contract ${this.contractAddress}...`) + if (!inputs[i]) { + return contract[func]() // workaround undefined argument inputs[i] + } + return contract[func](inputs[i]) + }), + ) + return results + } + + execute = async () => { + const results = await this.runQueries(config.queries, this.input.contract) + const data = await config.makeComparisionData(this.provider)( + results, + this.input.user.input, + this.contractAddress, + ) + const inspectionResults = config.inspect ? config.inspect(this.input.user, data) : [] + + deps.logger.info('Inspection Results:') + deps.logger.log(data.result) + // TODO: Gauntlet core forces us to use Result type for every command. Update to choose the result if using Base Command + return { + data: { + data: data.result, + contract: this.contractAddress, + inspection: inspectionResults, + }, + responses: [], + } + } + } + + return command +} diff --git a/packages-ts/starknet-gauntlet/src/dependencies/index.ts b/packages-ts/starknet-gauntlet/src/dependencies/index.ts new file mode 100644 index 0000000..efb7433 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/dependencies/index.ts @@ -0,0 +1,24 @@ +import { logger, prompt } from '@pluginv3.0/gauntlet-core/dist/utils' +import { IStarknetProvider } from '../provider' +import { IStarknetWallet } from '../wallet' +import { makeProvider } from '@pluginv3.0/evm-gauntlet' + +export interface Env { + providerUrl: string + pk?: string + account?: string + withLedger?: boolean + ledgerPath?: string + multisig?: string + [key: string]: string | boolean // Custom env +} + +export interface Dependencies { + logger: typeof logger + prompt: typeof prompt + makeEnv: (flags: Record) => Env + makeProvider: (url: string, wallet?: IStarknetWallet) => IStarknetProvider + makeWallet: (env: Env) => Promise +} + +export type InspectionDependencies = Omit diff --git a/packages-ts/starknet-gauntlet/src/events/index.ts b/packages-ts/starknet-gauntlet/src/events/index.ts new file mode 100644 index 0000000..88df678 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/events/index.ts @@ -0,0 +1 @@ +export { EventSubscription } from './subscription' diff --git a/packages-ts/starknet-gauntlet/src/events/subscription.ts b/packages-ts/starknet-gauntlet/src/events/subscription.ts new file mode 100644 index 0000000..57ed618 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/events/subscription.ts @@ -0,0 +1,30 @@ +// TODO: Use starknet WS client +type WSClient = any + +// TODO: Adapt to Starknet client +export abstract class EventSubscription { + abstract parseEvent: (event: any) => Event + + private _wsClient: WSClient + + constructor(readonly client: WSClient) { + this._wsClient = client + } + + public start() { + this._wsClient.start() + } + + public destroy() { + this._wsClient.destroy() + } + + public onEvent(contract: string, eventId: string, callback: (event: Event) => void) { + this._wsClient.subscribeTx( + { + [eventId]: contract, + }, + (data) => callback(this.parseEvent(data)), + ) + } +} diff --git a/packages-ts/starknet-gauntlet/src/index.ts b/packages-ts/starknet-gauntlet/src/index.ts new file mode 100644 index 0000000..7f2079d --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/index.ts @@ -0,0 +1,13 @@ +// Node.js 18 + Jest 28 are supposed to support fetch but I can't get it working. +// Copying starknet.js workaround: https://github.com/0xs34n/starknet.js/commit/83be37a9e3328a44abd9583b8167c3cb8d882790 +import fetch from 'cross-fetch' +if (!global.fetch) { + global.fetch = fetch +} + +export * from './commands/base' +export * from './dependencies' +export * from './provider' +export * from './wallet' +export * from './events' +export * from './utils' diff --git a/packages-ts/starknet-gauntlet/src/provider/index.ts b/packages-ts/starknet-gauntlet/src/provider/index.ts new file mode 100644 index 0000000..79ccd69 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/provider/index.ts @@ -0,0 +1,112 @@ +import { TransactionResponse } from '../transaction' +import { + SequencerProvider as StarknetProvider, + DeployContractResponse, + Sequencer, + CompiledContract, + Account, + Call, +} from 'starknet' +import { IStarknetWallet } from '../wallet' + +// TODO: Move to gauntlet-core +interface IProvider

{ + provider: P + send: () => Promise + deployContract: ( + contract: CompiledContract, + input: any, + wait?: boolean, + salt?: number, + ) => Promise + signAndSend: (calls: Call[], wait?: boolean) => Promise +} + +export interface IStarknetProvider extends IProvider {} +export const makeProvider = ( + url: string, + wallet?: IStarknetWallet, +): IProvider => { + return new Provider(url, wallet) +} + +export const wrapResponse = ( + provider: IStarknetProvider, + response: Sequencer.AddTransactionResponse | DeployContractResponse, + address?: string, +): TransactionResponse => { + const txResponse: TransactionResponse = { + hash: response.transaction_hash, + // HACK: Work around the response being either AddTransactionResponse or DeployContractResponse + address: address || (response as any).address || (response as any).contract_address, + wait: async () => { + // Success if does not throw + let success: boolean + try { + await provider.provider.waitForTransaction(response.transaction_hash) + txResponse.status = 'ACCEPTED' + success = true + } catch (e) { + txResponse.status = 'REJECTED' + txResponse.errorMessage = e.message + success = false + } + const status = await provider.provider.getTransactionStatus(response.transaction_hash) + txResponse.tx.code = status.tx_status as any // For some reason, starknet does not consider any other status than "TRANSACTION_RECEIVED" + return { success } + }, + status: 'PENDING', + tx: response, + } + return txResponse +} + +class Provider implements IStarknetProvider { + provider: StarknetProvider + account: Account + + constructor(baseUrl: string, wallet?: IStarknetWallet) { + this.provider = new StarknetProvider({ baseUrl }) + if (wallet) { + this.account = new Account(this.provider, wallet.getAccountAddress(), wallet.signer) + } + } + + setAccount(wallet: IStarknetWallet) { + this.account = new Account(this.provider, wallet.getAccountAddress(), wallet.signer) + } + + send = async () => { + // Use provider to send tx and wrap it in our type + return {} as TransactionResponse + } + + deployContract = async ( + contract: CompiledContract, + input: any = [], + wait = true, + salt = undefined, + ) => { + const tx = await this.account.declareAndDeploy({ + contract, + salt: salt ? '0x' + salt.toString(16) : salt, // convert number to hex or leave undefined + // unique: false, + ...(!!input && input.length > 0 && { constructorCalldata: input }), + }) + + const response = wrapResponse(this, tx.deploy) + + if (!wait) return response + await response.wait() + return response + } + + signAndSend = async (calls: Call[], wait = false) => { + const tx = await this.account.execute(calls) + const response = wrapResponse(this, tx) + if (!wait) return response + + await response.wait() + return response + } +} diff --git a/packages-ts/starknet-gauntlet/src/transaction/index.ts b/packages-ts/starknet-gauntlet/src/transaction/index.ts new file mode 100644 index 0000000..6ead91e --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/transaction/index.ts @@ -0,0 +1,10 @@ +import { Sequencer } from 'starknet' + +export type TransactionResponse = { + hash: string + address?: string + wait: () => Promise<{ success: boolean }> + tx?: Sequencer.AddTransactionResponse + status: 'PENDING' | 'ACCEPTED' | 'REJECTED' + errorMessage?: string +} diff --git a/packages-ts/starknet-gauntlet/src/utils/address.ts b/packages-ts/starknet-gauntlet/src/utils/address.ts new file mode 100644 index 0000000..69ea548 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/utils/address.ts @@ -0,0 +1,10 @@ +import { validateAndParseAddress } from 'starknet' + +// TODO: This is inconsistent. come back here +export const isValidAddress = (address: string): boolean => { + try { + validateAndParseAddress(address) + return !!address // check value is not falsy (undefined, "", etc) + } catch (e) {} + return false +} diff --git a/packages-ts/starknet-gauntlet/src/utils/index.ts b/packages-ts/starknet-gauntlet/src/utils/index.ts new file mode 100644 index 0000000..6f5a556 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/utils/index.ts @@ -0,0 +1 @@ +export * from './address' diff --git a/packages-ts/starknet-gauntlet/src/wallet/defaultWallet.ts b/packages-ts/starknet-gauntlet/src/wallet/defaultWallet.ts new file mode 100644 index 0000000..0ac4a47 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/wallet/defaultWallet.ts @@ -0,0 +1,24 @@ +import { Signer } from 'starknet' +import { IStarknetWallet } from './' +import { Env } from '../dependencies' + +export class Wallet implements IStarknetWallet { + signer: Signer + account: string + + private constructor(keypair: string, account?: string) { + this.signer = new Signer(keypair) + this.account = account + } + + static create = (pKey: string, account?: string) => { + return new Wallet(pKey, account) + } + + getPublicKey = async () => await this.signer.getPubKey() + getAccountAddress = () => this.account +} + +export const makeWallet = async (env: Env): Promise => { + return Wallet.create(env.pk, env.account) +} diff --git a/packages-ts/starknet-gauntlet/src/wallet/index.ts b/packages-ts/starknet-gauntlet/src/wallet/index.ts new file mode 100644 index 0000000..f728b77 --- /dev/null +++ b/packages-ts/starknet-gauntlet/src/wallet/index.ts @@ -0,0 +1,13 @@ +import { SignerInterface } from 'starknet' +import { makeWallet } from './defaultWallet' + +export interface IWallet { + signer: W + getPublicKey: () => Promise +} + +export interface IStarknetWallet extends IWallet { + getAccountAddress: () => string +} + +export { makeWallet } diff --git a/packages-ts/starknet-gauntlet/test/__mocks__/example.json b/packages-ts/starknet-gauntlet/test/__mocks__/example.json new file mode 100644 index 0000000..cf82dc9 --- /dev/null +++ b/packages-ts/starknet-gauntlet/test/__mocks__/example.json @@ -0,0 +1,7501 @@ +{ + "abi": [ + { + "inputs": [ + { + "name": "amount", + "type": "felt" + } + ], + "name": "increase_balance", + "outputs": [], + "type": "function" + }, + { + "inputs": [], + "name": "get_balance", + "outputs": [ + { + "name": "res", + "type": "felt" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "entry_points_by_type": { + "CONSTRUCTOR": [], + "EXTERNAL": [ + { + "offset": "0x3a", + "selector": "0x362398bec32bc0ebb411203221a35a0301193a96f317ebe5e40be9f60d15320" + }, + { + "offset": "0x5b", + "selector": "0x39e11d48192e4333233c7eb19d10ad67c362bb28580c604d67884c85da39695" + } + ], + "L1_HANDLER": [] + }, + "program": { + "attributes": [], + "builtins": [ + "pedersen", + "range_check" + ], + "data": [ + "0x480680017fff8000", + "0x53746f7261676552656164", + "0x400280007ffc7fff", + "0x400380017ffc7ffd", + "0x482680017ffc8000", + "0x3", + "0x480280027ffc8000", + "0x208b7fff7fff7ffe", + "0x480680017fff8000", + "0x53746f726167655772697465", + "0x400280007ffb7fff", + "0x400380017ffb7ffc", + "0x400380027ffb7ffd", + "0x482680017ffb8000", + "0x3", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x480680017fff8000", + "0x206f38f7e4f15e87567361213c28f235cccdaa1d7fd34c9db1dfe9489c6a091", + "0x208b7fff7fff7ffe", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa", + "0x480a7ffb7fff8000", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe6", + "0x48127ffe7fff8000", + "0x48127ff57fff8000", + "0x48127ff57fff8000", + "0x48127ffc7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffed", + "0x480a7ffa7fff8000", + "0x48127ffe7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe0", + "0x48127ff67fff8000", + "0x48127ff67fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffa7fff8000", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffe5", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48287ffd7ffc8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffec", + "0x208b7fff7fff7ffe", + "0x482680017ffd8000", + "0x1", + "0x402a7ffd7ffc7fff", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x480280007ffd8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x40780017fff7fff", + "0x1", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x48127ffc7fff8000", + "0x480680017fff8000", + "0x0", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe", + "0x480a7ffb7fff8000", + "0x480a7ffc7fff8000", + "0x480a7ffd7fff8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffc7", + "0x208b7fff7fff7ffe", + "0x40780017fff7fff", + "0x1", + "0x4003800080007ffc", + "0x4826800180008000", + "0x1", + "0x480a7ffd7fff8000", + "0x4828800080007ffe", + "0x480a80007fff8000", + "0x208b7fff7fff7ffe", + "0x402b7ffd7ffc7ffd", + "0x480280007ffb8000", + "0x480280017ffb8000", + "0x480280027ffb8000", + "0x1104800180018000", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffffffffee", + "0x48127ffe7fff8000", + "0x1104800180018000", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff1", + "0x48127ff47fff8000", + "0x48127ff47fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x48127ffb7fff8000", + "0x208b7fff7fff7ffe" + ], + "debug_info": { + "file_contents": { + "autogen/starknet/arg_processor/1b562308a65653425ce06491fa4b4539466f3251a07e73e099d0afe86a48900e.cairo": "assert [cast(fp + (-4), felt*)] = __calldata_actual_size\n", + "autogen/starknet/arg_processor/5e1cc73f0b484f90bb02da164d88332b40c6f698801aa4d3c603dab22157e902.cairo": "let __calldata_actual_size = __calldata_ptr - cast([cast(fp + (-3), felt**)], felt*)\n", + "autogen/starknet/arg_processor/7a16feca69d1dc1343a49177e1e57103319136de3f2c6fabefae170177a1305e.cairo": "let __calldata_arg_amount = [__calldata_ptr]\nlet __calldata_ptr = __calldata_ptr + 1\n", + "autogen/starknet/arg_processor/fee896b6d05b2e98056b5628baa6fbee0adfb8960f3fee9d79fd2f066956cc42.cairo": "assert [__return_value_ptr] = ret_struct.res\nlet __return_value_ptr = __return_value_ptr + 1\n", + "autogen/starknet/external/get_balance/424b26e79f70343cc02557f1fbd25745138efb26a3dc5c8b593ca765b73138b7.cairo": "let pedersen_ptr = [cast([cast(fp + (-5), felt**)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]\n", + "autogen/starknet/external/get_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo": "return (syscall_ptr,pedersen_ptr,range_check_ptr,retdata_size,retdata)\n", + "autogen/starknet/external/get_balance/c7060df96cb0acca1380ae43bf758cab727bfdf73cb5d34a93e24a9742817fda.cairo": "let syscall_ptr = [cast([cast(fp + (-5), felt**)] + 0, felt**)]\n", + "autogen/starknet/external/get_balance/e651458745e7cd218121c342e0915890767e2f59ddc2e315b8844ad0f47d582e.cairo": "let range_check_ptr = [cast([cast(fp + (-5), felt**)] + 2, felt*)]\n", + "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo": "let ret_struct = __wrapped_func{syscall_ptr=syscall_ptr, pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr}()\nlet (range_check_ptr, retdata_size, retdata) = get_balance_encode_return(ret_struct, range_check_ptr)\n", + "autogen/starknet/external/increase_balance/424b26e79f70343cc02557f1fbd25745138efb26a3dc5c8b593ca765b73138b7.cairo": "let pedersen_ptr = [cast([cast(fp + (-5), felt**)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]\n", + "autogen/starknet/external/increase_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo": "return (syscall_ptr,pedersen_ptr,range_check_ptr,retdata_size,retdata)\n", + "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo": "let ret_struct = __wrapped_func{syscall_ptr=syscall_ptr, pedersen_ptr=pedersen_ptr, range_check_ptr=range_check_ptr}(amount=__calldata_arg_amount,)\n%{ memory[ap] = segments.add() %} # Allocate memory for return value.\ntempvar retdata : felt*\nlet retdata_size = 0\n", + "autogen/starknet/external/increase_balance/c7060df96cb0acca1380ae43bf758cab727bfdf73cb5d34a93e24a9742817fda.cairo": "let syscall_ptr = [cast([cast(fp + (-5), felt**)] + 0, felt**)]\n", + "autogen/starknet/external/increase_balance/e651458745e7cd218121c342e0915890767e2f59ddc2e315b8844ad0f47d582e.cairo": "let range_check_ptr = [cast([cast(fp + (-5), felt**)] + 2, felt*)]\n", + "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo": "func get_balance_encode_return(ret_struct : __main__.get_balance.Return, range_check_ptr) -> (\n range_check_ptr, data_len : felt, data : felt*):\n %{ memory[ap] = segments.add() %}\n alloc_locals\n local __return_value_ptr_start : felt*\n let __return_value_ptr = __return_value_ptr_start\n with range_check_ptr:\n end\n return (\n range_check_ptr=range_check_ptr,\n data_len=__return_value_ptr - __return_value_ptr_start,\n data=__return_value_ptr_start)\nend\n", + "autogen/starknet/storage_var/balance/decl.cairo": "namespace balance:\n from starkware.starknet.common.storage import normalize_address\n from starkware.starknet.common.syscalls import storage_read, storage_write\n from starkware.cairo.common.cairo_builtins import HashBuiltin\n from starkware.cairo.common.hash import hash2\n\n func addr{pedersen_ptr : HashBuiltin*, range_check_ptr}() -> (res : felt):\n let res = 0\n call hash2\n call normalize_address\n end\n\n func read{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() -> (res : felt):\n let storage_addr = 0\n call addr\n call storage_read\n end\n\n func write{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(value : felt):\n let storage_addr = 0\n call addr\n call storage_write\n end\nend", + "autogen/starknet/storage_var/balance/impl.cairo": "namespace balance:\n from starkware.starknet.common.storage import normalize_address\n from starkware.starknet.common.syscalls import storage_read, storage_write\n from starkware.cairo.common.cairo_builtins import HashBuiltin\n from starkware.cairo.common.hash import hash2\n\n func addr{pedersen_ptr : HashBuiltin*, range_check_ptr}() -> (res : felt):\n let res = 916907772491729262376534102982219947830828984996257231353398618781993312401\n return (res=res)\n end\n\n func read{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}() -> (res : felt):\n let (storage_addr) = addr()\n let (__storage_var_temp0) = storage_read(address=storage_addr + 0)\n\n tempvar syscall_ptr = syscall_ptr\n tempvar pedersen_ptr = pedersen_ptr\n tempvar range_check_ptr = range_check_ptr\n tempvar __storage_var_temp0 : felt = __storage_var_temp0\n return ([cast(&__storage_var_temp0, felt*)])\n end\n\n func write{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(value : felt):\n let (storage_addr) = addr()\n storage_write(address=storage_addr + 0, value=[cast(&value, felt) + 0])\n return ()\n end\nend" + }, + "instruction_locations": { + "0": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 0 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.address": 0, + "starkware.starknet.common.syscalls.storage_read.syscall": 2, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 1 + } + }, + "hints": [], + "inst": { + "end_col": 79, + "end_line": 266, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 58, + "start_line": 266 + } + }, + "2": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.__temp0": 3, + "starkware.starknet.common.syscalls.storage_read.address": 0, + "starkware.starknet.common.syscalls.storage_read.syscall": 2, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 1 + } + }, + "hints": [], + "inst": { + "end_col": 97, + "end_line": 266, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 266 + } + }, + "3": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.__temp0": 3, + "starkware.starknet.common.syscalls.storage_read.address": 0, + "starkware.starknet.common.syscalls.storage_read.syscall": 2, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 1 + } + }, + "hints": [], + "inst": { + "end_col": 97, + "end_line": 266, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 266 + } + }, + "4": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.__temp0": 3, + "starkware.starknet.common.syscalls.storage_read.address": 0, + "starkware.starknet.common.syscalls.storage_read.response": 4, + "starkware.starknet.common.syscalls.storage_read.syscall": 2, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 5 + } + }, + "hints": [ + { + "location": { + "end_col": 87, + "end_line": 267, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 267 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 53, + "end_line": 269, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 38, + "end_line": 264, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 34, + "end_line": 270, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 270 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 19, + "start_line": 264 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 23, + "start_line": 269 + } + }, + "6": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 2 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.__temp0": 3, + "starkware.starknet.common.syscalls.storage_read.address": 0, + "starkware.starknet.common.syscalls.storage_read.response": 4, + "starkware.starknet.common.syscalls.storage_read.syscall": 2, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 5 + } + }, + "hints": [], + "inst": { + "end_col": 33, + "end_line": 270, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 19, + "start_line": 270 + } + }, + "7": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 3 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.__temp0": 3, + "starkware.starknet.common.syscalls.storage_read.address": 0, + "starkware.starknet.common.syscalls.storage_read.response": 4, + "starkware.starknet.common.syscalls.storage_read.syscall": 2, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 5 + } + }, + "hints": [], + "inst": { + "end_col": 34, + "end_line": 270, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 270 + } + }, + "8": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 0 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.address": 6, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 8, + "starkware.starknet.common.syscalls.storage_write.value": 7 + } + }, + "hints": [], + "inst": { + "end_col": 40, + "end_line": 284, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 18, + "start_line": 284 + } + }, + "10": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.__temp1": 9, + "starkware.starknet.common.syscalls.storage_write.address": 6, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 8, + "starkware.starknet.common.syscalls.storage_write.value": 7 + } + }, + "hints": [], + "inst": { + "end_col": 71, + "end_line": 284, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 283 + } + }, + "11": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.__temp1": 9, + "starkware.starknet.common.syscalls.storage_write.address": 6, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 8, + "starkware.starknet.common.syscalls.storage_write.value": 7 + } + }, + "hints": [], + "inst": { + "end_col": 71, + "end_line": 284, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 283 + } + }, + "12": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.__temp1": 9, + "starkware.starknet.common.syscalls.storage_write.address": 6, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 8, + "starkware.starknet.common.syscalls.storage_write.value": 7 + } + }, + "hints": [], + "inst": { + "end_col": 71, + "end_line": 284, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 283 + } + }, + "13": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.__temp1": 9, + "starkware.starknet.common.syscalls.storage_write.address": 6, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 10, + "starkware.starknet.common.syscalls.storage_write.value": 7 + } + }, + "hints": [ + { + "location": { + "end_col": 88, + "end_line": 285, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 285 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 54, + "end_line": 286, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 39, + "end_line": 282, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 14, + "end_line": 287, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 287 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 20, + "start_line": 282 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 23, + "start_line": 286 + } + }, + "15": { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 2 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.__temp1": 9, + "starkware.starknet.common.syscalls.storage_write.address": 6, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 10, + "starkware.starknet.common.syscalls.storage_write.value": 7 + } + }, + "hints": [], + "inst": { + "end_col": 14, + "end_line": 287, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "start_col": 5, + "start_line": 287 + } + }, + "16": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 0 + }, + "reference_ids": { + "__main__.balance.addr.pedersen_ptr": 11, + "__main__.balance.addr.range_check_ptr": 12, + "__main__.balance.addr.res": 13 + } + }, + "hints": [], + "inst": { + "end_col": 42, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 42, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 25, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 9 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + } + }, + "17": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 1 + }, + "reference_ids": { + "__main__.balance.addr.pedersen_ptr": 11, + "__main__.balance.addr.range_check_ptr": 12, + "__main__.balance.addr.res": 13 + } + }, + "hints": [], + "inst": { + "end_col": 59, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 59, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 25, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 9 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 44, + "start_line": 7 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 44, + "start_line": 7 + } + }, + "18": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 2 + }, + "reference_ids": { + "__main__.balance.addr.pedersen_ptr": 11, + "__main__.balance.addr.range_check_ptr": 12, + "__main__.balance.addr.res": 13 + } + }, + "hints": [], + "inst": { + "end_col": 94, + "end_line": 8, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 24, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 21, + "start_line": 9 + }, + "While expanding the reference 'res' in:" + ], + "start_col": 19, + "start_line": 8 + } + }, + "20": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.addr" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 2, + "offset": 3 + }, + "reference_ids": { + "__main__.balance.addr.pedersen_ptr": 11, + "__main__.balance.addr.range_check_ptr": 12, + "__main__.balance.addr.res": 13 + } + }, + "hints": [], + "inst": { + "end_col": 25, + "end_line": 9, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 9 + } + }, + "21": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 0 + }, + "reference_ids": { + "__main__.balance.read.pedersen_ptr": 15, + "__main__.balance.read.range_check_ptr": 16, + "__main__.balance.read.syscall_ptr": 14 + } + }, + "hints": [], + "inst": { + "end_col": 63, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 42, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 13 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 36, + "start_line": 12 + } + }, + "22": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 1 + }, + "reference_ids": { + "__main__.balance.read.pedersen_ptr": 15, + "__main__.balance.read.range_check_ptr": 16, + "__main__.balance.read.syscall_ptr": 14 + } + }, + "hints": [], + "inst": { + "end_col": 80, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 59, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 13 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 44, + "start_line": 7 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 65, + "start_line": 12 + } + }, + "23": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 2 + }, + "reference_ids": { + "__main__.balance.read.pedersen_ptr": 15, + "__main__.balance.read.range_check_ptr": 16, + "__main__.balance.read.syscall_ptr": 14 + } + }, + "hints": [], + "inst": { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 13 + } + }, + "25": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 7 + }, + "reference_ids": { + "__main__.balance.read.pedersen_ptr": 17, + "__main__.balance.read.range_check_ptr": 18, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 14 + } + }, + "hints": [], + "inst": { + "end_col": 34, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 38, + "end_line": 264, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 75, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 37, + "start_line": 14 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 19, + "start_line": 264 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 12 + } + }, + "26": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 8 + }, + "reference_ids": { + "__main__.balance.read.pedersen_ptr": 17, + "__main__.balance.read.range_check_ptr": 18, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 14 + } + }, + "hints": [], + "inst": { + "end_col": 26, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 70, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 58, + "start_line": 14 + }, + "While expanding the reference 'storage_addr' in:" + ], + "start_col": 14, + "start_line": 13 + } + }, + "27": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 9 + }, + "reference_ids": { + "__main__.balance.read.pedersen_ptr": 17, + "__main__.balance.read.range_check_ptr": 18, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 14 + } + }, + "hints": [], + "inst": { + "end_col": 75, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 37, + "start_line": 14 + } + }, + "29": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 14 + }, + "reference_ids": { + "__main__.balance.read.__storage_var_temp0": 21, + "__main__.balance.read.pedersen_ptr": 17, + "__main__.balance.read.range_check_ptr": 18, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 20 + } + }, + "hints": [], + "inst": { + "end_col": 38, + "end_line": 264, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 75, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 42, + "end_line": 16, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 31, + "start_line": 16 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 37, + "start_line": 14 + }, + "While trying to update the implicit return value 'syscall_ptr' in:" + ], + "start_col": 19, + "start_line": 264 + } + }, + "30": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 15 + }, + "reference_ids": { + "__main__.balance.read.__storage_var_temp0": 21, + "__main__.balance.read.pedersen_ptr": 17, + "__main__.balance.read.range_check_ptr": 18, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 22 + } + }, + "hints": [], + "inst": { + "end_col": 42, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 44, + "end_line": 17, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 32, + "start_line": 17 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 30, + "start_line": 13 + }, + "While trying to update the implicit return value 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + } + }, + "31": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 16 + }, + "reference_ids": { + "__main__.balance.read.__storage_var_temp0": 21, + "__main__.balance.read.pedersen_ptr": 23, + "__main__.balance.read.range_check_ptr": 18, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 22 + } + }, + "hints": [], + "inst": { + "end_col": 59, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 50, + "end_line": 18, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 35, + "start_line": 18 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 30, + "start_line": 13 + }, + "While trying to update the implicit return value 'range_check_ptr' in:" + ], + "start_col": 44, + "start_line": 7 + } + }, + "32": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 17 + }, + "reference_ids": { + "__main__.balance.read.__storage_var_temp0": 21, + "__main__.balance.read.pedersen_ptr": 23, + "__main__.balance.read.range_check_ptr": 24, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 22 + } + }, + "hints": [], + "inst": { + "end_col": 33, + "end_line": 14, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 65, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 46, + "start_line": 19 + }, + "While expanding the reference '__storage_var_temp0' in:" + ], + "start_col": 14, + "start_line": 14 + } + }, + "33": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.read" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 3, + "offset": 18 + }, + "reference_ids": { + "__main__.balance.read.__storage_var_temp0": 25, + "__main__.balance.read.pedersen_ptr": 23, + "__main__.balance.read.range_check_ptr": 24, + "__main__.balance.read.storage_addr": 19, + "__main__.balance.read.syscall_ptr": 22 + } + }, + "hints": [], + "inst": { + "end_col": 53, + "end_line": 20, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 20 + } + }, + "34": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 0 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 28, + "__main__.balance.write.range_check_ptr": 29, + "__main__.balance.write.syscall_ptr": 27, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 64, + "end_line": 23, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 42, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 24 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 37, + "start_line": 23 + } + }, + "35": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 1 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 28, + "__main__.balance.write.range_check_ptr": 29, + "__main__.balance.write.syscall_ptr": 27, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 81, + "end_line": 23, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 59, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 24 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 44, + "start_line": 7 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 66, + "start_line": 23 + } + }, + "36": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 2 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 28, + "__main__.balance.write.range_check_ptr": 29, + "__main__.balance.write.syscall_ptr": 27, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 30, + "start_line": 24 + } + }, + "38": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 7 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 30, + "__main__.balance.write.range_check_ptr": 31, + "__main__.balance.write.storage_addr": 32, + "__main__.balance.write.syscall_ptr": 27, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 35, + "end_line": 23, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 39, + "end_line": 282, + "input_file": { + "filename": "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/starkware/starknet/common/syscalls.cairo" + }, + "parent_location": [ + { + "end_col": 80, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 25 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 20, + "start_line": 282 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 16, + "start_line": 23 + } + }, + "39": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 8 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 30, + "__main__.balance.write.range_check_ptr": 31, + "__main__.balance.write.storage_addr": 32, + "__main__.balance.write.syscall_ptr": 27, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 26, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 43, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 31, + "start_line": 25 + }, + "While expanding the reference 'storage_addr' in:" + ], + "start_col": 14, + "start_line": 24 + } + }, + "40": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 9 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 30, + "__main__.balance.write.range_check_ptr": 31, + "__main__.balance.write.storage_addr": 32, + "__main__.balance.write.syscall_ptr": 27, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 79, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 55, + "start_line": 25 + } + }, + "41": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 10 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 30, + "__main__.balance.write.range_check_ptr": 31, + "__main__.balance.write.storage_addr": 32, + "__main__.balance.write.syscall_ptr": 27, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 80, + "end_line": 25, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 25 + } + }, + "43": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 14 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 30, + "__main__.balance.write.range_check_ptr": 31, + "__main__.balance.write.storage_addr": 32, + "__main__.balance.write.syscall_ptr": 33, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 42, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 64, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 18, + "end_line": 26, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 26 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 37, + "start_line": 19 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 30, + "start_line": 24 + }, + "While trying to update the implicit return value 'pedersen_ptr' in:" + ], + "start_col": 15, + "start_line": 7 + } + }, + "44": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 15 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 30, + "__main__.balance.write.range_check_ptr": 31, + "__main__.balance.write.storage_addr": 32, + "__main__.balance.write.syscall_ptr": 33, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 59, + "end_line": 7, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 24, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "parent_location": [ + { + "end_col": 81, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 18, + "end_line": 26, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 26 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 66, + "start_line": 19 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 30, + "start_line": 24 + }, + "While trying to update the implicit return value 'range_check_ptr' in:" + ], + "start_col": 44, + "start_line": 7 + } + }, + "45": { + "accessible_scopes": [ + "__main__", + "__main__.balance", + "__main__.balance.write" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 4, + "offset": 16 + }, + "reference_ids": { + "__main__.balance.write.pedersen_ptr": 30, + "__main__.balance.write.range_check_ptr": 31, + "__main__.balance.write.storage_addr": 32, + "__main__.balance.write.syscall_ptr": 33, + "__main__.balance.write.value": 26 + } + }, + "hints": [], + "inst": { + "end_col": 18, + "end_line": 26, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/impl.cairo" + }, + "start_col": 9, + "start_line": 26 + } + }, + "46": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 0 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 36, + "__main__.increase_balance.range_check_ptr": 37, + "__main__.increase_balance.syscall_ptr": 35 + } + }, + "hints": [], + "inst": { + "end_col": 42, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 34, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 16, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 16 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 13 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 23, + "start_line": 13 + } + }, + "47": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 1 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 36, + "__main__.increase_balance.range_check_ptr": 37, + "__main__.increase_balance.syscall_ptr": 35 + } + }, + "hints": [], + "inst": { + "end_col": 71, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 63, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 16, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 16 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 36, + "start_line": 13 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 44, + "start_line": 13 + } + }, + "48": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 2 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 36, + "__main__.increase_balance.range_check_ptr": 37, + "__main__.increase_balance.syscall_ptr": 35 + } + }, + "hints": [], + "inst": { + "end_col": 88, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 80, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 16, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 16 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 65, + "start_line": 13 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 73, + "start_line": 13 + } + }, + "49": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 3 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 36, + "__main__.increase_balance.range_check_ptr": 37, + "__main__.increase_balance.syscall_ptr": 35 + } + }, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 16, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 16 + } + }, + "51": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 23 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 39, + "__main__.increase_balance.range_check_ptr": 40, + "__main__.increase_balance.res": 41, + "__main__.increase_balance.syscall_ptr": 38 + } + }, + "hints": [], + "inst": { + "end_col": 34, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 16, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 35, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 32, + "end_line": 17, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 5, + "start_line": 17 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 16, + "start_line": 19 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 17, + "start_line": 16 + }, + "While trying to update the implicit return value 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 13 + } + }, + "52": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 24 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 39, + "__main__.increase_balance.range_check_ptr": 40, + "__main__.increase_balance.res": 41, + "__main__.increase_balance.syscall_ptr": 38 + } + }, + "hints": [], + "inst": { + "end_col": 63, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 16, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 64, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 32, + "end_line": 17, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 5, + "start_line": 17 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 37, + "start_line": 19 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 17, + "start_line": 16 + }, + "While trying to update the implicit return value 'pedersen_ptr' in:" + ], + "start_col": 36, + "start_line": 13 + } + }, + "53": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 25 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 39, + "__main__.increase_balance.range_check_ptr": 40, + "__main__.increase_balance.res": 41, + "__main__.increase_balance.syscall_ptr": 38 + } + }, + "hints": [], + "inst": { + "end_col": 80, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 16, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 81, + "end_line": 19, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 32, + "end_line": 17, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 5, + "start_line": 17 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 66, + "start_line": 19 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 17, + "start_line": 16 + }, + "While trying to update the implicit return value 'range_check_ptr' in:" + ], + "start_col": 65, + "start_line": 13 + } + }, + "54": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 26 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 39, + "__main__.increase_balance.range_check_ptr": 40, + "__main__.increase_balance.res": 41, + "__main__.increase_balance.syscall_ptr": 38 + } + }, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 17, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 19, + "start_line": 17 + } + }, + "55": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 27 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 39, + "__main__.increase_balance.range_check_ptr": 40, + "__main__.increase_balance.res": 41, + "__main__.increase_balance.syscall_ptr": 38 + } + }, + "hints": [], + "inst": { + "end_col": 32, + "end_line": 17, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 5, + "start_line": 17 + } + }, + "57": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 5, + "offset": 45 + }, + "reference_ids": { + "__main__.increase_balance.amount": 34, + "__main__.increase_balance.pedersen_ptr": 43, + "__main__.increase_balance.range_check_ptr": 44, + "__main__.increase_balance.res": 41, + "__main__.increase_balance.syscall_ptr": 42 + } + }, + "hints": [], + "inst": { + "end_col": 14, + "end_line": 18, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 5, + "start_line": 18 + } + }, + "58": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 0 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.pedersen_ptr": 46, + "__wrappers__.increase_balance.range_check_ptr": 47, + "__wrappers__.increase_balance.syscall_ptr": 45 + } + }, + "hints": [], + "inst": { + "end_col": 40, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/arg_processor/7a16feca69d1dc1343a49177e1e57103319136de3f2c6fabefae170177a1305e.cairo" + }, + "parent_location": [ + { + "end_col": 18, + "end_line": 14, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 45, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/5e1cc73f0b484f90bb02da164d88332b40c6f698801aa4d3c603dab22157e902.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 57, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/1b562308a65653425ce06491fa4b4539466f3251a07e73e099d0afe86a48900e.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While handling calldata of" + ], + "start_col": 35, + "start_line": 1 + }, + "While expanding the reference '__calldata_actual_size' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While handling calldata of" + ], + "start_col": 31, + "start_line": 1 + }, + "While expanding the reference '__calldata_ptr' in:" + ], + "start_col": 5, + "start_line": 14 + }, + "While handling calldata argument 'amount'" + ], + "start_col": 22, + "start_line": 2 + } + }, + "60": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 1 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 46, + "__wrappers__.increase_balance.range_check_ptr": 47, + "__wrappers__.increase_balance.syscall_ptr": 45 + } + }, + "hints": [], + "inst": { + "end_col": 57, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/1b562308a65653425ce06491fa4b4539466f3251a07e73e099d0afe86a48900e.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While handling calldata of" + ], + "start_col": 1, + "start_line": 1 + } + }, + "61": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 1 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 46, + "__wrappers__.increase_balance.range_check_ptr": 47, + "__wrappers__.increase_balance.syscall_ptr": 45 + } + }, + "hints": [], + "inst": { + "end_col": 64, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/c7060df96cb0acca1380ae43bf758cab727bfdf73cb5d34a93e24a9742817fda.cairo" + }, + "parent_location": [ + { + "end_col": 42, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 56, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 45, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 23, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 19, + "start_line": 1 + } + }, + "62": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 2 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 46, + "__wrappers__.increase_balance.range_check_ptr": 47, + "__wrappers__.increase_balance.syscall_ptr": 45 + } + }, + "hints": [], + "inst": { + "end_col": 110, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/424b26e79f70343cc02557f1fbd25745138efb26a3dc5c8b593ca765b73138b7.cairo" + }, + "parent_location": [ + { + "end_col": 71, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 83, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 71, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 44, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 20, + "start_line": 1 + } + }, + "63": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 3 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 46, + "__wrappers__.increase_balance.range_check_ptr": 47, + "__wrappers__.increase_balance.syscall_ptr": 45 + } + }, + "hints": [], + "inst": { + "end_col": 67, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/e651458745e7cd218121c342e0915890767e2f59ddc2e315b8844ad0f47d582e.cairo" + }, + "parent_location": [ + { + "end_col": 88, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 116, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 101, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 73, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 23, + "start_line": 1 + } + }, + "64": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 4 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 46, + "__wrappers__.increase_balance.range_check_ptr": 47, + "__wrappers__.increase_balance.syscall_ptr": 45 + } + }, + "hints": [], + "inst": { + "end_col": 45, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/7a16feca69d1dc1343a49177e1e57103319136de3f2c6fabefae170177a1305e.cairo" + }, + "parent_location": [ + { + "end_col": 18, + "end_line": 14, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 146, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 125, + "start_line": 1 + }, + "While expanding the reference '__calldata_arg_amount' in:" + ], + "start_col": 5, + "start_line": 14 + }, + "While handling calldata argument 'amount'" + ], + "start_col": 29, + "start_line": 1 + } + }, + "65": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 5 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 46, + "__wrappers__.increase_balance.range_check_ptr": 47, + "__wrappers__.increase_balance.syscall_ptr": 45 + } + }, + "hints": [], + "inst": { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + } + }, + "67": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 52 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + }, + "hints": [ + { + "location": { + "end_col": 34, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 2 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 24, + "end_line": 3, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 3 + } + }, + "69": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 53 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.retdata": 57, + "__wrappers__.increase_balance.retdata_size": 58, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + }, + "hints": [], + "inst": { + "end_col": 56, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 20, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 9, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 45, + "start_line": 1 + } + }, + "70": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 54 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.retdata": 57, + "__wrappers__.increase_balance.retdata_size": 58, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + }, + "hints": [], + "inst": { + "end_col": 83, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 33, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 21, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 71, + "start_line": 1 + } + }, + "71": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 55 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.retdata": 57, + "__wrappers__.increase_balance.retdata_size": 58, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + }, + "hints": [], + "inst": { + "end_col": 116, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 49, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 34, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 101, + "start_line": 1 + } + }, + "72": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 56 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.retdata": 57, + "__wrappers__.increase_balance.retdata_size": 58, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + }, + "hints": [], + "inst": { + "end_col": 21, + "end_line": 4, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 62, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 50, + "start_line": 1 + }, + "While expanding the reference 'retdata_size' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 20, + "start_line": 4 + } + }, + "74": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 57 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.retdata": 57, + "__wrappers__.increase_balance.retdata_size": 58, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + }, + "hints": [], + "inst": { + "end_col": 16, + "end_line": 3, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/b659e0b441b52e0e1ab35c834d1991f044fe80d7b0593ebe3e771ee044a7dabb.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 70, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 63, + "start_line": 1 + }, + "While expanding the reference 'retdata' in:" + ], + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 9, + "start_line": 3 + } + }, + "75": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 58 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.retdata": 57, + "__wrappers__.increase_balance.retdata_size": 58, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + }, + "hints": [], + "inst": { + "end_col": 71, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/increase_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 22, + "end_line": 13, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 13 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 1 + } + }, + "76": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 0 + }, + "reference_ids": { + "__main__.get_balance.pedersen_ptr": 60, + "__main__.get_balance.range_check_ptr": 61, + "__main__.get_balance.syscall_ptr": 59 + } + }, + "hints": [], + "inst": { + "end_col": 37, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 34, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 26, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 26 + }, + "While trying to retrieve the implicit argument 'syscall_ptr' in:" + ], + "start_col": 15, + "start_line": 13 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 18, + "start_line": 23 + } + }, + "77": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 1 + }, + "reference_ids": { + "__main__.get_balance.pedersen_ptr": 60, + "__main__.get_balance.range_check_ptr": 61, + "__main__.get_balance.syscall_ptr": 59 + } + }, + "hints": [], + "inst": { + "end_col": 66, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 63, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 26, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 26 + }, + "While trying to retrieve the implicit argument 'pedersen_ptr' in:" + ], + "start_col": 36, + "start_line": 13 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 39, + "start_line": 23 + } + }, + "78": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 2 + }, + "reference_ids": { + "__main__.get_balance.pedersen_ptr": 60, + "__main__.get_balance.range_check_ptr": 61, + "__main__.get_balance.syscall_ptr": 59 + } + }, + "hints": [], + "inst": { + "end_col": 83, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 80, + "end_line": 13, + "input_file": { + "filename": "autogen/starknet/storage_var/balance/decl.cairo" + }, + "parent_location": [ + { + "end_col": 31, + "end_line": 26, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 26 + }, + "While trying to retrieve the implicit argument 'range_check_ptr' in:" + ], + "start_col": 65, + "start_line": 13 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 68, + "start_line": 23 + } + }, + "79": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 3 + }, + "reference_ids": { + "__main__.get_balance.pedersen_ptr": 60, + "__main__.get_balance.range_check_ptr": 61, + "__main__.get_balance.syscall_ptr": 59 + } + }, + "hints": [], + "inst": { + "end_col": 31, + "end_line": 26, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 17, + "start_line": 26 + } + }, + "81": { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 7, + "offset": 23 + }, + "reference_ids": { + "__main__.get_balance.pedersen_ptr": 63, + "__main__.get_balance.range_check_ptr": 64, + "__main__.get_balance.res": 65, + "__main__.get_balance.syscall_ptr": 62 + } + }, + "hints": [], + "inst": { + "end_col": 17, + "end_line": 27, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 5, + "start_line": 27 + } + }, + "82": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 0 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + }, + "hints": [ + { + "location": { + "end_col": 38, + "end_line": 3, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 5, + "start_line": 3 + }, + "n_prefix_newlines": 0 + } + ], + "inst": { + "end_col": 17, + "end_line": 4, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 5, + "start_line": 4 + } + }, + "84": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 1 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.__return_value_ptr": 69, + "__wrappers__.get_balance_encode_return.__return_value_ptr_start": 68, + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + }, + "hints": [], + "inst": { + "end_col": 45, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/fee896b6d05b2e98056b5628baa6fbee0adfb8960f3fee9d79fd2f066956cc42.cairo" + }, + "parent_location": [ + { + "end_col": 15, + "end_line": 24, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 5, + "start_line": 24 + }, + "While handling return value 'res'" + ], + "start_col": 1, + "start_line": 1 + } + }, + "85": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 1 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.__return_value_ptr": 70, + "__wrappers__.get_balance_encode_return.__return_value_ptr_start": 68, + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + }, + "hints": [], + "inst": { + "end_col": 48, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/arg_processor/fee896b6d05b2e98056b5628baa6fbee0adfb8960f3fee9d79fd2f066956cc42.cairo" + }, + "parent_location": [ + { + "end_col": 15, + "end_line": 24, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 36, + "end_line": 11, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 18, + "start_line": 11 + }, + "While expanding the reference '__return_value_ptr' in:" + ], + "start_col": 5, + "start_line": 24 + }, + "While handling return value 'res'" + ], + "start_col": 26, + "start_line": 2 + } + }, + "87": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 2 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.__return_value_ptr": 70, + "__wrappers__.get_balance_encode_return.__return_value_ptr_start": 68, + "__wrappers__.get_balance_encode_return.__temp3": 71, + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + }, + "hints": [], + "inst": { + "end_col": 89, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 40, + "end_line": 10, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 25, + "start_line": 10 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 74, + "start_line": 1 + } + }, + "88": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 3 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.__return_value_ptr": 70, + "__wrappers__.get_balance_encode_return.__return_value_ptr_start": 68, + "__wrappers__.get_balance_encode_return.__temp3": 71, + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + }, + "hints": [], + "inst": { + "end_col": 63, + "end_line": 11, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 18, + "start_line": 11 + } + }, + "89": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 4 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.__return_value_ptr": 70, + "__wrappers__.get_balance_encode_return.__return_value_ptr_start": 68, + "__wrappers__.get_balance_encode_return.__temp3": 71, + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + }, + "hints": [], + "inst": { + "end_col": 35, + "end_line": 5, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 38, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 14, + "start_line": 12 + }, + "While expanding the reference '__return_value_ptr_start' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 11, + "start_line": 5 + } + }, + "90": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 5 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.__return_value_ptr": 70, + "__wrappers__.get_balance_encode_return.__return_value_ptr_start": 68, + "__wrappers__.get_balance_encode_return.__temp3": 71, + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + }, + "hints": [], + "inst": { + "end_col": 39, + "end_line": 12, + "input_file": { + "filename": "autogen/starknet/external/return/get_balance/4347b8d39c88b0ad2e8b75ecb28ec6466349f83ba13797a9224bef1cda14278c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling return value of" + ], + "start_col": 5, + "start_line": 9 + } + }, + "91": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 0 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 73, + "__wrappers__.get_balance.range_check_ptr": 74, + "__wrappers__.get_balance.syscall_ptr": 72 + } + }, + "hints": [], + "inst": { + "end_col": 57, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/arg_processor/1b562308a65653425ce06491fa4b4539466f3251a07e73e099d0afe86a48900e.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While handling calldata of" + ], + "start_col": 1, + "start_line": 1 + } + }, + "92": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 0 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 73, + "__wrappers__.get_balance.range_check_ptr": 74, + "__wrappers__.get_balance.syscall_ptr": 72 + } + }, + "hints": [], + "inst": { + "end_col": 64, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/c7060df96cb0acca1380ae43bf758cab727bfdf73cb5d34a93e24a9742817fda.cairo" + }, + "parent_location": [ + { + "end_col": 37, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 56, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 45, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 18, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 19, + "start_line": 1 + } + }, + "93": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 1 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 73, + "__wrappers__.get_balance.range_check_ptr": 74, + "__wrappers__.get_balance.syscall_ptr": 72 + } + }, + "hints": [], + "inst": { + "end_col": 110, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/424b26e79f70343cc02557f1fbd25745138efb26a3dc5c8b593ca765b73138b7.cairo" + }, + "parent_location": [ + { + "end_col": 66, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 83, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 71, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 39, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 20, + "start_line": 1 + } + }, + "94": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 2 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 73, + "__wrappers__.get_balance.range_check_ptr": 74, + "__wrappers__.get_balance.syscall_ptr": 72 + } + }, + "hints": [], + "inst": { + "end_col": 67, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/e651458745e7cd218121c342e0915890767e2f59ddc2e315b8844ad0f47d582e.cairo" + }, + "parent_location": [ + { + "end_col": 83, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 116, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 101, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 68, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 23, + "start_line": 1 + } + }, + "95": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 3 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 73, + "__wrappers__.get_balance.range_check_ptr": 74, + "__wrappers__.get_balance.syscall_ptr": 72 + } + }, + "hints": [], + "inst": { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + } + }, + "97": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 28 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 79, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 116, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 101, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 86, + "start_line": 2 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 101, + "start_line": 1 + } + }, + "98": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 29 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 79, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 102, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 48, + "start_line": 2 + } + }, + "100": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 36 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 81, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.retdata": 83, + "__wrappers__.get_balance.retdata_size": 82, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 56, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 20, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 9, + "start_line": 1 + }, + "While expanding the reference 'syscall_ptr' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 45, + "start_line": 1 + } + }, + "101": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 37 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 81, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.retdata": 83, + "__wrappers__.get_balance.retdata_size": 82, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 83, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 33, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 21, + "start_line": 1 + }, + "While expanding the reference 'pedersen_ptr' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 71, + "start_line": 1 + } + }, + "102": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 38 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 81, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.retdata": 83, + "__wrappers__.get_balance.retdata_size": 82, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 21, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 49, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 34, + "start_line": 1 + }, + "While expanding the reference 'range_check_ptr' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 6, + "start_line": 2 + } + }, + "103": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 39 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 81, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.retdata": 83, + "__wrappers__.get_balance.retdata_size": 82, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 35, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 62, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 50, + "start_line": 1 + }, + "While expanding the reference 'retdata_size' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 23, + "start_line": 2 + } + }, + "104": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 40 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 81, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.retdata": 83, + "__wrappers__.get_balance.retdata_size": 82, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 44, + "end_line": 2, + "input_file": { + "filename": "autogen/starknet/external/get_balance/fe6bfd058f097fe6019d30e1c6708266c68be305a2d1051d1a94fe208482e3e9.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "parent_location": [ + { + "end_col": 70, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 63, + "start_line": 1 + }, + "While expanding the reference 'retdata' in:" + ], + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 37, + "start_line": 2 + } + }, + "105": { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance" + ], + "flow_tracking_data": { + "ap_tracking": { + "group": 9, + "offset": 41 + }, + "reference_ids": { + "__wrappers__.get_balance.__calldata_actual_size": 76, + "__wrappers__.get_balance.__calldata_ptr": 75, + "__wrappers__.get_balance.pedersen_ptr": 78, + "__wrappers__.get_balance.range_check_ptr": 81, + "__wrappers__.get_balance.ret_struct": 80, + "__wrappers__.get_balance.retdata": 83, + "__wrappers__.get_balance.retdata_size": 82, + "__wrappers__.get_balance.syscall_ptr": 77 + } + }, + "hints": [], + "inst": { + "end_col": 71, + "end_line": 1, + "input_file": { + "filename": "autogen/starknet/external/get_balance/4ba2b119ceb30fe10f4cca3c9d73ef620c0fb5eece91b99a99d71217bba1001c.cairo" + }, + "parent_location": [ + { + "end_col": 17, + "end_line": 23, + "input_file": { + "filename": "contract.cairo" + }, + "start_col": 6, + "start_line": 23 + }, + "While constructing the external wrapper for:" + ], + "start_col": 1, + "start_line": 1 + } + } + } + }, + "hints": { + "4": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_read" + ], + "code": "syscall_handler.storage_read(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 0, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_read.__temp0": 3, + "starkware.starknet.common.syscalls.storage_read.address": 0, + "starkware.starknet.common.syscalls.storage_read.syscall": 2, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": 1 + } + } + } + ], + "13": [ + { + "accessible_scopes": [ + "starkware.starknet.common.syscalls", + "starkware.starknet.common.syscalls.storage_write" + ], + "code": "syscall_handler.storage_write(segments=segments, syscall_ptr=ids.syscall_ptr)", + "flow_tracking_data": { + "ap_tracking": { + "group": 1, + "offset": 1 + }, + "reference_ids": { + "starkware.starknet.common.syscalls.storage_write.__temp1": 9, + "starkware.starknet.common.syscalls.storage_write.address": 6, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": 8, + "starkware.starknet.common.syscalls.storage_write.value": 7 + } + } + } + ], + "67": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.increase_balance" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 6, + "offset": 52 + }, + "reference_ids": { + "__wrappers__.increase_balance.__calldata_actual_size": 51, + "__wrappers__.increase_balance.__calldata_arg_amount": 49, + "__wrappers__.increase_balance.__calldata_ptr": 50, + "__wrappers__.increase_balance.__temp2": 52, + "__wrappers__.increase_balance.pedersen_ptr": 54, + "__wrappers__.increase_balance.range_check_ptr": 55, + "__wrappers__.increase_balance.ret_struct": 56, + "__wrappers__.increase_balance.syscall_ptr": 53 + } + } + } + ], + "82": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__wrappers__", + "__wrappers__.get_balance_encode_return" + ], + "code": "memory[ap] = segments.add()", + "flow_tracking_data": { + "ap_tracking": { + "group": 8, + "offset": 0 + }, + "reference_ids": { + "__wrappers__.get_balance_encode_return.range_check_ptr": 67, + "__wrappers__.get_balance_encode_return.ret_struct": 66 + } + } + } + ] + }, + "identifiers": { + "__main__.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.balance": { + "type": "namespace" + }, + "__main__.balance.Args": { + "full_name": "__main__.balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "__main__.balance.ImplicitArgs": { + "full_name": "__main__.balance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.Return": { + "full_name": "__main__.balance.Return", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.balance.addr": { + "decorators": [], + "pc": 16, + "type": "function" + }, + "__main__.balance.addr.Args": { + "full_name": "__main__.balance.addr.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.addr.ImplicitArgs": { + "full_name": "__main__.balance.addr.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 0 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "__main__.balance.addr.Return": { + "full_name": "__main__.balance.addr.Return", + "members": { + "res": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.balance.addr.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.balance.addr.pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "full_name": "__main__.balance.addr.pedersen_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 16, + "value": "[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + } + ], + "type": "reference" + }, + "__main__.balance.addr.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__main__.balance.addr.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 16, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__main__.balance.addr.res": { + "cairo_type": "felt", + "full_name": "__main__.balance.addr.res", + "references": [ + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 16, + "value": "cast(916907772491729262376534102982219947830828984996257231353398618781993312401, felt)" + } + ], + "type": "reference" + }, + "__main__.balance.hash2": { + "destination": "starkware.cairo.common.hash.hash2", + "type": "alias" + }, + "__main__.balance.normalize_address": { + "destination": "starkware.starknet.common.storage.normalize_address", + "type": "alias" + }, + "__main__.balance.read": { + "decorators": [], + "pc": 21, + "type": "function" + }, + "__main__.balance.read.Args": { + "full_name": "__main__.balance.read.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.read.ImplicitArgs": { + "full_name": "__main__.balance.read.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.balance.read.Return": { + "full_name": "__main__.balance.read.Return", + "members": { + "res": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.balance.read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.balance.read.__storage_var_temp0": { + "cairo_type": "felt", + "full_name": "__main__.balance.read.__storage_var_temp0", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 14 + }, + "pc": 29, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 18 + }, + "pc": 33, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__main__.balance.read.pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "full_name": "__main__.balance.read.pedersen_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 21, + "value": "[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 7 + }, + "pc": 25, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 16 + }, + "pc": 31, + "value": "[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + } + ], + "type": "reference" + }, + "__main__.balance.read.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__main__.balance.read.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 21, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 7 + }, + "pc": 25, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 17 + }, + "pc": 32, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__main__.balance.read.storage_addr": { + "cairo_type": "felt", + "full_name": "__main__.balance.read.storage_addr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 7 + }, + "pc": 25, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__main__.balance.read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "__main__.balance.read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 21, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 14 + }, + "pc": 29, + "value": "[cast(ap + (-2), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 15 + }, + "pc": 30, + "value": "[cast(ap + (-1), felt**)]" + } + ], + "type": "reference" + }, + "__main__.balance.storage_read": { + "destination": "starkware.starknet.common.syscalls.storage_read", + "type": "alias" + }, + "__main__.balance.storage_write": { + "destination": "starkware.starknet.common.syscalls.storage_write", + "type": "alias" + }, + "__main__.balance.write": { + "decorators": [], + "pc": 34, + "type": "function" + }, + "__main__.balance.write.Args": { + "full_name": "__main__.balance.write.Args", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.balance.write.ImplicitArgs": { + "full_name": "__main__.balance.write.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.balance.write.Return": { + "full_name": "__main__.balance.write.Return", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.balance.write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.balance.write.pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "full_name": "__main__.balance.write.pedersen_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 7 + }, + "pc": 38, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + } + ], + "type": "reference" + }, + "__main__.balance.write.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__main__.balance.write.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-4), felt*)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 7 + }, + "pc": 38, + "value": "[cast(ap + (-2), felt*)]" + } + ], + "type": "reference" + }, + "__main__.balance.write.storage_addr": { + "cairo_type": "felt", + "full_name": "__main__.balance.write.storage_addr", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 7 + }, + "pc": 38, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__main__.balance.write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "__main__.balance.write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-6), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 14 + }, + "pc": 43, + "value": "[cast(ap + (-1), felt**)]" + } + ], + "type": "reference" + }, + "__main__.balance.write.value": { + "cairo_type": "felt", + "full_name": "__main__.balance.write.value", + "references": [ + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__main__.get_balance": { + "decorators": [ + "view" + ], + "pc": 76, + "type": "function" + }, + "__main__.get_balance.Args": { + "full_name": "__main__.get_balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.get_balance.ImplicitArgs": { + "full_name": "__main__.get_balance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.get_balance.Return": { + "full_name": "__main__.get_balance.Return", + "members": { + "res": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.get_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.get_balance.pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "full_name": "__main__.get_balance.pedersen_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 76, + "value": "[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + } + ], + "type": "reference" + }, + "__main__.get_balance.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__main__.get_balance.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 76, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-2), felt*)]" + } + ], + "type": "reference" + }, + "__main__.get_balance.res": { + "cairo_type": "felt", + "full_name": "__main__.get_balance.res", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__main__.get_balance.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "__main__.get_balance.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 76, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-4), felt**)]" + } + ], + "type": "reference" + }, + "__main__.increase_balance": { + "decorators": [ + "external" + ], + "pc": 46, + "type": "function" + }, + "__main__.increase_balance.Args": { + "full_name": "__main__.increase_balance.Args", + "members": { + "amount": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "__main__.increase_balance.ImplicitArgs": { + "full_name": "__main__.increase_balance.ImplicitArgs", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__main__.increase_balance.Return": { + "full_name": "__main__.increase_balance.Return", + "members": {}, + "size": 0, + "type": "struct" + }, + "__main__.increase_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__main__.increase_balance.amount": { + "cairo_type": "felt", + "full_name": "__main__.increase_balance.amount", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__main__.increase_balance.pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "full_name": "__main__.increase_balance.pedersen_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 45 + }, + "pc": 57, + "value": "[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + } + ], + "type": "reference" + }, + "__main__.increase_balance.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__main__.increase_balance.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-4), felt*)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 45 + }, + "pc": 57, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__main__.increase_balance.res": { + "cairo_type": "felt", + "full_name": "__main__.increase_balance.res", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__main__.increase_balance.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "__main__.increase_balance.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-6), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 45 + }, + "pc": 57, + "value": "[cast(ap + (-3), felt**)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance": { + "decorators": [ + "view" + ], + "pc": 91, + "type": "function" + }, + "__wrappers__.get_balance.Args": { + "full_name": "__wrappers__.get_balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_balance.ImplicitArgs": { + "full_name": "__wrappers__.get_balance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_balance.Return": { + "full_name": "__wrappers__.get_balance.Return", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "retdata": { + "cairo_type": "felt*", + "offset": 4 + }, + "size": { + "cairo_type": "felt", + "offset": 3 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "__wrappers__.get_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.get_balance.__calldata_actual_size": { + "cairo_type": "felt", + "full_name": "__wrappers__.get_balance.__calldata_actual_size", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "cast([fp + (-3)] - [fp + (-3)], felt)" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance.__calldata_ptr": { + "cairo_type": "felt*", + "full_name": "__wrappers__.get_balance.__calldata_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast(fp + (-3), felt**)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance.__wrapped_func": { + "destination": "__main__.get_balance", + "type": "alias" + }, + "__wrappers__.get_balance.pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "full_name": "__wrappers__.get_balance.pedersen_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__wrappers__.get_balance.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast([fp + (-5)] + 2, felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 36 + }, + "pc": 100, + "value": "[cast(ap + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance.ret_struct": { + "cairo_type": "__main__.get_balance.Return", + "full_name": "__wrappers__.get_balance.ret_struct", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-1), __main__.get_balance.Return*)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance.retdata": { + "cairo_type": "felt*", + "full_name": "__wrappers__.get_balance.retdata", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 36 + }, + "pc": 100, + "value": "[cast(ap + (-1), felt**)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance.retdata_size": { + "cairo_type": "felt", + "full_name": "__wrappers__.get_balance.retdata_size", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 36 + }, + "pc": 100, + "value": "[cast(ap + (-2), felt*)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "__wrappers__.get_balance.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast([fp + (-5)], felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-4), felt**)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance_encode_return": { + "decorators": [], + "pc": 82, + "type": "function" + }, + "__wrappers__.get_balance_encode_return.Args": { + "full_name": "__wrappers__.get_balance_encode_return.Args", + "members": { + "range_check_ptr": { + "cairo_type": "felt", + "offset": 1 + }, + "ret_struct": { + "cairo_type": "__main__.get_balance.Return", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "__wrappers__.get_balance_encode_return.ImplicitArgs": { + "full_name": "__wrappers__.get_balance_encode_return.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.get_balance_encode_return.Return": { + "full_name": "__wrappers__.get_balance_encode_return.Return", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 2 + }, + "data_len": { + "cairo_type": "felt", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 3, + "type": "struct" + }, + "__wrappers__.get_balance_encode_return.SIZEOF_LOCALS": { + "type": "const", + "value": 1 + }, + "__wrappers__.get_balance_encode_return.__return_value_ptr": { + "cairo_type": "felt*", + "full_name": "__wrappers__.get_balance_encode_return.__return_value_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 84, + "value": "[cast(fp, felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 85, + "value": "cast([fp] + 1, felt*)" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance_encode_return.__return_value_ptr_start": { + "cairo_type": "felt*", + "full_name": "__wrappers__.get_balance_encode_return.__return_value_ptr_start", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 84, + "value": "[cast(fp, felt**)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance_encode_return.__temp3": { + "cairo_type": "felt", + "full_name": "__wrappers__.get_balance_encode_return.__temp3", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 2 + }, + "pc": 87, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "__wrappers__.get_balance_encode_return.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__wrappers__.get_balance_encode_return.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 82, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "__wrappers__.get_balance_encode_return.ret_struct": { + "cairo_type": "__main__.get_balance.Return", + "full_name": "__wrappers__.get_balance_encode_return.ret_struct", + "references": [ + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 82, + "value": "[cast(fp + (-4), __main__.get_balance.Return*)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance": { + "decorators": [ + "external" + ], + "pc": 58, + "type": "function" + }, + "__wrappers__.increase_balance.Args": { + "full_name": "__wrappers__.increase_balance.Args", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increase_balance.ImplicitArgs": { + "full_name": "__wrappers__.increase_balance.ImplicitArgs", + "members": {}, + "size": 0, + "type": "struct" + }, + "__wrappers__.increase_balance.Return": { + "full_name": "__wrappers__.increase_balance.Return", + "members": { + "pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "offset": 1 + }, + "range_check_ptr": { + "cairo_type": "felt", + "offset": 2 + }, + "retdata": { + "cairo_type": "felt*", + "offset": 4 + }, + "size": { + "cairo_type": "felt", + "offset": 3 + }, + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "__wrappers__.increase_balance.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "__wrappers__.increase_balance.__calldata_actual_size": { + "cairo_type": "felt", + "full_name": "__wrappers__.increase_balance.__calldata_actual_size", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "cast([fp + (-3)] + 1 - [fp + (-3)], felt)" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.__calldata_arg_amount": { + "cairo_type": "felt", + "full_name": "__wrappers__.increase_balance.__calldata_arg_amount", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-3)], felt*)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.__calldata_ptr": { + "cairo_type": "felt*", + "full_name": "__wrappers__.increase_balance.__calldata_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "cast([fp + (-3)] + 1, felt*)" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.__temp2": { + "cairo_type": "felt", + "full_name": "__wrappers__.increase_balance.__temp2", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 1 + }, + "pc": 60, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.__wrapped_func": { + "destination": "__main__.increase_balance", + "type": "alias" + }, + "__wrappers__.increase_balance.pedersen_ptr": { + "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*", + "full_name": "__wrappers__.increase_balance.pedersen_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.range_check_ptr": { + "cairo_type": "felt", + "full_name": "__wrappers__.increase_balance.range_check_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-5)] + 2, felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.ret_struct": { + "cairo_type": "__main__.increase_balance.Return", + "full_name": "__wrappers__.increase_balance.ret_struct", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + 0, __main__.increase_balance.Return*)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.retdata": { + "cairo_type": "felt*", + "full_name": "__wrappers__.increase_balance.retdata", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 53 + }, + "pc": 69, + "value": "[cast(ap + (-1), felt**)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.retdata_size": { + "cairo_type": "felt", + "full_name": "__wrappers__.increase_balance.retdata_size", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 53 + }, + "pc": 69, + "value": "cast(0, felt)" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "__wrappers__.increase_balance.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-5)], felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + (-3), felt**)]" + } + ], + "type": "reference" + }, + "__wrappers__.increase_balance_encode_return.memcpy": { + "destination": "starkware.cairo.common.memcpy.memcpy", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.BitwiseBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.BitwiseBuiltin", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "x_and_y": { + "cairo_type": "felt", + "offset": 2 + }, + "x_or_y": { + "cairo_type": "felt", + "offset": 4 + }, + "x_xor_y": { + "cairo_type": "felt", + "offset": 3 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcOpBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.EcOpBuiltin", + "members": { + "m": { + "cairo_type": "felt", + "offset": 4 + }, + "p": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 0 + }, + "q": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 2 + }, + "r": { + "cairo_type": "starkware.cairo.common.ec_point.EcPoint", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.EcPoint": { + "destination": "starkware.cairo.common.ec_point.EcPoint", + "type": "alias" + }, + "starkware.cairo.common.cairo_builtins.HashBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "members": { + "result": { + "cairo_type": "felt", + "offset": 2 + }, + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.cairo_builtins.SignatureBuiltin": { + "full_name": "starkware.cairo.common.cairo_builtins.SignatureBuiltin", + "members": { + "message": { + "cairo_type": "felt", + "offset": 1 + }, + "pub_key": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.dict_access.DictAccess": { + "full_name": "starkware.cairo.common.dict_access.DictAccess", + "members": { + "key": { + "cairo_type": "felt", + "offset": 0 + }, + "new_value": { + "cairo_type": "felt", + "offset": 2 + }, + "prev_value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.cairo.common.ec_point.EcPoint": { + "full_name": "starkware.cairo.common.ec_point.EcPoint", + "members": { + "x": { + "cairo_type": "felt", + "offset": 0 + }, + "y": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.cairo.common.hash.HashBuiltin": { + "destination": "starkware.cairo.common.cairo_builtins.HashBuiltin", + "type": "alias" + }, + "starkware.starknet.common.storage.ADDR_BOUND": { + "type": "const", + "value": -106710729501573572985208420194530329073740042555888586719489 + }, + "starkware.starknet.common.storage.MAX_STORAGE_ITEM_SIZE": { + "type": "const", + "value": 256 + }, + "starkware.starknet.common.storage.assert_250_bit": { + "destination": "starkware.cairo.common.math.assert_250_bit", + "type": "alias" + }, + "starkware.starknet.common.syscalls.CALL_CONTRACT_SELECTOR": { + "type": "const", + "value": 20853273475220472486191784820 + }, + "starkware.starknet.common.syscalls.CallContract": { + "full_name": "starkware.starknet.common.syscalls.CallContract", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.CallContractResponse", + "offset": 5 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractRequest": { + "full_name": "starkware.starknet.common.syscalls.CallContractRequest", + "members": { + "calldata": { + "cairo_type": "felt*", + "offset": 4 + }, + "calldata_size": { + "cairo_type": "felt", + "offset": 3 + }, + "contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "function_selector": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.CallContractResponse": { + "full_name": "starkware.starknet.common.syscalls.CallContractResponse", + "members": { + "retdata": { + "cairo_type": "felt*", + "offset": 1 + }, + "retdata_size": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.DELEGATE_CALL_SELECTOR": { + "type": "const", + "value": 21167594061783206823196716140 + }, + "starkware.starknet.common.syscalls.DELEGATE_L1_HANDLER_SELECTOR": { + "type": "const", + "value": 23274015802972845247556842986379118667122 + }, + "starkware.starknet.common.syscalls.DictAccess": { + "destination": "starkware.cairo.common.dict_access.DictAccess", + "type": "alias" + }, + "starkware.starknet.common.syscalls.EMIT_EVENT_SELECTOR": { + "type": "const", + "value": 1280709301550335749748 + }, + "starkware.starknet.common.syscalls.EmitEvent": { + "full_name": "starkware.starknet.common.syscalls.EmitEvent", + "members": { + "data": { + "cairo_type": "felt*", + "offset": 4 + }, + "data_len": { + "cairo_type": "felt", + "offset": 3 + }, + "keys": { + "cairo_type": "felt*", + "offset": 2 + }, + "keys_len": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 5, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GET_BLOCK_NUMBER_SELECTOR": { + "type": "const", + "value": 1448089106835523001438702345020786 + }, + "starkware.starknet.common.syscalls.GET_BLOCK_TIMESTAMP_SELECTOR": { + "type": "const", + "value": 24294903732626645868215235778792757751152 + }, + "starkware.starknet.common.syscalls.GET_CALLER_ADDRESS_SELECTOR": { + "type": "const", + "value": 94901967781393078444254803017658102643 + }, + "starkware.starknet.common.syscalls.GET_CONTRACT_ADDRESS_SELECTOR": { + "type": "const", + "value": 6219495360805491471215297013070624192820083 + }, + "starkware.starknet.common.syscalls.GET_SEQUENCER_ADDRESS_SELECTOR": { + "type": "const", + "value": 1592190833581991703053805829594610833820054387 + }, + "starkware.starknet.common.syscalls.GET_TX_INFO_SELECTOR": { + "type": "const", + "value": 1317029390204112103023 + }, + "starkware.starknet.common.syscalls.GET_TX_SIGNATURE_SELECTOR": { + "type": "const", + "value": 1448089128652340074717162277007973 + }, + "starkware.starknet.common.syscalls.GetBlockNumber": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumber", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockNumberResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockNumberResponse", + "members": { + "block_number": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestamp": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestamp", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampRequest": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetBlockTimestampResponse": { + "full_name": "starkware.starknet.common.syscalls.GetBlockTimestampResponse", + "members": { + "block_timestamp": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetCallerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetCallerAddressResponse", + "members": { + "caller_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddress": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetContractAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetContractAddressResponse", + "members": { + "contract_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddress": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddress", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressRequest": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetSequencerAddressResponse": { + "full_name": "starkware.starknet.common.syscalls.GetSequencerAddressResponse", + "members": { + "sequencer_address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfo": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfo", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxInfoResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxInfoResponse", + "members": { + "tx_info": { + "cairo_type": "starkware.starknet.common.syscalls.TxInfo*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignature": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignature", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "offset": 1 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureRequest": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureRequest", + "members": { + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.GetTxSignatureResponse": { + "full_name": "starkware.starknet.common.syscalls.GetTxSignatureResponse", + "members": { + "signature": { + "cairo_type": "felt*", + "offset": 1 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.SEND_MESSAGE_TO_L1_SELECTOR": { + "type": "const", + "value": 433017908768303439907196859243777073 + }, + "starkware.starknet.common.syscalls.STORAGE_READ_SELECTOR": { + "type": "const", + "value": 100890693370601760042082660 + }, + "starkware.starknet.common.syscalls.STORAGE_WRITE_SELECTOR": { + "type": "const", + "value": 25828017502874050592466629733 + }, + "starkware.starknet.common.syscalls.SendMessageToL1SysCall": { + "full_name": "starkware.starknet.common.syscalls.SendMessageToL1SysCall", + "members": { + "payload_ptr": { + "cairo_type": "felt*", + "offset": 3 + }, + "payload_size": { + "cairo_type": "felt", + "offset": 2 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "to_address": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 4, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageRead": { + "full_name": "starkware.starknet.common.syscalls.StorageRead", + "members": { + "request": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadRequest", + "offset": 0 + }, + "response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadRequest": { + "full_name": "starkware.starknet.common.syscalls.StorageReadRequest", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageReadResponse": { + "full_name": "starkware.starknet.common.syscalls.StorageReadResponse", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.StorageWrite": { + "full_name": "starkware.starknet.common.syscalls.StorageWrite", + "members": { + "address": { + "cairo_type": "felt", + "offset": 1 + }, + "selector": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 2 + } + }, + "size": 3, + "type": "struct" + }, + "starkware.starknet.common.syscalls.TxInfo": { + "full_name": "starkware.starknet.common.syscalls.TxInfo", + "members": { + "account_contract_address": { + "cairo_type": "felt", + "offset": 1 + }, + "chain_id": { + "cairo_type": "felt", + "offset": 6 + }, + "max_fee": { + "cairo_type": "felt", + "offset": 2 + }, + "signature": { + "cairo_type": "felt*", + "offset": 4 + }, + "signature_len": { + "cairo_type": "felt", + "offset": 3 + }, + "transaction_hash": { + "cairo_type": "felt", + "offset": 5 + }, + "version": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 7, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read": { + "decorators": [], + "pc": 0, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_read.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_read.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.Return": { + "full_name": "starkware.starknet.common.syscalls.storage_read.Return", + "members": { + "value": { + "cairo_type": "felt", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_read.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_read.__temp0": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.syscalls.storage_read.__temp0", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 2, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read.address": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.syscalls.storage_read.address", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read.response": { + "cairo_type": "starkware.starknet.common.syscalls.StorageReadResponse", + "full_name": "starkware.starknet.common.syscalls.storage_read.response", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 4, + "value": "[cast([fp + (-4)] + 2, starkware.starknet.common.syscalls.StorageReadResponse*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read.syscall": { + "cairo_type": "starkware.starknet.common.syscalls.StorageRead", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast([fp + (-4)], starkware.starknet.common.syscalls.StorageRead*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_read.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_read.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 4, + "value": "cast([fp + (-4)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write": { + "decorators": [], + "pc": 8, + "type": "function" + }, + "starkware.starknet.common.syscalls.storage_write.Args": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Args", + "members": { + "address": { + "cairo_type": "felt", + "offset": 0 + }, + "value": { + "cairo_type": "felt", + "offset": 1 + } + }, + "size": 2, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.ImplicitArgs": { + "full_name": "starkware.starknet.common.syscalls.storage_write.ImplicitArgs", + "members": { + "syscall_ptr": { + "cairo_type": "felt*", + "offset": 0 + } + }, + "size": 1, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.Return": { + "full_name": "starkware.starknet.common.syscalls.storage_write.Return", + "members": {}, + "size": 0, + "type": "struct" + }, + "starkware.starknet.common.syscalls.storage_write.SIZEOF_LOCALS": { + "type": "const", + "value": 0 + }, + "starkware.starknet.common.syscalls.storage_write.__temp1": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.syscalls.storage_write.__temp1", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 10, + "value": "[cast(ap + (-1), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write.address": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.syscalls.storage_write.address", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-4), felt*)]" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write.syscall_ptr": { + "cairo_type": "felt*", + "full_name": "starkware.starknet.common.syscalls.storage_write.syscall_ptr", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 13, + "value": "cast([fp + (-5)] + 3, felt*)" + } + ], + "type": "reference" + }, + "starkware.starknet.common.syscalls.storage_write.value": { + "cairo_type": "felt", + "full_name": "starkware.starknet.common.syscalls.storage_write.value", + "references": [ + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-3), felt*)]" + } + ], + "type": "reference" + } + }, + "main_scope": "__main__", + "prime": "0x800000000000011000000000000000000000000000000000000000000000001", + "reference_manager": { + "references": [ + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast(fp + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 0 + }, + "pc": 0, + "value": "[cast([fp + (-4)], starkware.starknet.common.syscalls.StorageRead*)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 2, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 4, + "value": "[cast([fp + (-4)] + 2, starkware.starknet.common.syscalls.StorageReadResponse*)]" + }, + { + "ap_tracking_data": { + "group": 0, + "offset": 1 + }, + "pc": 4, + "value": "cast([fp + (-4)] + 3, felt*)" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-4), felt*)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 0 + }, + "pc": 8, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 10, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 1, + "offset": 1 + }, + "pc": 13, + "value": "cast([fp + (-5)] + 3, felt*)" + }, + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 16, + "value": "[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 16, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 2, + "offset": 0 + }, + "pc": 16, + "value": "cast(916907772491729262376534102982219947830828984996257231353398618781993312401, felt)" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 21, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 21, + "value": "[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 0 + }, + "pc": 21, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 7 + }, + "pc": 25, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 7 + }, + "pc": 25, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 7 + }, + "pc": 25, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 14 + }, + "pc": 29, + "value": "[cast(ap + (-2), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 14 + }, + "pc": 29, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 15 + }, + "pc": 30, + "value": "[cast(ap + (-1), felt**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 16 + }, + "pc": 31, + "value": "[cast(ap + (-1), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 17 + }, + "pc": 32, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 3, + "offset": 18 + }, + "pc": 33, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-6), felt**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 0 + }, + "pc": 34, + "value": "[cast(fp + (-4), felt*)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 7 + }, + "pc": 38, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 7 + }, + "pc": 38, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 7 + }, + "pc": 38, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 4, + "offset": 14 + }, + "pc": 43, + "value": "[cast(ap + (-1), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-6), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-5), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 0 + }, + "pc": 46, + "value": "[cast(fp + (-4), felt*)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 23 + }, + "pc": 51, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 45 + }, + "pc": 57, + "value": "[cast(ap + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 45 + }, + "pc": 57, + "value": "[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 5, + "offset": 45 + }, + "pc": 57, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-5)], felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-5)] + 2, felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "[cast([fp + (-3)], felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "cast([fp + (-3)] + 1, felt*)" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 0 + }, + "pc": 58, + "value": "cast([fp + (-3)] + 1 - [fp + (-3)], felt)" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 1 + }, + "pc": 60, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + (-2), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 52 + }, + "pc": 67, + "value": "[cast(ap + 0, __main__.increase_balance.Return*)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 53 + }, + "pc": 69, + "value": "[cast(ap + (-1), felt**)]" + }, + { + "ap_tracking_data": { + "group": 6, + "offset": 53 + }, + "pc": 69, + "value": "cast(0, felt)" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 76, + "value": "[cast(fp + (-5), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 76, + "value": "[cast(fp + (-4), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 0 + }, + "pc": 76, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 7, + "offset": 23 + }, + "pc": 81, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 82, + "value": "[cast(fp + (-4), __main__.get_balance.Return*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 0 + }, + "pc": 82, + "value": "[cast(fp + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 84, + "value": "[cast(fp, felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 84, + "value": "[cast(fp, felt**)]" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 1 + }, + "pc": 85, + "value": "cast([fp] + 1, felt*)" + }, + { + "ap_tracking_data": { + "group": 8, + "offset": 2 + }, + "pc": 87, + "value": "[cast(ap + (-1), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast([fp + (-5)], felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast([fp + (-5)] + 1, starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast([fp + (-5)] + 2, felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "[cast(fp + (-3), felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 0 + }, + "pc": 91, + "value": "cast([fp + (-3)] - [fp + (-3)], felt)" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-4), felt**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-3), starkware.cairo.common.cairo_builtins.HashBuiltin**)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 28 + }, + "pc": 97, + "value": "[cast(ap + (-1), __main__.get_balance.Return*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 36 + }, + "pc": 100, + "value": "[cast(ap + (-3), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 36 + }, + "pc": 100, + "value": "[cast(ap + (-2), felt*)]" + }, + { + "ap_tracking_data": { + "group": 9, + "offset": 36 + }, + "pc": 100, + "value": "[cast(ap + (-1), felt**)]" + } + ] + } + } +} diff --git a/packages-ts/starknet-gauntlet/test/commands/execute.test.ts b/packages-ts/starknet-gauntlet/test/commands/execute.test.ts new file mode 100644 index 0000000..75bd7b3 --- /dev/null +++ b/packages-ts/starknet-gauntlet/test/commands/execute.test.ts @@ -0,0 +1,115 @@ +import { ExecuteCommandConfig, makeExecuteCommand } from '../../src/index' +import { + devnetAccount0Address, + devnetPrivateKey, + loadExampleContract, + registerExecuteCommand, +} from '../utils' +import { IntegratedDevnet, startNetwork } from '../utils/network' + +const TIMEOUT = 100000 + +let account: string = devnetAccount0Address +let privateKey: string = devnetPrivateKey + +describe('Execute Command', () => { + type UserInput = { + a: string + b: number + } + + type ContractInput = [string, number] + + const makeUserInput = async (flags, args): Promise => { + return { + a: flags.a, + b: Number(flags.b), + } + } + + const makeContractInput = async (userInput: UserInput): Promise => { + return [userInput.a, userInput.b] + } + + const simpleCommandConfig: ExecuteCommandConfig = { + contractId: '', + category: 'example', + action: 'action', + ux: { + description: '', + examples: [], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: loadExampleContract, + } + + const commandConfigWithSuffixes = { + ...simpleCommandConfig, + ...{ suffixes: ['send', 'bob'] }, + } + + const command = registerExecuteCommand(makeExecuteCommand(simpleCommandConfig)) + const commandWithSuffixes = registerExecuteCommand(makeExecuteCommand(commandConfigWithSuffixes)) + + it('Command ID generation', async () => { + expect(command.id).toEqual('example:action') + expect(commandWithSuffixes.id).toEqual('example:action:send:bob') + }) + + it('Command input creation', async () => { + const commandInstance = await command.create({ a: 'a', b: '20' }, []) + expect(commandInstance.input.user).toEqual({ a: 'a', b: 20 }) + expect(commandInstance.input.contract).toEqual(['a', 20]) + }) +}) + +describe('Execute with network', () => { + let network: IntegratedDevnet + let contractAddress: string + + beforeAll(async () => { + network = await startNetwork({ seed: 0 }) + }, 15000) + + it( + 'Command deploy execution', + async () => { + const makeUserInput = async (flags, args) => { + return + } + + const makeContractInput = async (userInput) => { + return {} + } + + const deployCommandConfig: ExecuteCommandConfig = { + contractId: '', + category: 'example', + action: 'deploy', + ux: { + description: '', + examples: [], + }, + makeUserInput, + makeContractInput, + validations: [], + loadContract: loadExampleContract, + } + + const command = registerExecuteCommand(makeExecuteCommand(deployCommandConfig)) + + const commandInstance = await command.create({}, []) + const report = await commandInstance.execute() + expect(report.responses[0].tx.status).toEqual('ACCEPTED') + + contractAddress = report.responses[0].contract + }, + TIMEOUT, + ) + + afterAll(() => { + network.stop() + }) +}) diff --git a/packages-ts/starknet-gauntlet/test/utils/index.ts b/packages-ts/starknet-gauntlet/test/utils/index.ts new file mode 100644 index 0000000..5dde7dc --- /dev/null +++ b/packages-ts/starknet-gauntlet/test/utils/index.ts @@ -0,0 +1,83 @@ +import { CompiledContract, json } from 'starknet' +import fs from 'fs' +import { logger, prompt } from '@pluginv3.0/gauntlet-core/dist/utils' +import { + CommandCtor, + Dependencies, + ExecuteCommandInstance, + InspectCommandInstance, + makeProvider, + makeWallet, +} from '../../src/index' + +export { startNetwork, IntegratedDevnet } from './network' + +export const loadContract = (name: string): CompiledContract => { + return json.parse(fs.readFileSync(`${__dirname}/../__mocks__/${name}.json`).toString('ascii')) +} + +export const loadExampleContract = () => loadContract('example') + +export const noop = () => {} + +export const noopLogger: typeof logger = { + table: noop, + log: noop, + info: noop, + warn: noop, + success: noop, + error: noop, + loading: noop, + line: noop, + style: () => '', + debug: noop, + time: noop, +} + +export const noopPrompt: typeof prompt = async () => {} + +export const TIMEOUT = 200000 +export const LOCAL_URL = 'http://127.0.0.1:5050/' +export const devnetPrivateKey = '0xe3e70682c2094cac629f6fbed82c07cd' +export const devnetAccount0Address = + '0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a' +// export const devnetKeyPair = ec.getKeyPair(devnetPrivateKey); + +export const registerExecuteCommand = ( + registerCommand: (deps: Dependencies) => CommandCtor>, +) => { + const deps: Dependencies = { + logger: noopLogger, + prompt: noopPrompt, + makeEnv: (flags) => { + return { + providerUrl: LOCAL_URL, + pk: (flags.pk as string) || devnetPrivateKey, + account: (flags.account as string) || devnetAccount0Address, + } + }, + makeProvider: makeProvider, + makeWallet: makeWallet, + } + return registerCommand(deps) +} + +export const registerInspectCommand = ( + registerCommand: ( + deps: Omit, + ) => CommandCtor>, +) => { + const deps: Omit = { + logger: noopLogger, + prompt: noopPrompt, + makeEnv: (flags) => { + return { + providerUrl: LOCAL_URL, + pk: (flags.pk as string) || devnetPrivateKey, + account: (flags.account as string) || devnetAccount0Address, + } + }, + makeProvider: makeProvider, + } + return registerCommand(deps) +} diff --git a/packages-ts/starknet-gauntlet/test/utils/network.ts b/packages-ts/starknet-gauntlet/test/utils/network.ts new file mode 100644 index 0000000..16bd13c --- /dev/null +++ b/packages-ts/starknet-gauntlet/test/utils/network.ts @@ -0,0 +1,76 @@ +import { ChildProcess, spawn } from 'child_process' + +export abstract class IntegratedDevnet { + protected childProcess: ChildProcess + + constructor(protected port: string) { + IntegratedDevnet.cleanupFns.push(this.cleanup.bind(this)) + } + + protected static cleanupFns: Array<() => void> = [] + + public static cleanAll(): void { + this.cleanupFns.forEach((fn) => fn()) + } + + protected abstract spawnChildProcess(): Promise + + protected abstract cleanup(): void + + public async start(): Promise { + this.childProcess = await this.spawnChildProcess() + + return new Promise((resolve, reject) => { + setTimeout(resolve, 4000) + + this.childProcess.on('error', (error) => { + reject(error) + }) + }) + } + + public stop() { + if (!this.childProcess) { + return + } + + this.cleanup() + } +} + +class VenvDevnet extends IntegratedDevnet { + private command: string + private opts: any + + constructor(port: string, opts: any) { + super(port) + + this.opts = opts + this.command = 'starknet-devnet' + } + + protected async spawnChildProcess(): Promise { + let args = ['--port', this.port, '--gas-price', '1', '--lite-mode'] + if (this.opts?.seed) { + args.push('--seed', this.opts.seed.toString()) + } else { + args.push('--seed', '0') + } + return spawn(this.command, args) + } + + protected cleanup(): void { + this.childProcess?.kill() + } +} + +export const startNetwork = async (opts?: {}): Promise => { + const devnet = new VenvDevnet('5050', opts) + + await devnet.start() + + // Starting to poll devnet too soon can result in ENOENT + await new Promise((f) => setTimeout(f, 2000)) + + return devnet +} diff --git a/packages-ts/starknet-gauntlet/tsconfig.json b/packages-ts/starknet-gauntlet/tsconfig.json new file mode 100644 index 0000000..2c84c1f --- /dev/null +++ b/packages-ts/starknet-gauntlet/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/packages-ts/starknet/.gitignore b/packages-ts/starknet/.gitignore new file mode 100644 index 0000000..6cb6d20 --- /dev/null +++ b/packages-ts/starknet/.gitignore @@ -0,0 +1,3 @@ +cache/ +node_modules/ +starknet-artifacts/ diff --git a/packages-ts/starknet/hardhat.config.ts b/packages-ts/starknet/hardhat.config.ts new file mode 100644 index 0000000..7e851a7 --- /dev/null +++ b/packages-ts/starknet/hardhat.config.ts @@ -0,0 +1,26 @@ +import { HardhatUserConfig } from 'hardhat/types' +import '@shardlabs/starknet-hardhat-plugin' + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +const config: HardhatUserConfig = { + starknet: { + venv: 'active', + network: 'devnet', + wallets: { + OpenZeppelin: { + accountName: 'OpenZeppelin', + modulePath: 'starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount', + accountPath: '~/.starknet_accounts', + }, + }, + }, + networks: { + devnet: { + url: 'http://127.0.0.1:5050/', + }, + }, +} + +export default config diff --git a/packages-ts/starknet/package.json b/packages-ts/starknet/package.json new file mode 100644 index 0000000..3a093b9 --- /dev/null +++ b/packages-ts/starknet/package.json @@ -0,0 +1,29 @@ +{ + "name": "@pluginv3.0/starknet", + "version": "1.0.0", + "description": "Starknet test utilities", + "keywords": [ + "typescript", + "cli" + ], + "main": "./dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "!dist/**/*.test.js" + ], + "scripts": { + "lint": "tsc", + "test": "npx hardhat --network localhost test", + "gauntlet": "ts-node ./src/index.ts", + "format": "yarn prettier --write ./src", + "format:check": "yarn prettier --check ./src", + "clean": "rm -rf ./dist/ ./bin/", + "build": "yarn clean && tsc -b", + "bundle": "yarn build && pkg ." + }, + "devDependencies": { + "@shardlabs/starknet-hardhat-plugin": "^0.8.0-alpha.0", + "hardhat": "^2.10.2" + } +} diff --git a/packages-ts/starknet/src/account.ts b/packages-ts/starknet/src/account.ts new file mode 100644 index 0000000..e0d34c4 --- /dev/null +++ b/packages-ts/starknet/src/account.ts @@ -0,0 +1,100 @@ +import { Account, SequencerProvider, ec, uint256 } from 'starknet' + +export const ERC20_ADDRESS = '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7' + +export const DEVNET_URL = 'http://127.0.0.1:5050' +const DEVNET_NAME = 'devnet' +// This function loads options from the environment. +// It returns options for Devnet as default when nothing is configured in the environment. +export const makeFunderOptsFromEnv = () => { + const network = process.env.NETWORK || DEVNET_NAME + const gateway = process.env.NODE_URL || DEVNET_URL + const accountAddr = process.env.ACCOUNT?.toLowerCase() + const keyPair = ec.starkCurve.utils.randomPrivateKey() + + return { network, gateway, accountAddr, keyPair } +} + +interface FundAccounts { + account: string + amount: number +} + +interface FunderOptions { + network?: string + gateway?: string + accountAddr?: string + keyPair?: Uint8Array +} + +// Define the Strategy to use depending on the network. +export class Funder { + private opts: FunderOptions + private strategy: IFundingStrategy + + constructor(opts: FunderOptions) { + this.opts = opts + if (this.opts.network === DEVNET_NAME) { + this.strategy = new DevnetFundingStrategy() + return + } + this.strategy = new AllowanceFundingStrategy() + } + + // This function adds some funds to pre-deployed account that we are using in our test. + public async fund(accounts: FundAccounts[]) { + await this.strategy.fund(accounts, this.opts) + } +} + +interface IFundingStrategy { + fund(accounts: FundAccounts[], opts: FunderOptions): Promise +} + +// Fund the Account on Devnet +class DevnetFundingStrategy implements IFundingStrategy { + public async fund(accounts: FundAccounts[], opts: FunderOptions) { + accounts.forEach(async (account) => { + const body = { + address: account.account, + amount: account.amount, + lite: true, + } + await fetch(`${opts.gateway}/mint`, { + method: 'post', + body: JSON.stringify(body), + headers: { 'Content-Type': 'application/json' }, + }) + }) + } +} + +// Fund the Account on Testnet +class AllowanceFundingStrategy implements IFundingStrategy { + public async fund(accounts: FundAccounts[], opts: FunderOptions) { + const provider = new SequencerProvider({ + baseUrl: 'https://alpha4.starknet.io', + }) + + const operator = new Account(provider, opts.accountAddr, opts.keyPair) + + for (const account of accounts) { + const data = [ + account.account, + uint256.bnToUint256(account.amount).low.toString(), + uint256.bnToUint256(account.amount).high.toString(), + ] + const nonce = await operator.getNonce() + const hash = await operator.execute( + { + contractAddress: ERC20_ADDRESS, + entrypoint: 'transfer', + calldata: data, + }, + undefined, + { nonce }, + ) + await provider.waitForTransaction(hash.transaction_hash) + } + } +} diff --git a/packages-ts/starknet/src/index.ts b/packages-ts/starknet/src/index.ts new file mode 100644 index 0000000..c901699 --- /dev/null +++ b/packages-ts/starknet/src/index.ts @@ -0,0 +1,2 @@ +export * from './utils' +export * as account from './account' diff --git a/packages-ts/starknet/src/utils.ts b/packages-ts/starknet/src/utils.ts new file mode 100644 index 0000000..1e6890f --- /dev/null +++ b/packages-ts/starknet/src/utils.ts @@ -0,0 +1,68 @@ +import { constants, encode, num } from 'starknet' +import { expect } from 'chai' +import { artifacts, network } from 'hardhat' + +// This function adds the build info to the test network so that the network knows +// how to handle custom errors. It is automatically done when testing +// against the default hardhat network. +export const addCompilationToNetwork = async (fullyQualifiedName: string) => { + if (network.name !== 'hardhat') { + // This is so that the network can know about custom errors. + // Running against the provided hardhat node does this automatically. + + const buildInfo = await artifacts.getBuildInfo(fullyQualifiedName) + if (!buildInfo) { + throw Error('Cannot find build info') + } + const { solcVersion, input, output } = buildInfo + console.log('Sending compilation result for StarknetValidator test') + await network.provider.request({ + method: 'hardhat_addCompilationResult', + params: [solcVersion, input, output], + }) + console.log('Successfully sent compilation result for StarknetValidator test') + } +} + +export const expectInvokeError = async (invoke: Promise, expected?: string) => { + try { + await invoke + } catch (err: any) { + expectInvokeErrorMsg(err?.message, expected) + return // force + } + expect.fail("Unexpected! Invoke didn't error!?") +} + +export const expectInvokeErrorMsg = (actual: string, expected?: string) => { + // Match transaction error + expect(actual).to.deep.contain('TRANSACTION_FAILED') + // Match specific error + if (expected) expectSpecificMsg(actual, expected) +} + +export const expectCallError = async (call: Promise, expected?: string) => { + try { + await call + } catch (err: any) { + expectCallErrorMsg(err?.message, expected) + return // force + } + expect.fail("Unexpected! Call didn't error!?") +} + +export const expectCallErrorMsg = (actual: string, expected?: string) => { + // Match call error + expect(actual).to.deep.contain('Could not perform call') + // Match specific error + if (expected) expectSpecificMsg(actual, expected) +} + +export const expectSpecificMsg = (actual: string, expected: string) => { + // Match specific error + const matches = actual.match(/Error message: (.+?)\n/g) + // Joint matches should include the expected, or fail + if (matches && matches.length > 0) { + expect(matches.join()).to.include(expected) + } else expect.fail(`\nActual: ${actual}\n\nExpected: ${expected}`) +} diff --git a/packages-ts/starknet/test/fundAccount.test.ts b/packages-ts/starknet/test/fundAccount.test.ts new file mode 100644 index 0000000..aef762e --- /dev/null +++ b/packages-ts/starknet/test/fundAccount.test.ts @@ -0,0 +1,73 @@ +import { assert } from 'chai' +import { account } from '@pluginv3.0/starknet' +import { Account, ec, SequencerProvider, stark } from 'starknet' +import { DEVNET_URL, ERC20_ADDRESS } from '../src/account' + +describe('fundAccount', function () { + this.timeout(900_000) + let alice: Account + let bob: Account + let provider: SequencerProvider + + const opts = account.makeFunderOptsFromEnv() + const funder = new account.Funder(opts) + + before(async function () { + const gateway_url = process.env.NODE_URL || DEVNET_URL + provider = new SequencerProvider({ baseUrl: gateway_url }) + + const aliceStarkKeyPair = ec.starkCurve.utils.randomPrivateKey() + const bobStarkKeyPair = ec.starkCurve.utils.randomPrivateKey() + + const default_alice_address = stark.randomAddress() + const default_bob_address = stark.randomAddress() + + alice = new Account(provider, default_alice_address, aliceStarkKeyPair) + bob = new Account(provider, default_bob_address, bobStarkKeyPair) + + await funder.fund([ + { account: alice.address, amount: 5000 }, + { account: bob.address, amount: 8000 }, + ]) + }) + + it('should have fund alice', async () => { + const balance = await alice.callContract({ + contractAddress: ERC20_ADDRESS, + entrypoint: 'balanceOf', + calldata: [BigInt(alice.address).toString(10)], + }) + assert.deepEqual(balance.result, ['0x1388', '0x0']) + }) + + it('should have fund bob', async () => { + const balance = await bob.callContract({ + contractAddress: ERC20_ADDRESS, + entrypoint: 'balanceOf', + calldata: [BigInt(bob.address).toString(10)], + }) + assert.deepEqual(balance.result, ['0x1f40', '0x0']) + }) + + it("should increament alice's fees", async () => { + await funder.fund([{ account: alice.address, amount: 100 }]) + + const balance = await alice.callContract({ + contractAddress: ERC20_ADDRESS, + entrypoint: 'balanceOf', + calldata: [BigInt(alice.address).toString(10)], + }) + assert.deepEqual(balance.result, ['0x13ec', '0x0']) + }) + + it("should increament bob's fees", async () => { + await funder.fund([{ account: bob.address, amount: 1000 }]) + + const balance = await bob.callContract({ + contractAddress: ERC20_ADDRESS, + entrypoint: 'balanceOf', + calldata: [BigInt(bob.address).toString(10)], + }) + assert.deepEqual(balance.result, ['0x2328', '0x0']) + }) +}) diff --git a/packages-ts/starknet/tsconfig.json b/packages-ts/starknet/tsconfig.json new file mode 100644 index 0000000..2b6853d --- /dev/null +++ b/packages-ts/starknet/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "dist", + "**/*.spec.ts", + "**/*.test.ts" + ], +} diff --git a/relayer/go.mod b/relayer/go.mod new file mode 100644 index 0000000..dc39fa8 --- /dev/null +++ b/relayer/go.mod @@ -0,0 +1,51 @@ +module github.com/goplugin/plugin-starknet/relayer + +go 1.20 + +require ( + github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 + github.com/pkg/errors v0.9.1 + github.com/smartcontractkit/caigo v0.0.0-20230508053235-41120ca1f9f3 + github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82 + github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc + github.com/stretchr/testify v1.8.2 + golang.org/x/exp v0.0.0-20230307190834-24139beb5833 +) + +require ( + github.com/benbjohnson/clock v1.3.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/ethereum/go-ethereum v1.11.5 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/gogo/protobuf v1.3.3 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/satori/go.uuid v1.2.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.5.0 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/sys v0.7.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/relayer/go.sum b/relayer/go.sum new file mode 100644 index 0000000..f884390 --- /dev/null +++ b/relayer/go.sum @@ -0,0 +1,214 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac h1:TQ2m26VW06Df1P82Ed/jZhBtf13pReWyl2XQ8hy+J08= +github.com/NethermindEth/juno v0.0.0-20220630151419-cbd368b222ac/go.mod h1:FTk2+xybtQe5X+oNFx+a0n5EeZMD9Nc+LCH4fxFwrEE= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= +github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.11.5 h1:3M1uan+LAUvdn+7wCEFrcMM4LJTeuxDrPTg/f31a5QQ= +github.com/ethereum/go-ethereum v1.11.5/go.mod h1:it7x0DWnTDMfVFdXcU6Ti4KEFQynLHVRarcSlPr0HBo= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/smartcontractkit/caigo v0.0.0-20230508053235-41120ca1f9f3 h1:6RsuA0LBbC/6DgTYzg659Pw7GKktubj1GzTcB/VNC44= +github.com/smartcontractkit/caigo v0.0.0-20230508053235-41120ca1f9f3/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= +github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82 h1:FX7LW/czuotFwzfK3UavL7HkKQv6fn/5wzcZASdKWQ0= +github.com/goplugin/plugin-relay v0.1.7-0.20230422214339-5fee8d7f3f82/go.mod h1:3E3PXaMEl2gADk/DTkbOxsvtpDcJ5ZSyW+vt0TjsEH0= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc h1:aSCDAai0Dmbhp/KHTtJnC/EJcaEz4CAO80SKRzRZiQA= +github.com/goplugin/plugin-libocr v0.0.0-20230413082317-9561d14087cc/go.mod h1:5JnCHuYgmIP9ZyXzgAfI5Iwu0WxBtBKp+ApeT5o1Cjw= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A= +github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/relayer/package.json b/relayer/package.json new file mode 100644 index 0000000..aa6b1e2 --- /dev/null +++ b/relayer/package.json @@ -0,0 +1,7 @@ +{ + "name": "@pluginv3.0/starknet-relayer", + "version": "0.0.1", + "license": "MIT", + "dependencies": {}, + "devDependencies": {} +} diff --git a/relayer/pkg/plugin/chain/chain.go b/relayer/pkg/plugin/chain/chain.go new file mode 100644 index 0000000..a8c4f38 --- /dev/null +++ b/relayer/pkg/plugin/chain/chain.go @@ -0,0 +1,23 @@ +package starknet + +import ( + "github.com/goplugin/plugin-relay/pkg/types" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/config" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/txm" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + // unused module to keep in go.mod and prevent ambiguous import + _ "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +type ChainSet = types.ChainSet[string, Chain] + +type Chain interface { + types.ChainService + + Config() config.Config + + TxManager() txm.TxManager + Reader() (starknet.Reader, error) +} diff --git a/relayer/pkg/plugin/config/config.go b/relayer/pkg/plugin/config/config.go new file mode 100644 index 0000000..f3092d3 --- /dev/null +++ b/relayer/pkg/plugin/config/config.go @@ -0,0 +1,78 @@ +package config + +import ( + "time" + + "github.com/goplugin/plugin-relay/pkg/utils" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/txm" +) + +var DefaultConfigSet = ConfigSet{ + OCR2CachePollPeriod: 5 * time.Second, + OCR2CacheTTL: time.Minute, + RequestTimeout: 10 * time.Second, + TxTimeout: time.Minute, + TxSendFrequency: 5 * time.Second, + TxMaxBatchSize: 100, +} + +type ConfigSet struct { + OCR2CachePollPeriod time.Duration + OCR2CacheTTL time.Duration + + // client config + RequestTimeout time.Duration + + // txm config + TxTimeout time.Duration + TxSendFrequency time.Duration + TxMaxBatchSize int +} + +type Config interface { + txm.Config // txm config + + // ocr2 config + ocr2.Config + + // client config + RequestTimeout() time.Duration +} + +type Chain struct { + OCR2CachePollPeriod *utils.Duration + OCR2CacheTTL *utils.Duration + RequestTimeout *utils.Duration + TxTimeout *utils.Duration + TxSendFrequency *utils.Duration + TxMaxBatchSize *int64 +} + +func (c *Chain) SetDefaults() { + if c.OCR2CachePollPeriod == nil { + c.OCR2CachePollPeriod = utils.MustNewDuration(DefaultConfigSet.OCR2CachePollPeriod) + } + if c.OCR2CacheTTL == nil { + c.OCR2CacheTTL = utils.MustNewDuration(DefaultConfigSet.OCR2CacheTTL) + } + if c.RequestTimeout == nil { + c.RequestTimeout = utils.MustNewDuration(DefaultConfigSet.RequestTimeout) + } + if c.TxTimeout == nil { + c.TxTimeout = utils.MustNewDuration(DefaultConfigSet.TxTimeout) + } + if c.TxSendFrequency == nil { + c.TxSendFrequency = utils.MustNewDuration(DefaultConfigSet.TxSendFrequency) + } + if c.TxMaxBatchSize == nil { + i := int64(DefaultConfigSet.TxMaxBatchSize) + c.TxMaxBatchSize = &i + } +} + +type Node struct { + Name *string + URL *utils.URL +} diff --git a/relayer/pkg/plugin/db/db.go b/relayer/pkg/plugin/db/db.go new file mode 100644 index 0000000..e82f618 --- /dev/null +++ b/relayer/pkg/plugin/db/db.go @@ -0,0 +1,14 @@ +package db + +import ( + "time" +) + +type Node struct { + ID int32 + Name string + ChainID string `db:"starknet_chain_id"` + URL string + CreatedAt time.Time + UpdatedAt time.Time +} diff --git a/relayer/pkg/plugin/keys/key.go b/relayer/pkg/plugin/keys/key.go new file mode 100644 index 0000000..456dae0 --- /dev/null +++ b/relayer/pkg/plugin/keys/key.go @@ -0,0 +1,104 @@ +package keys + +import ( + crypto_rand "crypto/rand" + "encoding/hex" + "fmt" + "io" + "math/big" + + "github.com/smartcontractkit/caigo" +) + +// Raw represents the Stark private key +type Raw []byte + +// Key gets the Key +func (raw Raw) Key() Key { + k := Key{} + var err error + + k.priv = new(big.Int).SetBytes(raw) + k.pub.X, k.pub.Y, err = caigo.Curve.PrivateToPoint(k.priv) + if err != nil { + panic(err) // key not generated + } + return k +} + +// String returns description +func (raw Raw) String() string { + return "" +} + +// GoString wraps String() +func (raw Raw) GoString() string { + return raw.String() +} + +var _ fmt.GoStringer = &Key{} + +type PublicKey struct { + X, Y *big.Int +} + +// Key represents Starknet key +type Key struct { + priv *big.Int + pub PublicKey +} + +// New creates new Key +func New() (Key, error) { + return newFrom(crypto_rand.Reader) +} + +// MustNewInsecure return Key if no error +func MustNewInsecure(reader io.Reader) Key { + key, err := newFrom(reader) + if err != nil { + panic(err) + } + return key +} + +func newFrom(reader io.Reader) (Key, error) { + return GenerateKey(reader) +} + +// ID gets Key ID +func (key Key) ID() string { + return key.StarkKeyStr() +} + +// StarkKeyStr is the starknet public key associated to the private key +// it is the X component of the ECDSA pubkey and used in the deployment of the account contract +// this func is used in exporting it via CLI and API +func (key Key) StarkKeyStr() string { + return "0x" + hex.EncodeToString(PubKeyToStarkKey(key.pub)) +} + +// Raw from private key +func (key Key) Raw() Raw { + return key.priv.Bytes() +} + +// String is the print-friendly format of the Key +func (key Key) String() string { + return fmt.Sprintf("StarknetKey{PrivateKey: , StarkKey: %s}", key.StarkKeyStr()) +} + +// GoString wraps String() +func (key Key) GoString() string { + return key.String() +} + +// ToPrivKey returns the key usable for signing. +func (key Key) ToPrivKey() *big.Int { + return key.priv +} + +// PublicKey copies public key object +func (key Key) PublicKey() PublicKey { + return key.pub +} diff --git a/relayer/pkg/plugin/keys/keystore.go b/relayer/pkg/plugin/keys/keystore.go new file mode 100644 index 0000000..4990baf --- /dev/null +++ b/relayer/pkg/plugin/keys/keystore.go @@ -0,0 +1,7 @@ +package keys + +//go:generate mockery --name Keystore --output ./mocks/ --case=underscore --filename keystore.go + +type Keystore interface { + Get(id string) (Key, error) +} diff --git a/relayer/pkg/plugin/keys/mocks/keystore.go b/relayer/pkg/plugin/keys/mocks/keystore.go new file mode 100644 index 0000000..5577b59 --- /dev/null +++ b/relayer/pkg/plugin/keys/mocks/keystore.go @@ -0,0 +1,50 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + + keys "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/keys" +) + +// Keystore is an autogenerated mock type for the Keystore type +type Keystore struct { + mock.Mock +} + +// Get provides a mock function with given fields: id +func (_m *Keystore) Get(id string) (keys.Key, error) { + ret := _m.Called(id) + + var r0 keys.Key + if rf, ok := ret.Get(0).(func(string) keys.Key); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(keys.Key) + } + + var r1 error + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewKeystore interface { + mock.TestingT + Cleanup(func()) +} + +// NewKeystore creates a new instance of Keystore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewKeystore(t mockConstructorTestingTNewKeystore) *Keystore { + mock := &Keystore{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/relayer/pkg/plugin/keys/ocr2key.go b/relayer/pkg/plugin/keys/ocr2key.go new file mode 100644 index 0000000..a29a196 --- /dev/null +++ b/relayer/pkg/plugin/keys/ocr2key.go @@ -0,0 +1,143 @@ +package keys + +import ( + "bytes" + "io" + "math/big" + + "github.com/NethermindEth/juno/pkg/crypto/pedersen" + "github.com/smartcontractkit/caigo" + "github.com/pkg/errors" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/medianreport" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + ocrtypes "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +var _ ocrtypes.OnchainKeyring = &OCR2Key{} + +type OCR2Key struct { + Key +} + +func NewOCR2Key(material io.Reader) (*OCR2Key, error) { + k, err := GenerateKey(material) + + return &OCR2Key{k}, err +} + +func (sk *OCR2Key) PublicKey() ocrtypes.OnchainPublicKey { + return PubKeyToStarkKey(sk.pub) +} + +func ReportToSigData(reportCtx ocrtypes.ReportContext, report ocrtypes.Report) (*big.Int, error) { + var dataArray []*big.Int + + rawReportContext := medianreport.RawReportContext(reportCtx) + dataArray = append(dataArray, new(big.Int).SetBytes(rawReportContext[0][:])) + dataArray = append(dataArray, new(big.Int).SetBytes(rawReportContext[1][:])) + dataArray = append(dataArray, new(big.Int).SetBytes(rawReportContext[2][:])) + + // split report into separate felts for hashing + splitReport, err := medianreport.SplitReport(report) + if err != nil { + return &big.Int{}, err + } + for i := 0; i < len(splitReport); i++ { + dataArray = append(dataArray, new(big.Int).SetBytes(splitReport[i])) + } + + hash := pedersen.ArrayDigest(dataArray...) + return hash, nil +} + +func (sk *OCR2Key) Sign(reportCtx ocrtypes.ReportContext, report ocrtypes.Report) ([]byte, error) { + hash, err := ReportToSigData(reportCtx, report) + if err != nil { + return []byte{}, err + } + + r, s, err := caigo.Curve.Sign(hash, sk.priv) + if err != nil { + return []byte{}, err + } + + // enforce s <= N/2 to prevent signature malleability + if s.Cmp(new(big.Int).Rsh(caigo.Curve.N, 1)) > 0 { + s.Sub(caigo.Curve.N, s) + } + + // encoding: public key (32 bytes) + r (32 bytes) + s (32 bytes) + buff := bytes.NewBuffer([]byte(sk.PublicKey())) + if _, err := buff.Write(starknet.PadBytes(r.Bytes(), byteLen)); err != nil { + return []byte{}, err + } + if _, err := buff.Write(starknet.PadBytes(s.Bytes(), byteLen)); err != nil { + return []byte{}, err + } + + out := buff.Bytes() + if len(out) != sk.MaxSignatureLength() { + return []byte{}, errors.Errorf("unexpected signature size, got %d want %d", len(out), sk.MaxSignatureLength()) + } + return out, nil +} + +func (sk *OCR2Key) Verify(publicKey ocrtypes.OnchainPublicKey, reportCtx ocrtypes.ReportContext, report ocrtypes.Report, signature []byte) bool { + // check valid signature length + if len(signature) != sk.MaxSignatureLength() { + return false + } + + // convert OnchainPublicKey (starkkey) into ecdsa public keys (prepend 2 or 3 to indicate +/- Y coord) + var keys [2]PublicKey + keys[0].X = new(big.Int).SetBytes(publicKey) + keys[0].Y = caigo.Curve.GetYCoordinate(keys[0].X) + + // When there is no point with the provided x-coordinate, the GetYCoordinate function returns the nil value. + if keys[0].Y == nil { + return false + } + + keys[1].X = keys[0].X + keys[1].Y = new(big.Int).Mul(keys[0].Y, big.NewInt(-1)) + + hash, err := ReportToSigData(reportCtx, report) + if err != nil { + return false + } + + r := new(big.Int).SetBytes(signature[32:64]) + s := new(big.Int).SetBytes(signature[64:]) + + // Only allow canonical signatures to avoid signature malleability. Verify s <= N/2 + if s.Cmp(new(big.Int).Rsh(caigo.Curve.N, 1)) == 1 { + return false + } + + return caigo.Curve.Verify(hash, r, s, keys[0].X, keys[0].Y) || caigo.Curve.Verify(hash, r, s, keys[1].X, keys[1].Y) +} + +func (sk *OCR2Key) MaxSignatureLength() int { + return 32 + 32 + 32 // publickey + r + s +} + +func (sk *OCR2Key) Marshal() ([]byte, error) { + return starknet.PadBytes(sk.priv.Bytes(), sk.privateKeyLen()), nil +} + +func (sk *OCR2Key) privateKeyLen() int { + // https://github.com/NethermindEth/juno/blob/3e71279632d82689e5af03e26693ca5c58a2376e/pkg/crypto/weierstrass/weierstrass.go#L377 + return 32 +} + +func (sk *OCR2Key) Unmarshal(in []byte) error { + // enforce byte length + if len(in) != sk.privateKeyLen() { + return errors.Errorf("unexpected seed size, got %d want %d", len(in), sk.privateKeyLen()) + } + + sk.Key = Raw(in).Key() + return nil +} diff --git a/relayer/pkg/plugin/keys/ocr2key_test.go b/relayer/pkg/plugin/keys/ocr2key_test.go new file mode 100644 index 0000000..42cd869 --- /dev/null +++ b/relayer/pkg/plugin/keys/ocr2key_test.go @@ -0,0 +1,178 @@ +package keys + +import ( + cryptorand "crypto/rand" + "encoding/hex" + "math/big" + "testing" + + junotypes "github.com/NethermindEth/juno/pkg/types" + caigotypes "github.com/smartcontractkit/caigo/types" + + ocrtypes "github.com/goplugin/plugin-libocr/offchainreporting2/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// msg to hash +// [ +// '0x4acf99cb25a4803916f086440c661295b105a485efdc649ac4de9536da25b', // digest +// 1, // epoch_and_round +// 1, // extra_hash +// 1, // timestamp +// '0x00010203000000000000000000000000000000000000000000000000000000', // observers +// 4, // len +// 99, // reports +// 99, +// 99, +// 99, +// 1 juels_per_fee_coin +// ] +// hash 0x1332a8dabaabef63b03438ca50760cb9f5c0292cbf015b2395e50e6157df4e3 +// --> privKey 2137244795266879235401249500471353867704187908407744160927664772020405449078 r 2898571078985034687500959842265381508927681132188252715370774777831313601543 s 1930849708769648077928186998643944706551011476358007177069185543644456022504 pubKey 1118148281956858477519852250235501663092798578871088714409528077622994994907 +// privKey 3571531812827697194985986636869245829152430835021673171507607525908246940354 r 3242770073040892094735101607173275538752888766491356946211654602282309624331 s 2150742645846855766116236144967953798077492822890095121354692808525999221887 pubKey 2445157821578193538289426656074203099996547227497157254541771705133209838679 + +func TestStarknetKeyring_TestVector(t *testing.T) { + var kr1 OCR2Key + bigKey, _ := new(big.Int).SetString("2137244795266879235401249500471353867704187908407744160927664772020405449078", 10) + feltKey := junotypes.BigToFelt(bigKey) + err := kr1.Unmarshal(feltKey.Bytes()) + require.NoError(t, err) + // kr2, err := NewOCR2Key(cryptorand.Reader) + // require.NoError(t, err) + + bytes, err := caigotypes.HexToBytes("0x004acf99cb25a4803916f086440c661295b105a485efdc649ac4de9536da25b") + require.NoError(t, err) + configDigest, err := ocrtypes.BytesToConfigDigest(bytes) + require.NoError(t, err) + + ctx := ocrtypes.ReportContext{ + ReportTimestamp: ocrtypes.ReportTimestamp{ + ConfigDigest: configDigest, + Epoch: 0, + Round: 1, + }, + ExtraHash: [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, + }, + } + + var report []byte + report = append(report, junotypes.BigToFelt(big.NewInt(1)).Bytes()...) + report = append(report, junotypes.HexToFelt("0x00010203000000000000000000000000000000000000000000000000000000").Bytes()...) + report = append(report, junotypes.BigToFelt(big.NewInt(4)).Bytes()...) + report = append(report, junotypes.BigToFelt(big.NewInt(99)).Bytes()...) + report = append(report, junotypes.BigToFelt(big.NewInt(99)).Bytes()...) + report = append(report, junotypes.BigToFelt(big.NewInt(99)).Bytes()...) + report = append(report, junotypes.BigToFelt(big.NewInt(99)).Bytes()...) + report = append(report, junotypes.BigToFelt(big.NewInt(1)).Bytes()...) + + // check that report hash matches expected + msg, err := ReportToSigData(ctx, report) + require.NoError(t, err) + + expected, err := caigotypes.HexToBytes("0x1332a8dabaabef63b03438ca50760cb9f5c0292cbf015b2395e50e6157df4e3") + require.NoError(t, err) + assert.Equal(t, expected, msg.Bytes()) + + // check that signature matches expected + sig, err := kr1.Sign(ctx, report) + require.NoError(t, err) + + pub := junotypes.BytesToFelt(sig[0:32]) + r := junotypes.BytesToFelt(sig[32:64]) + s := junotypes.BytesToFelt(sig[64:]) + + bigPubExpected, _ := new(big.Int).SetString("1118148281956858477519852250235501663092798578871088714409528077622994994907", 10) + feltPubExpected := junotypes.BigToFelt(bigPubExpected) + assert.Equal(t, feltPubExpected, pub) + + bigRExpected, _ := new(big.Int).SetString("2898571078985034687500959842265381508927681132188252715370774777831313601543", 10) + feltRExpected := junotypes.BigToFelt(bigRExpected) + assert.Equal(t, feltRExpected, r) + + // test for malleability + otherS, _ := new(big.Int).SetString("1930849708769648077928186998643944706551011476358007177069185543644456022504", 10) + bigSExpected, _ := new(big.Int).SetString("1687653079896483135769135784451125398975732275358080312084893914240056843079", 10) + + feltSExpected := junotypes.BigToFelt(bigSExpected) + assert.NotEqual(t, otherS, s, "signature not in canonical form") + assert.Equal(t, feltSExpected, s) +} + +func TestStarknetKeyring_Sign_Verify(t *testing.T) { + kr1, err := NewOCR2Key(cryptorand.Reader) + require.NoError(t, err) + kr2, err := NewOCR2Key(cryptorand.Reader) + require.NoError(t, err) + + digest := "00044e5d4f35325e464c87374b13c512f60e09d1236dd902f4bef4c9aedd7300" + bytes, err := hex.DecodeString(digest) + require.NoError(t, err) + configDigest, err := ocrtypes.BytesToConfigDigest(bytes) + require.NoError(t, err) + + ctx := ocrtypes.ReportContext{ + ReportTimestamp: ocrtypes.ReportTimestamp{ + ConfigDigest: configDigest, + Epoch: 1, + Round: 1, + }, + ExtraHash: [32]byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + }, + } + report := ocrtypes.Report{ + 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, 97, 91, 43, 83, // observations_timestamp + 0, 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, 0, 0, 0, 0, // observers + 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, 2, // len + 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, 73, 150, 2, 210, // observation 1 + 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, 73, 150, 2, 211, // observation 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 224, 182, 179, 167, 100, 0, 0, // juels per fee coin (1 with 18 decimal places) + } + + t.Run("can verify", func(t *testing.T) { + sig, err := kr1.Sign(ctx, report) + require.NoError(t, err) + result := kr2.Verify(kr1.PublicKey(), ctx, report, sig) + require.True(t, result) + }) + + t.Run("invalid sig", func(t *testing.T) { + result := kr2.Verify(kr1.PublicKey(), ctx, report, []byte{0x01}) + require.False(t, result) + + longSig := [100]byte{} + result = kr2.Verify(kr1.PublicKey(), ctx, report, longSig[:]) + require.False(t, result) + }) + + t.Run("invalid pubkey", func(t *testing.T) { + sig, err := kr1.Sign(ctx, report) + require.NoError(t, err) + + pk := []byte{0x01} + result := kr2.Verify(pk, ctx, report, sig) + require.False(t, result) + + pk = big.NewInt(int64(31337)).Bytes() + result = kr2.Verify(pk, ctx, report, sig) + require.False(t, result) + }) +} + +func TestStarknetKeyring_Marshal(t *testing.T) { + kr1, err := NewOCR2Key(cryptorand.Reader) + require.NoError(t, err) + m, err := kr1.Marshal() + require.NoError(t, err) + kr2 := OCR2Key{} + err = kr2.Unmarshal(m) + require.NoError(t, err) + assert.True(t, kr1.priv.Cmp(kr2.priv) == 0) + + // Invalid seed size should error + require.Error(t, kr2.Unmarshal([]byte{0x01})) +} diff --git a/relayer/pkg/plugin/keys/utils.go b/relayer/pkg/plugin/keys/utils.go new file mode 100644 index 0000000..84a24f3 --- /dev/null +++ b/relayer/pkg/plugin/keys/utils.go @@ -0,0 +1,60 @@ +package keys + +import ( + "crypto/rand" + "fmt" + "io" + "math/big" + + "github.com/NethermindEth/juno/pkg/crypto/pedersen" + "github.com/smartcontractkit/caigo" + + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +// constants +var ( + byteLen = 32 +) + +// PubKeyToContract implements the pubkey to deployed account given contract hash + salt +func PubKeyToAccount(pubkey PublicKey, classHash, salt *big.Int) []byte { + hash := pedersen.ArrayDigest( + new(big.Int).SetBytes([]byte("STARKNET_CONTRACT_ADDRESS")), + big.NewInt(0), + salt, // salt + classHash, // classHash + pedersen.ArrayDigest(pubkey.X), + ) + + // pad big.Int to 32 bytes if needed + return starknet.PadBytes(hash.Bytes(), byteLen) +} + +// PubToStarkKey implements the pubkey to starkkey functionality: https://github.com/0xs34n/starknet.js/blob/cd61356974d355aa42f07a3d63f7ccefecbd913c/src/utils/ellipticCurve.ts#L49 +func PubKeyToStarkKey(pubkey PublicKey) []byte { + return starknet.PadBytes(pubkey.X.Bytes(), byteLen) +} + +// reimplements parts of https://github.com/smartcontractkit/caigo/blob/main/utils.go#L85 +// generate the PK as a pseudo-random number in the interval [1, CurveOrder - 1] +// using io.Reader, and Key struct +func GenerateKey(material io.Reader) (k Key, err error) { + max := new(big.Int).Sub(caigo.Curve.N, big.NewInt(1)) + + k.priv, err = rand.Int(material, max) + if err != nil { + return k, err + } + + k.pub.X, k.pub.Y, err = caigo.Curve.PrivateToPoint(k.priv) + if err != nil { + return k, err + } + + if !caigo.Curve.IsOnCurve(k.pub.X, k.pub.Y) { + return k, fmt.Errorf("key gen is not on stark curve") + } + + return k, nil +} diff --git a/relayer/pkg/plugin/ocr2/client.go b/relayer/pkg/plugin/ocr2/client.go new file mode 100644 index 0000000..39f2489 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/client.go @@ -0,0 +1,252 @@ +package ocr2 + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "time" + + junotypes "github.com/NethermindEth/juno/pkg/types" + "github.com/pkg/errors" + + caigogw "github.com/smartcontractkit/caigo/gateway" + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + "github.com/goplugin/plugin-relay/pkg/logger" +) + +//go:generate mockery --name OCR2Reader --output ./mocks/ + +type OCR2Reader interface { + LatestConfigDetails(context.Context, caigotypes.Hash) (ContractConfigDetails, error) + LatestTransmissionDetails(context.Context, caigotypes.Hash) (TransmissionDetails, error) + LatestRoundData(context.Context, caigotypes.Hash) (RoundData, error) + LinkAvailableForPayment(context.Context, caigotypes.Hash) (*big.Int, error) + ConfigFromEventAt(context.Context, caigotypes.Hash, uint64) (ContractConfig, error) + NewTransmissionsFromEventsAt(context.Context, caigotypes.Hash, uint64) ([]NewTransmissionEvent, error) + BillingDetails(context.Context, caigotypes.Hash) (BillingDetails, error) + + BaseReader() starknet.Reader +} + +var _ OCR2Reader = (*Client)(nil) + +type Client struct { + r starknet.Reader + lggr logger.Logger +} + +func NewClient(reader starknet.Reader, lggr logger.Logger) (*Client, error) { + return &Client{ + r: reader, + lggr: lggr, + }, nil +} + +func (c *Client) BaseReader() starknet.Reader { + return c.r +} + +func (c *Client) BillingDetails(ctx context.Context, address caigotypes.Hash) (bd BillingDetails, err error) { + ops := starknet.CallOps{ + ContractAddress: address, + Selector: "billing", + } + + res, err := c.r.CallContract(ctx, ops) + if err != nil { + return bd, errors.Wrap(err, "couldn't call the contract") + } + + // [0] - observation payment, [1] - transmission payment, [2] - gas base, [3] - gas per signature + if len(res) != 4 { + return bd, errors.New("unexpected result length") + } + + observationPaymentFelt := junotypes.HexToFelt(res[0]) + transmissionPaymentFelt := junotypes.HexToFelt(res[1]) + + bd, err = NewBillingDetails(observationPaymentFelt, transmissionPaymentFelt) + if err != nil { + return bd, errors.Wrap(err, "couldn't initialize billing details") + } + + return +} + +func (c *Client) LatestConfigDetails(ctx context.Context, address caigotypes.Hash) (ccd ContractConfigDetails, err error) { + ops := starknet.CallOps{ + ContractAddress: address, + Selector: "latest_config_details", + } + + res, err := c.r.CallContract(ctx, ops) + if err != nil { + return ccd, errors.Wrap(err, "couldn't call the contract") + } + + // [0] - config count, [1] - block number, [2] - config digest + if len(res) != 3 { + return ccd, errors.New("unexpected result length") + } + + blockNum := junotypes.HexToFelt(res[1]) + configDigest := junotypes.HexToFelt(res[2]) + + ccd, err = NewContractConfigDetails(blockNum, configDigest) + if err != nil { + return ccd, errors.Wrap(err, "couldn't initialize config details") + } + + return +} + +func (c *Client) LatestTransmissionDetails(ctx context.Context, address caigotypes.Hash) (td TransmissionDetails, err error) { + ops := starknet.CallOps{ + ContractAddress: address, + Selector: "latest_transmission_details", + } + + res, err := c.r.CallContract(ctx, ops) + if err != nil { + return td, errors.Wrap(err, "couldn't call the contract") + } + + // [0] - config digest, [1] - epoch and round, [2] - latest answer, [3] - latest timestamp + if len(res) != 4 { + return td, errors.New("unexpected result length") + } + + digest := junotypes.HexToFelt(res[0]) + configDigest := types.ConfigDigest{} + digest.Big().FillBytes(configDigest[:]) + + epoch, round := parseEpochAndRound(junotypes.HexToFelt(res[1]).Big()) + + latestAnswer := starknet.HexToSignedBig(res[2]) + + timestampFelt := junotypes.HexToFelt(res[3]) + // TODO: Int64() can return invalid data if int is too big + unixTime := timestampFelt.Big().Int64() + latestTimestamp := time.Unix(unixTime, 0) + + td = TransmissionDetails{ + Digest: configDigest, + Epoch: epoch, + Round: round, + LatestAnswer: latestAnswer, + LatestTimestamp: latestTimestamp, + } + + return td, nil +} + +func (c *Client) LatestRoundData(ctx context.Context, address caigotypes.Hash) (round RoundData, err error) { + ops := starknet.CallOps{ + ContractAddress: address, + Selector: "latest_round_data", + } + + results, err := c.r.CallContract(ctx, ops) + if err != nil { + return round, errors.Wrap(err, "couldn't call the contract with selector latest_round_data") + } + felts := []junotypes.Felt{} + for _, result := range results { + felts = append(felts, junotypes.HexToFelt(result)) + } + + round, err = NewRoundData(felts) + if err != nil { + return round, errors.Wrap(err, "unable to decode RoundData") + } + return round, nil +} + +func (c *Client) LinkAvailableForPayment(ctx context.Context, address caigotypes.Hash) (*big.Int, error) { + results, err := c.r.CallContract(ctx, starknet.CallOps{ + ContractAddress: address, + Selector: "link_available_for_payment", + }) + if err != nil { + return nil, errors.Wrap(err, "failed to call the contract with selector 'link_available_for_payment'") + } + if len(results) != 1 { + return nil, errors.Wrap(err, "insufficient data from selector 'link_available_for_payment'") + } + return junotypes.HexToFelt(results[0]).Big(), nil +} + +func (c *Client) fetchEventsFromBlock(ctx context.Context, address caigotypes.Hash, eventType string, blockNum uint64) (eventsAsFeltArrs [][]*caigotypes.Felt, err error) { + block, err := c.r.BlockByNumberGateway(ctx, blockNum) + if err != nil { + return eventsAsFeltArrs, errors.Wrap(err, "couldn't fetch block by number") + } + + for _, txReceipt := range block.TransactionReceipts { + for _, event := range txReceipt.Events { + var decodedEvent caigogw.Event + + m, err := json.Marshal(event) + if err != nil { + return eventsAsFeltArrs, errors.Wrap(err, "couldn't marshal event") + } + + err = json.Unmarshal(m, &decodedEvent) + if err != nil { + return eventsAsFeltArrs, errors.Wrap(err, "couldn't unmarshal event") + } + + if starknet.IsEventFromContract(&decodedEvent, address, eventType) { + eventsAsFeltArrs = append(eventsAsFeltArrs, decodedEvent.Data) + } + } + } + if len(eventsAsFeltArrs) == 0 { + return nil, errors.New("events not found in the block") + } + return eventsAsFeltArrs, nil +} + +func (c *Client) ConfigFromEventAt(ctx context.Context, address caigotypes.Hash, blockNum uint64) (cc ContractConfig, err error) { + eventsAsFeltArrs, err := c.fetchEventsFromBlock(ctx, address, "ConfigSet", blockNum) + if err != nil { + return cc, errors.Wrap(err, "failed to fetch config_set events") + } + if len(eventsAsFeltArrs) != 1 { + return cc, fmt.Errorf("expected to find one config_set event in block %d for address %s but found %d", blockNum, address, len(eventsAsFeltArrs)) + } + configAtEvent := eventsAsFeltArrs[0] + config, err := ParseConfigSetEvent(configAtEvent) + if err != nil { + return cc, errors.Wrap(err, "couldn't parse config event") + } + return ContractConfig{ + Config: config, + ConfigBlock: blockNum, + }, nil +} + +// NewTransmissionsFromEventsAt finds events of type new_transmission emitted by the contract address in a given block number. +func (c *Client) NewTransmissionsFromEventsAt(ctx context.Context, address caigotypes.Hash, blockNum uint64) (events []NewTransmissionEvent, err error) { + eventsAsFeltArrs, err := c.fetchEventsFromBlock(ctx, address, "NewTransmission", blockNum) + if err != nil { + return nil, errors.Wrap(err, "failed to fetch new_transmission events") + } + if len(eventsAsFeltArrs) == 0 { + return nil, fmt.Errorf("expected to find at least one new_transmission event in block %d for address %s but found %d", blockNum, address, len(eventsAsFeltArrs)) + } + events = []NewTransmissionEvent{} + for _, felts := range eventsAsFeltArrs { + event, err := ParseNewTransmissionEvent(felts) + if err != nil { + return nil, errors.Wrap(err, "couldn't parse new_transmission event") + } + events = append(events, event) + } + return events, nil +} diff --git a/relayer/pkg/plugin/ocr2/client_test.go b/relayer/pkg/plugin/ocr2/client_test.go new file mode 100644 index 0000000..2480d3c --- /dev/null +++ b/relayer/pkg/plugin/ocr2/client_test.go @@ -0,0 +1,124 @@ +package ocr2 + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "github.com/smartcontractkit/caigo/gateway" + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-relay/pkg/logger" + + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +const BLOCK_OUTPUT = `{"block_hash": "0x2", "block_number": 2, "parent_block_hash": "0x1", "sequencer_address": "0x4bbfb0d1aab5bf33eec5ada3a1040c41ed902a1eeb38c78a753d6f6359f1666", "transactions": [{"entry_point_type": "EXTERNAL", "transaction_hash": "0x2bb11daf4649bbadd51eb33a6890abb869e55c9d65f424e7ef74d34b543b914", "max_fee": "0x1713081b1e9400", "signature": ["0x2dd6147385d73e6a1b278863aa8be6b3c545a81810406807862c15aaae459b8", "0x1d072fdd6280d74c1e0788af5cc0f0169323167f04162a15660afe2e32425a6"], "calldata": ["0x1", "0xd43963a4e875a361f5d164b2e70953598eb4f45fde86924082d51b4d78e489", "0x2f09d463867ebc70075969cdd4d3c0643f9b69dbc84bf9bf96923a52dc3c8d8", "0x0", "0x22", "0x22", "0x4", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603730", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603734", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603731", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603735", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603732", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603736", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603733", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603737", "0x1", "0x0", "0x2", "0x15", "0x263", "0x880a0d9e61d1080d88ee16f1880bcc1960b2080cab5ee01288090dfc04a30", "0x53a0201024220af400004fa5d02cd5170b5261032e71f2847ead36159cf8d", "0xee68affc3c8520904220af400004fa5d02cd5170b5261032e71f2847ead361", "0x59cf8dee68affc3c8520914220af400004fa5d02cd5170b5261032e71f2847", "0xead36159cf8dee68affc3c8520924220af400004fa5d02cd5170b5261032e7", "0x1f2847ead36159cf8dee68affc3c8520934a42307830346363316266613939", "0x65323832653433346165663238313563613137333337613932336364326336", "0x31636630633764653562333236643761383630333733304a42307830346363", "0x31626661393965323832653433346165663238313563613137333337613932", "0x33636432633631636630633764653562333236643761383630333733314a42", "0x30783034636331626661393965323832653433346165663238313563613137", "0x33333761393233636432633631636630633764653562333236643761383630", "0x333733324a4230783034636331626661393965323832653433346165663238", "0x31356361313733333761393233636432633631636630633764653562333236", "0x643761383630333733335200608094ebdc03688084af5f708084af5f788084", "0xaf5f82018c010a202ac49e648a1f84da5a143eeab68c8402c65a1567e63971", "0x7f5732d5e6310c2c761220a6c1ae85186dc981dc61cd14d7511ee5ab70258a", "0x10ac4e03e4d4991761b2c0a61a1090696dc7afed7f61a26887e78e683a1c1a", "0x10a29e5fa535f2edea7afa9acb4fd349b31a10d1b88713982955d79fa0e422", "0x685a748b1a10a07e0118cc38a71d2a9d60bf52938b4a", "0x0"], "contract_address": "0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a", "entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", "type": "INVOKE_FUNCTION"}], "starknet_version": "0.9.1", "transaction_receipts": [{"transaction_hash": "0x2bb11daf4649bbadd51eb33a6890abb869e55c9d65f424e7ef74d34b543b914", "actual_fee": "0xf62056769b800", "transaction_index": 0, "l2_to_l1_messages": [], "execution_resources": {"builtin_instance_counter": {"pedersen_builtin": 69, "range_check_builtin": 97, "ecdsa_builtin": 1, "bitwise_builtin": 1, "output_builtin": 0}, "n_steps": 3432, "n_memory_holes": 326}, "events": [{"from_address": "0xd43963a4e875a361f5d164b2e70953598eb4f45fde86924082d51b4d78e489", "keys": ["0x9a144bf4a6a8fd083c93211e163e59221578efcc86b93f8c97c620e7b9608a"], "data": ["0x0", "0x4b791b801cf0d7b6a2f9e59daf15ec2dd7d9cdc3bc5e037bada9c86e4821c", "0x1", "0x4", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603730", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603734", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603731", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603735", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603732", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603736", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603733", "0x4cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603737", "0x1", "0x3", "0x1", "0x0", "0xf4240", "0x2", "0x15", "0x263", "0x880a0d9e61d1080d88ee16f1880bcc1960b2080cab5ee01288090dfc04a30", "0x53a0201024220af400004fa5d02cd5170b5261032e71f2847ead36159cf8d", "0xee68affc3c8520904220af400004fa5d02cd5170b5261032e71f2847ead361", "0x59cf8dee68affc3c8520914220af400004fa5d02cd5170b5261032e71f2847", "0xead36159cf8dee68affc3c8520924220af400004fa5d02cd5170b5261032e7", "0x1f2847ead36159cf8dee68affc3c8520934a42307830346363316266613939", "0x65323832653433346165663238313563613137333337613932336364326336", "0x31636630633764653562333236643761383630333733304a42307830346363", "0x31626661393965323832653433346165663238313563613137333337613932", "0x33636432633631636630633764653562333236643761383630333733314a42", "0x30783034636331626661393965323832653433346165663238313563613137", "0x33333761393233636432633631636630633764653562333236643761383630", "0x333733324a4230783034636331626661393965323832653433346165663238", "0x31356361313733333761393233636432633631636630633764653562333236", "0x643761383630333733335200608094ebdc03688084af5f708084af5f788084", "0xaf5f82018c010a202ac49e648a1f84da5a143eeab68c8402c65a1567e63971", "0x7f5732d5e6310c2c761220a6c1ae85186dc981dc61cd14d7511ee5ab70258a", "0x10ac4e03e4d4991761b2c0a61a1090696dc7afed7f61a26887e78e683a1c1a", "0x10a29e5fa535f2edea7afa9acb4fd349b31a10d1b88713982955d79fa0e422", "0x685a748b1a10a07e0118cc38a71d2a9d60bf52938b4a"]}]}], "gas_price": "0x174876e800", "state_root": "0000000000000000000000000000000000000000000000000000000000000000", "status": "ACCEPTED_ON_L2", "timestamp": 1664483024}` +const ocr2ContractAddress = "0xd43963a4e875a361f5d164b2e70953598eb4f45fde86924082d51b4d78e489" // matches BLOCK_OUTPUT event + +func TestOCR2Client(t *testing.T) { + chainID := gateway.GOERLI_ID + lggr := logger.Test(t) + + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + req, _ := io.ReadAll(r.Body) + fmt.Println(r.RequestURI, r.URL, string(req)) + + var out []byte + + switch { + case r.RequestURI == "/feeder_gateway/call_contract?blockNumber=pending": + type Request struct { + Selector string `json:"entry_point_selector"` + } + + reqdata := Request{} + require.NoError(t, json.Unmarshal(req, &reqdata)) + + switch { + case caigotypes.BigToHex(caigotypes.GetSelectorFromName("billing")) == reqdata.Selector: + // billing response + out = []byte(`{"result":["0x0","0x0","0x0","0x0"]}`) + case caigotypes.BigToHex(caigotypes.GetSelectorFromName("latest_config_details")) == reqdata.Selector: + // latest config details response + out = []byte(`{"result":["0x1","0x2","0x4b791b801cf0d7b6a2f9e59daf15ec2dd7d9cdc3bc5e037bada9c86e4821c"]}`) + case caigotypes.BigToHex(caigotypes.GetSelectorFromName("latest_transmission_details")) == reqdata.Selector: + // latest transmission details response + out = []byte(`{"result":["0x4cfc96325fa7d72e4854420e2d7b0abda72de17d45e4c3c0d9f626016d669","0x0","0x0","0x0"]}`) + case caigotypes.BigToHex(caigotypes.GetSelectorFromName("latest_round_data")) == reqdata.Selector: + // latest transmission details response + out = []byte(`{"result":["0x0","0x0","0x0","0x0","0x0"]}`) + case caigotypes.BigToHex(caigotypes.GetSelectorFromName("link_available_for_payment")) == reqdata.Selector: + // latest transmission details response + out = []byte(`{"result":["0x0"]}`) + default: + require.False(t, true, "unsupported contract method") + } + case strings.Contains(r.RequestURI, "/feeder_gateway/get_block"): + out = []byte(BLOCK_OUTPUT) + default: + require.False(t, true, "unsupported endpoint") + } + + _, err := w.Write(out) + require.NoError(t, err) + })) + defer mockServer.Close() + + url := mockServer.URL + duration := 10 * time.Second + reader, err := starknet.NewClient(chainID, url, lggr, &duration) + require.NoError(t, err) + client, err := NewClient(reader, lggr) + assert.NoError(t, err) + + contractAddress := caigotypes.HexToHash(ocr2ContractAddress) + + t.Run("get billing details", func(t *testing.T) { + billing, err := client.BillingDetails(context.Background(), contractAddress) + require.NoError(t, err) + fmt.Printf("%+v\n", billing) + }) + + t.Run("get latest config details", func(t *testing.T) { + details, err := client.LatestConfigDetails(context.Background(), contractAddress) + require.NoError(t, err) + fmt.Printf("%+v\n", details) + + config, err := client.ConfigFromEventAt(context.Background(), contractAddress, details.Block) + require.NoError(t, err) + fmt.Printf("%+v\n", config) + }) + + t.Run("get latest transmission details", func(t *testing.T) { + transmissions, err := client.LatestTransmissionDetails(context.Background(), contractAddress) + require.NoError(t, err) + fmt.Printf("%+v\n", transmissions) + }) + + t.Run("get latest round data", func(t *testing.T) { + round, err := client.LatestRoundData(context.Background(), contractAddress) + require.NoError(t, err) + fmt.Printf("%+v\n", round) + }) + + t.Run("get link available for payment", func(t *testing.T) { + available, err := client.LinkAvailableForPayment(context.Background(), contractAddress) + require.NoError(t, err) + fmt.Printf("%+v\n", available) + }) + + t.Run("get latest transmission", func(t *testing.T) { + round, err := client.LatestRoundData(context.Background(), contractAddress) + assert.NoError(t, err) + fmt.Printf("%+v\n", round) + }) +} diff --git a/relayer/pkg/plugin/ocr2/config.go b/relayer/pkg/plugin/ocr2/config.go new file mode 100644 index 0000000..5e95b26 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/config.go @@ -0,0 +1,8 @@ +package ocr2 + +import "time" + +type Config interface { + OCR2CachePollPeriod() time.Duration + OCR2CacheTTL() time.Duration +} diff --git a/relayer/pkg/plugin/ocr2/config_digester.go b/relayer/pkg/plugin/ocr2/config_digester.go new file mode 100644 index 0000000..7cfa76e --- /dev/null +++ b/relayer/pkg/plugin/ocr2/config_digester.go @@ -0,0 +1,104 @@ +package ocr2 + +import ( + "encoding/binary" + "errors" + "math/big" + "strings" + + "github.com/NethermindEth/juno/pkg/crypto/pedersen" + + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/medianreport" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +// TODO: use libocr constant +const ConfigDigestPrefixStarknet types.ConfigDigestPrefix = 4 + +var _ types.OffchainConfigDigester = (*offchainConfigDigester)(nil) + +type offchainConfigDigester struct { + chainID string + contract string +} + +func NewOffchainConfigDigester(chainID, contract string) offchainConfigDigester { + return offchainConfigDigester{ + chainID: chainID, + contract: contract, + } +} + +// TODO: ConfigDigest is byte[32] but what we really want here is a felt +func (d offchainConfigDigester) ConfigDigest(cfg types.ContractConfig) (types.ConfigDigest, error) { + configDigest := types.ConfigDigest{} + + contract_address, valid := new(big.Int).SetString(strings.TrimPrefix(d.contract, "0x"), 16) + if !valid { + return configDigest, errors.New("invalid contract address") + } + + if len(d.chainID) > 31 { + return configDigest, errors.New("chainID exceeds max length") + } + + if len(cfg.Signers) != len(cfg.Transmitters) { + return configDigest, errors.New("must have equal number of signers and transmitters") + } + + if len(cfg.Signers) <= 3*int(cfg.F) { + return configDigest, errors.New("number of oracles must be greater than 3*f") + } + + oracles := []*big.Int{} + for i := range cfg.Signers { + signer := new(big.Int).SetBytes(cfg.Signers[i]) + transmitter, valid := new(big.Int).SetString(strings.TrimPrefix(string(cfg.Transmitters[i]), "0x"), 16) + if !valid { + return configDigest, errors.New("invalid transmitter") + } + oracles = append(oracles, signer, transmitter) + } + + offchainConfig := starknet.EncodeFelts(cfg.OffchainConfig) + + onchainConfig, err := medianreport.OnchainConfigCodec{}.DecodeToFelts(cfg.OnchainConfig) + if err != nil { + return configDigest, err + } + + // golang... https://stackoverflow.com/questions/28625546/mixing-exploded-slices-and-regular-parameters-in-variadic-functions + msg := []*big.Int{ + new(big.Int).SetBytes([]byte(d.chainID)), // chain_id + contract_address, // contract_address + new(big.Int).SetUint64(cfg.ConfigCount), // config_count + new(big.Int).SetInt64(int64(len(cfg.Signers))), // oracles_len + } + msg = append(msg, oracles...) + msg = append( + msg, + big.NewInt(int64(cfg.F)), // f + big.NewInt(int64(len(onchainConfig))), // onchain_config_len + ) + msg = append(msg, onchainConfig...) + msg = append( + msg, + new(big.Int).SetUint64(cfg.OffchainConfigVersion), // offchain_config_version + big.NewInt(int64(len(offchainConfig))), // offchain_config_len + ) + msg = append(msg, offchainConfig...) // offchain_config + + digest := pedersen.ArrayDigest(msg...) + digest.FillBytes(configDigest[:]) + + // set first two bytes to the digest prefix + binary.BigEndian.PutUint16(configDigest[:2], uint16(d.ConfigDigestPrefix())) + + return configDigest, nil +} + +func (offchainConfigDigester) ConfigDigestPrefix() types.ConfigDigestPrefix { + return ConfigDigestPrefixStarknet +} diff --git a/relayer/pkg/plugin/ocr2/config_digester_test.go b/relayer/pkg/plugin/ocr2/config_digester_test.go new file mode 100644 index 0000000..c079304 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/config_digester_test.go @@ -0,0 +1,67 @@ +package ocr2_test + +import ( + "strings" + "testing" + + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +var testConfig = types.ContractConfig{ + ConfigCount: 1, + Signers: []types.OnchainPublicKey{ + starknet.XXXMustHexDecodeString("03f5df103ef3ae4d8e5ec708abf48bfdbff08f9e8deacc1a0bedf3e93cffd2a3"), + starknet.XXXMustHexDecodeString("0312c009b6d4cad9bd653450bb81eec18e81733052ee3f6cb3a2c182082db173"), + starknet.XXXMustHexDecodeString("02fc4861ccb51c1548dee618ed1103fbc1c01be0144da8950ad1d80c1a7bc3ba"), + starknet.XXXMustHexDecodeString("0331d8d682d098b685a929e0ad1d89a768ea8a1ca254c2dcbddf57521623729e"), + }, + Transmitters: []types.Account{ + "01ccc16a80a22f0643b217d32798fe6994c823b7838262db80b4e2a867c61caa", + "00578180df3312211b37f95ff74428270ea5fe1850908c1d6165b7242e614277", + "0339c8b556e92cd6b7f7b6c0c69c942db62d0385209a387600077be35509d99e", + "07ac7c65dc083c4552d53dc5b925de392e41255c6eada6a1ebdf1bdcb6b3ba54", + }, + F: 1, + OnchainConfig: []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, // version + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 246, // min (-1) + 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, 59, 154, 202, 0, // max (1000000000) + }, + OffchainConfigVersion: 2, + OffchainConfig: []byte{1}, +} + +func TestConfigDigester(t *testing.T) { + d := ocr2.NewOffchainConfigDigester( + "SN_GOERLI", // DEFAULT_CHAIN_ID = StarknetChainId.TESTNET + "01dfac180005c5a5efc88d2c37f880320e1764b83dd3a35006690e1ed7da68d7", + ) + + digest, err := d.ConfigDigest(testConfig) + assert.NoError(t, err) + assert.Equal(t, "0004d46ed94aa1a4bfa938170a3df74f5b286498a411f59fe5be4d00b6eef12d", digest.Hex()) +} + +func TestConfigDigester_InvalidChainID(t *testing.T) { + d := ocr2.NewOffchainConfigDigester( + strings.Repeat("a", 256), // chain ID is too long + "42c59a00fd21bdc27c7be3e9cc272a9b684037e4a37417c2d5a920081e6e87c", + ) + + _, err := d.ConfigDigest(testConfig) + assert.Error(t, err, "chainID") +} + +func FuzzEncoding(f *testing.F) { + f.Add([]byte("hello world")) + f.Fuzz(func(t *testing.T, data []byte) { + result, err := starknet.DecodeFelts(starknet.EncodeFelts(data)) + require.NoError(t, err) + require.Equal(t, data, result) + }) +} diff --git a/relayer/pkg/plugin/ocr2/contract_cache.go b/relayer/pkg/plugin/ocr2/contract_cache.go new file mode 100644 index 0000000..f985495 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/contract_cache.go @@ -0,0 +1,159 @@ +package ocr2 + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/pkg/errors" + + "github.com/goplugin/plugin-relay/pkg/logger" + "github.com/goplugin/plugin-relay/pkg/utils" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +type Tracker interface { + Start() error + Close() error + poll() +} + +var _ Tracker = (*contractCache)(nil) +var _ types.ContractConfigTracker = (*contractCache)(nil) + +type contractCache struct { + contractConfig ContractConfig + blockHeight uint64 + ccLock sync.RWMutex + ccLastCheckedAt time.Time + + stop, done chan struct{} + + reader Reader + cfg Config + lggr logger.Logger +} + +func NewContractCache(cfg Config, reader Reader, lggr logger.Logger) *contractCache { + return &contractCache{ + cfg: cfg, + reader: reader, + lggr: lggr, + stop: make(chan struct{}), + done: make(chan struct{}), + } +} + +func (c *contractCache) updateConfig(ctx context.Context) error { + configBlock, configDigest, err := c.reader.LatestConfigDetails(ctx) + if err != nil { + return errors.Wrap(err, "couldn't fetch latest config details") + } + + c.ccLock.RLock() + isSame := c.contractConfig.ConfigBlock == configBlock && c.contractConfig.Config.ConfigDigest == configDigest + c.ccLock.RUnlock() + + var newConfig types.ContractConfig + if !isSame { + newConfig, err = c.reader.LatestConfig(ctx, configBlock) + if err != nil { + return errors.Wrap(err, "couldn't fetch latest config") + } + } + + blockHeight, err := c.reader.LatestBlockHeight(ctx) + if err != nil { + return errors.Wrap(err, "failed to fetch latest block height") + } + + c.lggr.Debugw("contract cache update", "blockHeight", blockHeight, "configBlock", configBlock, "configDigest", configDigest) + + c.ccLock.Lock() + defer c.ccLock.Unlock() + c.ccLastCheckedAt = time.Now() + c.blockHeight = blockHeight + if !isSame { + c.contractConfig = ContractConfig{ + Config: newConfig, + ConfigBlock: configBlock, + } + } + + return nil +} + +func (c *contractCache) Start() error { + ctx, cancel := utils.ContextFromChan(c.stop) + defer cancel() + if err := c.updateConfig(ctx); err != nil { + c.lggr.Warnf("Failed to populate initial config: %v", err) + } + go c.poll() + return nil +} + +func (c *contractCache) Close() error { + close(c.stop) + return nil +} + +func (c *contractCache) poll() { + defer close(c.done) + tick := time.After(0) + for { + select { + case <-c.stop: + return + case <-tick: + ctx, cancel := utils.ContextFromChan(c.stop) + + if err := c.updateConfig(ctx); err != nil { + c.lggr.Errorf("Failed to update config: %v", err) + } + cancel() + + tick = time.After(utils.WithJitter(c.cfg.OCR2CachePollPeriod())) + } + } +} + +func (c *contractCache) Notify() <-chan struct{} { + return nil +} + +func (c *contractCache) LatestConfigDetails(ctx context.Context) (changedInBlock uint64, configDigest types.ConfigDigest, err error) { + c.ccLock.RLock() + defer c.ccLock.RUnlock() + changedInBlock = c.contractConfig.ConfigBlock + configDigest = c.contractConfig.Config.ConfigDigest + err = c.assertConfigNotStale() + return +} + +func (c *contractCache) LatestConfig(ctx context.Context, changedInBlock uint64) (config types.ContractConfig, err error) { + c.ccLock.RLock() + defer c.ccLock.RUnlock() + config = c.contractConfig.Config + err = c.assertConfigNotStale() + return +} + +func (c *contractCache) LatestBlockHeight(ctx context.Context) (blockHeight uint64, err error) { + c.ccLock.RLock() + defer c.ccLock.RUnlock() + return c.blockHeight, c.assertConfigNotStale() +} + +func (c *contractCache) assertConfigNotStale() error { + if c.ccLastCheckedAt.IsZero() { + return errors.New("contract config cache not yet initialized") + } + + if since := time.Since(c.ccLastCheckedAt); since > c.cfg.OCR2CacheTTL() { + return fmt.Errorf("contract config cache expired: checked last %s ago", since) + } + + return nil +} diff --git a/relayer/pkg/plugin/ocr2/contract_reader.go b/relayer/pkg/plugin/ocr2/contract_reader.go new file mode 100644 index 0000000..f3f99b1 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/contract_reader.go @@ -0,0 +1,125 @@ +package ocr2 + +import ( + "context" + "math/big" + "time" + + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/pkg/errors" + + "github.com/goplugin/plugin-relay/pkg/logger" + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +type Reader interface { + types.ContractConfigTracker + median.MedianContract +} + +var _ Reader = (*contractReader)(nil) + +type contractReader struct { + address caigotypes.Hash + reader OCR2Reader + lggr logger.Logger +} + +func NewContractReader(address string, reader OCR2Reader, lggr logger.Logger) Reader { + return &contractReader{ + address: caigotypes.HexToHash(address), // TODO: propagate type everywhere + reader: reader, + lggr: lggr, + } +} + +func (c *contractReader) Notify() <-chan struct{} { + return nil +} + +func (c *contractReader) LatestConfigDetails(ctx context.Context) (changedInBlock uint64, configDigest types.ConfigDigest, err error) { + resp, err := c.reader.LatestConfigDetails(ctx, c.address) + if err != nil { + return changedInBlock, configDigest, errors.Wrap(err, "couldn't get latest config details") + } + + changedInBlock = resp.Block + configDigest = resp.Digest + + return +} + +func (c *contractReader) LatestConfig(ctx context.Context, changedInBlock uint64) (config types.ContractConfig, err error) { + resp, err := c.reader.ConfigFromEventAt(ctx, c.address, changedInBlock) + if err != nil { + return config, errors.Wrap(err, "couldn't get latest config") + } + + config = resp.Config + + return +} + +func (c *contractReader) LatestBlockHeight(ctx context.Context) (blockHeight uint64, err error) { + blockHeight, err = c.reader.BaseReader().LatestBlockHeight(ctx) + if err != nil { + return blockHeight, errors.Wrap(err, "couldn't get latest block height") + } + + return +} + +func (c *contractReader) LatestTransmissionDetails( + ctx context.Context, +) ( + configDigest types.ConfigDigest, + epoch uint32, + round uint8, + latestAnswer *big.Int, + latestTimestamp time.Time, + err error, +) { + transmissionDetails, err := c.reader.LatestTransmissionDetails(ctx, c.address) + if err != nil { + err = errors.Wrap(err, "couldn't get transmission details") + } + + configDigest = transmissionDetails.Digest + epoch = transmissionDetails.Epoch + round = transmissionDetails.Round + latestAnswer = transmissionDetails.LatestAnswer + latestTimestamp = transmissionDetails.LatestTimestamp + + return +} + +func (c *contractReader) LatestRoundRequested( + ctx context.Context, + lookback time.Duration, +) ( + configDigest types.ConfigDigest, + epoch uint32, + round uint8, + err error, +) { + transmissionDetails, err := c.reader.LatestTransmissionDetails(ctx, c.address) + if err != nil { + err = errors.Wrap(err, "couldn't get transmission details") + } + + configDigest = transmissionDetails.Digest + epoch = transmissionDetails.Epoch + round = transmissionDetails.Round + + return +} + +func (c *contractReader) LatestBillingDetails(ctx context.Context) (bd BillingDetails, err error) { + bd, err = c.reader.BillingDetails(ctx, c.address) + if err != nil { + err = errors.Wrap(err, "couldn't get billing details") + } + + return +} diff --git a/relayer/pkg/plugin/ocr2/contract_transmitter.go b/relayer/pkg/plugin/ocr2/contract_transmitter.go new file mode 100644 index 0000000..c9c8d22 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/contract_transmitter.go @@ -0,0 +1,113 @@ +package ocr2 + +import ( + "context" + "encoding/hex" + "fmt" + + "github.com/pkg/errors" + + caigotypes "github.com/smartcontractkit/caigo/types" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/medianreport" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/txm" + + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +var _ types.ContractTransmitter = (*contractTransmitter)(nil) + +type contractTransmitter struct { + reader *transmissionsCache + + contractAddress caigotypes.Hash + senderAddress caigotypes.Hash + accountAddress caigotypes.Hash + + txm txm.TxManager +} + +func NewContractTransmitter( + reader *transmissionsCache, + contractAddress string, + senderAddress string, + accountAddress string, + txm txm.TxManager, +) *contractTransmitter { + return &contractTransmitter{ + reader: reader, + contractAddress: caigotypes.HexToHash(contractAddress), + senderAddress: caigotypes.HexToHash(senderAddress), + accountAddress: caigotypes.HexToHash(accountAddress), + txm: txm, + } +} + +func (c *contractTransmitter) Transmit( + ctx context.Context, + reportCtx types.ReportContext, + report types.Report, + sigs []types.AttributedOnchainSignature, +) error { + // flat array of arguments + // convert everything to hex string -> caigo internally converts into big.int + var transmitPayload []string + + // ReportContext: + // config_digest + // epoch_and_round + // extra_hash + reportContext := medianreport.RawReportContext(reportCtx) + + for _, r := range reportContext { + transmitPayload = append(transmitPayload, "0x"+hex.EncodeToString(r[:])) + } + + slices, err := medianreport.SplitReport(report) + if err != nil { + return err + } + for i := 0; i < len(slices); i++ { + hexStr := hex.EncodeToString(slices[i]) + transmitPayload = append(transmitPayload, "0x"+hexStr) + } + + transmitPayload = append(transmitPayload, "0x"+fmt.Sprintf("%x", len(sigs))) // signatures_len + for _, sig := range sigs { + // signature: 32 byte public key + 32 byte R + 32 byte S + signature := sig.Signature + if len(signature) != 32+32+32 { + return errors.New("invalid length of the signature") + } + transmitPayload = append(transmitPayload, "0x"+hex.EncodeToString(signature[32:64])) // r + transmitPayload = append(transmitPayload, "0x"+hex.EncodeToString(signature[64:])) // s + transmitPayload = append(transmitPayload, "0x"+hex.EncodeToString(signature[:32])) // public key + } + + err = c.txm.Enqueue(c.senderAddress, c.accountAddress, caigotypes.FunctionCall{ + ContractAddress: c.contractAddress, + EntryPointSelector: "transmit", + Calldata: transmitPayload, + }) + + return err +} + +func (c *contractTransmitter) LatestConfigDigestAndEpoch( + ctx context.Context, +) ( + configDigest types.ConfigDigest, + epoch uint32, + err error, +) { + configDigest, epoch, _, _, _, err = c.reader.LatestTransmissionDetails(ctx) + if err != nil { + err = errors.Wrap(err, "couldn't fetch latest transmission details") + } + + return +} + +func (c *contractTransmitter) FromAccount() types.Account { + return types.Account(c.senderAddress.String()) +} diff --git a/relayer/pkg/plugin/ocr2/events.go b/relayer/pkg/plugin/ocr2/events.go new file mode 100644 index 0000000..54dc706 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/events.go @@ -0,0 +1,242 @@ +package ocr2 + +import ( + "encoding/hex" + "math/big" + "time" + + "github.com/pkg/errors" + + caigotypes "github.com/smartcontractkit/caigo/types" + + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/medianreport" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +var ( + MaxObservers = 31 + + // Event selectors + NewTransmissionEventSelector = "019e22f866f4c5aead2809bf160d2b29e921e335d899979732101c6f3c38ff81" + ConfigSetEventSelector = "9a144bf4a6a8fd083c93211e163e59221578efcc86b93f8c97c620e7b9608a" +) + +// NewTransmissionEvent represents the 'NewTransmission' event +type NewTransmissionEvent struct { + RoundId uint32 + LatestAnswer *big.Int + Transmitter *caigotypes.Felt + LatestTimestamp time.Time + Observers []uint8 + ObservationsLen uint32 + Observations []*big.Int + JuelsPerFeeCoin *big.Int + GasPrice *big.Int + ConfigDigest types.ConfigDigest + Epoch uint32 + Round uint8 + Reimbursement *big.Int +} + +// ParseNewTransmissionEvent is decoding binary felt data as the NewTransmissionEvent type +func ParseNewTransmissionEvent(eventData []*caigotypes.Felt) (NewTransmissionEvent, error) { + { + const observationsLenIndex = 5 + const constNumOfElements = 11 + + if len(eventData) < constNumOfElements { + return NewTransmissionEvent{}, errors.New("invalid: event data") + } + + observationsLen := eventData[observationsLenIndex].Uint64() + if len(eventData) != constNumOfElements+int(observationsLen) { + return NewTransmissionEvent{}, errors.New("invalid: event data") + } + } + + // round_id + index := 0 + roundId := uint32(eventData[index].Uint64()) + + // answer + index++ + latestAnswer := starknet.HexToSignedBig(eventData[index].String()) + + // transmitter + index++ + transmitter := eventData[index] + + // observation_timestamp + index++ + unixTime := eventData[index].Int64() + latestTimestamp := time.Unix(unixTime, 0) + + // observers (raw) max 31 + index++ + observersRaw := starknet.PadBytes(eventData[index].Big().Bytes(), MaxObservers) + + // observation_len + index++ + observationsLen := uint32(eventData[index].Uint64()) + + // observers (based on observationsLen) + var observers []uint8 + for i := 0; i < int(observationsLen); i++ { + observers = append(observers, observersRaw[i]) + } + + // observations (based on observationsLen) + var observations []*big.Int + for i := 0; i < int(observationsLen); i++ { + observations = append(observations, eventData[index+i+1].Big()) + } + + // juels_per_fee_coin + index += int(observationsLen) + 1 + juelsPerFeeCoin := eventData[index].Big() + + // juels_per_fee_coin + index++ + gasPrice := eventData[index].Big() + + // config digest + index++ + digest, err := types.BytesToConfigDigest(starknet.PadBytes(eventData[index].Bytes(), len(types.ConfigDigest{}))) + if err != nil { + return NewTransmissionEvent{}, errors.Wrap(err, "couldn't convert bytes to ConfigDigest") + } + + // epoch_and_round + index++ + epoch, round := parseEpochAndRound(eventData[index].Big()) + + // reimbursement + index++ + reimbursement := eventData[index].Big() + + return NewTransmissionEvent{ + RoundId: roundId, + LatestAnswer: latestAnswer, + Transmitter: transmitter, + LatestTimestamp: latestTimestamp, + Observers: observers, + ObservationsLen: observationsLen, + Observations: observations, + JuelsPerFeeCoin: juelsPerFeeCoin, + GasPrice: gasPrice, + ConfigDigest: digest, + Epoch: epoch, + Round: round, + Reimbursement: reimbursement, + }, nil +} + +// ParseConfigSetEvent is decoding binary felt data as the libocr ContractConfig type +func ParseConfigSetEvent(eventData []*caigotypes.Felt) (types.ContractConfig, error) { + { + const oraclesLenIdx = 3 + if len(eventData) < oraclesLenIdx { + return types.ContractConfig{}, errors.New("invalid: event data") + } + + oraclesLen := eventData[oraclesLenIdx].Uint64() + onchainConfigLenIdx := oraclesLenIdx + 2*oraclesLen + 2 + + if uint64(len(eventData)) < onchainConfigLenIdx { + return types.ContractConfig{}, errors.New("invalid: event data") + } + + onchainConfigLen := eventData[onchainConfigLenIdx].Uint64() + offchainConfigLenIdx := onchainConfigLenIdx + onchainConfigLen + 2 + + if uint64(len(eventData)) < offchainConfigLenIdx { + return types.ContractConfig{}, errors.New("invalid: event data") + } + + offchainConfigLen := eventData[offchainConfigLenIdx].Uint64() + if uint64(len(eventData)) != offchainConfigLenIdx+offchainConfigLen+1 { + return types.ContractConfig{}, errors.New("invalid: event data") + } + } + + index := 0 + // previous_config_block_number - skip + + // latest_config_digest + index++ + digest, err := types.BytesToConfigDigest(starknet.PadBytes(eventData[index].Bytes(), len(types.ConfigDigest{}))) + if err != nil { + return types.ContractConfig{}, errors.Wrap(err, "couldn't convert bytes to ConfigDigest") + } + + // config_count + index++ + configCount := eventData[index].Uint64() + + // oracles_len + index++ + oraclesLen := eventData[index].Uint64() + + // oracles + index++ + oracleMembers := eventData[index:(index + int(oraclesLen)*2)] + var signers []types.OnchainPublicKey + var transmitters []types.Account + for i, member := range oracleMembers { + if i%2 == 0 { + signers = append(signers, starknet.PadBytes(member.Bytes(), 32)) // pad to 32 bytes + } else { + transmitters = append(transmitters, types.Account("0x"+hex.EncodeToString(starknet.PadBytes(member.Bytes(), 32)))) // pad to 32 byte length then re-encode + } + } + + // f + index = index + int(oraclesLen)*2 + f := eventData[index].Uint64() + + // onchain_config length + index++ + onchainConfigLen := eventData[index].Uint64() + + // onchain_config (version=1, min, max) + index++ + onchainConfigFelts := eventData[index:(index + int(onchainConfigLen))] + onchainConfig, err := medianreport.OnchainConfigCodec{}.EncodeFromFelt( + onchainConfigFelts[0].Big(), + onchainConfigFelts[1].Big(), + onchainConfigFelts[2].Big(), + ) + if err != nil { + return types.ContractConfig{}, errors.Wrap(err, "err in encoding onchain config from felts") + } + + // offchain_config_version + index += int(onchainConfigLen) + offchainConfigVersion := eventData[index].Uint64() + + // offchain_config_len + index++ + offchainConfigLen := eventData[index].Uint64() + + // offchain_config + index++ + offchainConfigFelts := eventData[index:(index + int(offchainConfigLen))] + // todo: get rid of caigoToJuno workaround + offchainConfig, err := starknet.DecodeFelts(starknet.FeltsToBig(offchainConfigFelts)) + if err != nil { + return types.ContractConfig{}, errors.Wrap(err, "couldn't decode offchain config") + } + + return types.ContractConfig{ + ConfigDigest: digest, + ConfigCount: configCount, + Signers: signers, + Transmitters: transmitters, + F: uint8(f), + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + }, nil +} diff --git a/relayer/pkg/plugin/ocr2/events_test.go b/relayer/pkg/plugin/ocr2/events_test.go new file mode 100644 index 0000000..f69dee4 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/events_test.go @@ -0,0 +1,154 @@ +package ocr2 + +import ( + "encoding/hex" + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + caigotypes "github.com/smartcontractkit/caigo/types" + + "github.com/goplugin/plugin-libocr/offchainreporting2/types" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/medianreport" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +var ( + newTransmissionEventRaw = []string{ + "0x1", + "0x63", + "0x2c0dd77ce74b1667dc6fa782bbafaef5becbe2d04b052726ab236daeb52ac5d", + "0x1", + "0x10203000000000000000000000000000000000000000000000000000000", + "0x4", + "0x63", + "0x63", + "0x63", + "0x63", + "0x1", + "0x1", + "0x485341c18461d70eac6ded4b8b17147f173308ddd56216a86f9ec4d994453", + "0x1", + "0x0", + } + configSetEventRaw = []string{ + "0x0", + "0x485341c18461d70eac6ded4b8b17147f173308ddd56216a86f9ec4d994453", + "0x1", + "0x4", + "0x21e867aa6e6c545949a9c6f9f5401b70007bd93675857a0a7d5345b8bffcbf0", + "0x2c0dd77ce74b1667dc6fa782bbafaef5becbe2d04b052726ab236daeb52ac5d", + "0x64642f34e68436f45757b920f4cdfbdff82728844d740bac672a19ad72011ca", + "0x2de61335d8f1caa7e9df54486f016ded83d0e02fde4c12280f4b898720b0e2b", + "0x3fad2efda193b37e4e526972d9613238b9ff993e1e3d3b1dd376d7b8ceb7acd", + "0x2f14e18cc198dd5133c8a9aa92992fc1a462f703401716f402d0ee383b54faa", + "0x4fcf11b05ebd00a207030c04836defbec3d37a3f77e581f2d0962a20a55adcd", + "0x5c35686f78db31d9d896bb425b3fd99be19019f8aeaf0f7a8767867903341d4", + "0x1", + "0x3", + "0x1", + "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff7", + "0x3b9aca00", + "0x2", + "0x2", + "0x1", + "0x1", + } +) + +func TestNewTransmissionEvent_Parse(t *testing.T) { + eventData, err := starknet.StringsToFelt(newTransmissionEventRaw) + assert.NoError(t, err) + require.Equal(t, len(newTransmissionEventRaw), len(eventData)) + + e, err := ParseNewTransmissionEvent(eventData) + assert.NoError(t, err) + + require.Equal(t, e.RoundId, uint32(1)) + require.Equal(t, e.LatestAnswer, big.NewInt(99)) + require.Equal(t, e.LatestTimestamp, time.Unix(1, 0)) + require.Equal(t, e.Epoch, uint32(0)) + require.Equal(t, e.Round, uint8(1)) + require.Equal(t, e.Reimbursement, big.NewInt(0)) + + require.Equal(t, e.JuelsPerFeeCoin, big.NewInt(1)) + require.Equal(t, e.GasPrice, big.NewInt(1)) + + transmitterHex := "0x2c0dd77ce74b1667dc6fa782bbafaef5becbe2d04b052726ab236daeb52ac5d" + require.Equal(t, len(transmitterHex), int(2+31.5*2)) // len('0x') + len(max_felt_len) + require.Equal(t, e.Transmitter, caigotypes.StrToFelt(transmitterHex)) + + require.Equal(t, e.Observers, []uint8{0, 1, 2, 3}) + require.Equal(t, e.ObservationsLen, uint32(4)) + require.Equal(t, e.ObservationsLen, uint32(len(e.Observers))) + + configDigest := XXXMustBytesToConfigDigest(starknet.XXXMustHexDecodeString("000485341c18461d70eac6ded4b8b17147f173308ddd56216a86f9ec4d994453")) + require.Equal(t, len(configDigest), 32) // padded to 32 bytes + require.Equal(t, e.ConfigDigest, configDigest) +} + +func TestConfigSetEvent_Parse(t *testing.T) { + eventData, err := starknet.StringsToFelt(configSetEventRaw) + assert.NoError(t, err) + require.Equal(t, len(configSetEventRaw), len(eventData)) + + e, err := ParseConfigSetEvent(eventData) + assert.NoError(t, err) + + configDigest := XXXMustBytesToConfigDigest(starknet.XXXMustHexDecodeString("000485341c18461d70eac6ded4b8b17147f173308ddd56216a86f9ec4d994453")) + require.Equal(t, len(configDigest), 32) // padded to 32 bytes + require.Equal(t, e.ConfigDigest, configDigest) + require.Equal(t, e.ConfigCount, uint64(1)) + + oraclesLen := 4 + require.Equal(t, len(e.Signers), oraclesLen) + signersExpected := []types.OnchainPublicKey{ + starknet.XXXMustHexDecodeString("021e867aa6e6c545949a9c6f9f5401b70007bd93675857a0a7d5345b8bffcbf0"), + starknet.XXXMustHexDecodeString("064642f34e68436f45757b920f4cdfbdff82728844d740bac672a19ad72011ca"), + starknet.XXXMustHexDecodeString("03fad2efda193b37e4e526972d9613238b9ff993e1e3d3b1dd376d7b8ceb7acd"), + starknet.XXXMustHexDecodeString("04fcf11b05ebd00a207030c04836defbec3d37a3f77e581f2d0962a20a55adcd"), + } + require.Equal(t, e.Signers, signersExpected) + + transmittersExpected := []types.Account{ + "0x02c0dd77ce74b1667dc6fa782bbafaef5becbe2d04b052726ab236daeb52ac5d", + "0x02de61335d8f1caa7e9df54486f016ded83d0e02fde4c12280f4b898720b0e2b", + "0x02f14e18cc198dd5133c8a9aa92992fc1a462f703401716f402d0ee383b54faa", + "0x05c35686f78db31d9d896bb425b3fd99be19019f8aeaf0f7a8767867903341d4", + } + require.Equal(t, e.Transmitters, transmittersExpected) + require.Equal(t, len(e.Transmitters), oraclesLen) + + require.Equal(t, e.F, uint8(1)) + + onchainConfig, err := medianreport.OnchainConfigCodec{}.EncodeFromBigInt( + big.NewInt(medianreport.OnchainConfigVersion), // version + big.NewInt(-10), // min + big.NewInt(1000000000), // max + ) + assert.NoError(t, err) + require.Equal(t, e.OnchainConfig, onchainConfig) + + require.Equal(t, e.OffchainConfigVersion, uint64(2)) + require.Equal(t, e.OffchainConfig, []uint8{0x1}) // dummy config +} + +func TestNewTransmissionEventSelector(t *testing.T) { + bytes, err := hex.DecodeString(NewTransmissionEventSelector) + require.NoError(t, err) + eventKey := new(big.Int) + eventKey.SetBytes(bytes) + assert.Equal(t, caigotypes.GetSelectorFromName("NewTransmission").Cmp(eventKey), 0) +} + +func TestConfigSetEventSelector(t *testing.T) { + bytes, err := hex.DecodeString(ConfigSetEventSelector) + require.NoError(t, err) + eventKey := new(big.Int) + eventKey.SetBytes(bytes) + assert.Equal(t, caigotypes.GetSelectorFromName("ConfigSet").Cmp(eventKey), 0) +} diff --git a/relayer/pkg/plugin/ocr2/medianreport/onchainconfig.go b/relayer/pkg/plugin/ocr2/medianreport/onchainconfig.go new file mode 100644 index 0000000..3893eb0 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/medianreport/onchainconfig.go @@ -0,0 +1,115 @@ +package medianreport + +import ( + "fmt" + "math/big" + + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/goplugin/plugin-libocr/bigbigendian" + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" +) + +const ( + OnchainConfigVersion = 1 + byteWidth = 32 + length = 3 * byteWidth +) + +// report format +// 32 bytes - version +// 32 bytes - min +// 32 bytes - max + +type OnchainConfigCodec struct{} + +var _ median.OnchainConfigCodec = &OnchainConfigCodec{} + +// DecodeToFelts decodes the onchainconfig into felt values (used in config digest hashing) +func (codec OnchainConfigCodec) DecodeToFelts(b []byte) ([]*big.Int, error) { + if len(b) != length { + return []*big.Int{}, fmt.Errorf("unexpected length of OnchainConfig, expected %v, got %v", length, len(b)) + } + + configVersion, err := bigbigendian.DeserializeSigned(byteWidth, b[:32]) + if err != nil { + return []*big.Int{}, fmt.Errorf("unable to decode version: %s", err) + } + if OnchainConfigVersion != configVersion.Int64() { + return []*big.Int{}, fmt.Errorf("unexpected version of OnchainConfig, expected %v, got %v", OnchainConfigVersion, configVersion.Int64()) + } + + min, err := bigbigendian.DeserializeSigned(byteWidth, b[byteWidth:2*byteWidth]) + if err != nil { + return []*big.Int{}, err + } + max, err := bigbigendian.DeserializeSigned(byteWidth, b[2*byteWidth:]) + if err != nil { + return []*big.Int{}, err + } + + // ensure felts (used in config digester) + min = starknet.SignedBigToFelt(min) + max = starknet.SignedBigToFelt(max) + + return []*big.Int{configVersion, min, max}, nil +} + +// Decode converts the onchainconfig via the outputs of DecodeToFelts into signed big.Ints that libocr expects +func (codec OnchainConfigCodec) Decode(b []byte) (median.OnchainConfig, error) { + felts, err := codec.DecodeToFelts(b) + if err != nil { + return median.OnchainConfig{}, err + } + + // convert felts to big.Ints + min := starknet.FeltToSignedBig(&caigotypes.Felt{Int: felts[1]}) + max := starknet.FeltToSignedBig(&caigotypes.Felt{Int: felts[2]}) + + if !(min.Cmp(max) <= 0) { + return median.OnchainConfig{}, fmt.Errorf("OnchainConfig min (%v) should not be greater than max(%v)", min, max) + } + + return median.OnchainConfig{Min: min, Max: max}, nil +} + +// TODO: both 'EncodeFromBigInt' and 'EncodeFromFelt' have the same signature - we need a custom type to represent Felts +// EncodeFromBigInt encodes the config where min & max are big Ints with positive or negative values +func (codec OnchainConfigCodec) EncodeFromBigInt(version, min, max *big.Int) ([]byte, error) { + return codec.EncodeFromFelt(version, starknet.SignedBigToFelt(min), starknet.SignedBigToFelt(max)) +} + +// EncodeFromFelt encodes the config where min & max are big.Int representations of a felt +// Cairo has no notion of signed values: negative values have to be wrapped into the upper half of PRIME (so 0 to PRIME/2 is positive, PRIME/2 to PRIME is negative) +func (codec OnchainConfigCodec) EncodeFromFelt(version, min, max *big.Int) ([]byte, error) { + if version.Uint64() != OnchainConfigVersion { + return nil, fmt.Errorf("unexpected version of OnchainConfig, expected %v, got %v", OnchainConfigVersion, version.Int64()) + } + + versionBytes, err := bigbigendian.SerializeSigned(byteWidth, version) + if err != nil { + return nil, err + } + + minBytes, err := bigbigendian.SerializeSigned(byteWidth, min) + if err != nil { + return nil, err + } + + maxBytes, err := bigbigendian.SerializeSigned(byteWidth, max) + if err != nil { + return nil, err + } + result := []byte{} + result = append(result, versionBytes...) + result = append(result, minBytes...) + result = append(result, maxBytes...) + + return result, nil +} + +// Encode takes the interface that libocr uses (+/- big.Ints) and serializes it into 3 felts +func (codec OnchainConfigCodec) Encode(c median.OnchainConfig) ([]byte, error) { + return codec.EncodeFromBigInt(big.NewInt(OnchainConfigVersion), c.Min, c.Max) +} diff --git a/relayer/pkg/plugin/ocr2/medianreport/onchainconfig_test.go b/relayer/pkg/plugin/ocr2/medianreport/onchainconfig_test.go new file mode 100644 index 0000000..a4a78bb --- /dev/null +++ b/relayer/pkg/plugin/ocr2/medianreport/onchainconfig_test.go @@ -0,0 +1,91 @@ +package medianreport + +import ( + "math/big" + "testing" + + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestOnchainConfigCodec(t *testing.T) { + var params = []struct { + name string + val []*big.Int + expectErr bool + }{ + { + name: "positive min < positive max", + val: []*big.Int{big.NewInt(1), big.NewInt(1000)}, + expectErr: false, + }, + { + name: "negative min < positive max", + val: []*big.Int{big.NewInt(-1000), big.NewInt(1000)}, + expectErr: false, + }, + { + name: "negative min < negative max", + val: []*big.Int{big.NewInt(-1000), big.NewInt(-1)}, + expectErr: false, + }, + { + name: "positive min > positive max", + val: []*big.Int{big.NewInt(1000), big.NewInt(1)}, + expectErr: true, + }, + { + name: "negative min > negative max", + val: []*big.Int{big.NewInt(-1), big.NewInt(-1000)}, + expectErr: true, + }, + { + name: "positive min > negative max", + val: []*big.Int{big.NewInt(1), big.NewInt(-1000)}, + expectErr: true, + }, + { + name: "min = max", + val: []*big.Int{big.NewInt(0), big.NewInt(0)}, + expectErr: false, + }, + } + + codec := OnchainConfigCodec{} + + for _, p := range params { + t.Run(p.name, func(t *testing.T) { + cfg := median.OnchainConfig{ + Min: p.val[0], + Max: p.val[1], + } + + configBytes, err := codec.Encode(cfg) + require.NoError(t, err) + + newCfg, err := codec.Decode(configBytes) + if p.expectErr { + assert.Error(t, err) + return // exit func if error is verified + } + require.NoError(t, err) + + assert.True(t, cfg.Min.Cmp(newCfg.Min) == 0) + assert.True(t, cfg.Max.Cmp(newCfg.Max) == 0) + }) + } + + t.Run("incorrect length", func(t *testing.T) { + b := make([]byte, length-1) + _, err := codec.Decode(b) + assert.Error(t, err) + }) + + t.Run("incorrect version", func(t *testing.T) { + b := make([]byte, length) + b[0] = 1 + _, err := codec.Decode(b) + assert.Error(t, err) + }) +} diff --git a/relayer/pkg/plugin/ocr2/medianreport/report.go b/relayer/pkg/plugin/ocr2/medianreport/report.go new file mode 100644 index 0000000..2296ee0 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/medianreport/report.go @@ -0,0 +1,159 @@ +package medianreport + +import ( + "math" + "math/big" + "sort" + + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + junotypes "github.com/NethermindEth/juno/pkg/types" + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/pkg/errors" + + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +var _ median.ReportCodec = (*ReportCodec)(nil) + +const ( + timestampSizeBytes = junotypes.FeltLength + observersSizeBytes = junotypes.FeltLength + observationsLenBytes = junotypes.FeltLength + prefixSizeBytes = timestampSizeBytes + observersSizeBytes + observationsLenBytes + juelsPerFeeCoinSizeBytes = junotypes.FeltLength + gasPriceSizeBytes = junotypes.FeltLength + observationSizeBytes = junotypes.FeltLength +) + +type ReportCodec struct{} + +func (c ReportCodec) BuildReport(oo []median.ParsedAttributedObservation) (types.Report, error) { + num := len(oo) + if num == 0 { + return nil, errors.New("couldn't build report from empty attributed observations") + } + + // preserve original array + oo = append([]median.ParsedAttributedObservation{}, oo...) + numFelt := junotypes.BigToFelt(big.NewInt(int64(num))) + + // median timestamp + sort.Slice(oo, func(i, j int) bool { + return oo[i].Timestamp < oo[j].Timestamp + }) + timestamp := oo[num/2].Timestamp + timestampFelt := junotypes.BigToFelt(big.NewInt(int64(timestamp))) + + // median juelsPerFeeCoin + sort.Slice(oo, func(i, j int) bool { + return oo[i].JuelsPerFeeCoin.Cmp(oo[j].JuelsPerFeeCoin) < 0 + }) + juelsPerFeeCoin := oo[num/2].JuelsPerFeeCoin + juelsPerFeeCoin = starknet.SignedBigToFelt(juelsPerFeeCoin) // converts negative bigInts to corresponding felt in bigInt form + juelsPerFeeCoinFelt := junotypes.BigToFelt(juelsPerFeeCoin) + + // TODO: source from observations + gasPrice := big.NewInt(1) // := oo[num/2].GasPrice + gasPriceFelt := junotypes.BigToFelt(gasPrice) + + // sort by values + sort.Slice(oo, func(i, j int) bool { + return oo[i].Value.Cmp(oo[j].Value) < 0 + }) + + var observers junotypes.Felt + var observations []junotypes.Felt + for i, o := range oo { + observers[i] = byte(o.Observer) + obs := starknet.SignedBigToFelt(o.Value) // converts negative bigInts to corresponding felt in bigInt form + observations = append(observations, junotypes.BigToFelt(obs)) + } + + var report []byte + report = append(report, timestampFelt.Bytes()...) + report = append(report, observers.Bytes()...) + report = append(report, numFelt.Bytes()...) + for _, o := range observations { + report = append(report, o.Bytes()...) + } + report = append(report, juelsPerFeeCoinFelt.Bytes()...) + report = append(report, gasPriceFelt.Bytes()...) + + return report, nil +} + +func (c ReportCodec) MedianFromReport(report types.Report) (*big.Int, error) { + rLen := len(report) + if rLen < prefixSizeBytes+juelsPerFeeCoinSizeBytes { + return nil, errors.New("invalid report length") + } + + // Decode the number of observations + numBig := junotypes.BytesToFelt(report[(timestampSizeBytes + observersSizeBytes):prefixSizeBytes]).Big() + if !numBig.IsUint64() { + return nil, errors.New("length of observations is invalid") + } + n64 := numBig.Uint64() + if n64 == 0 { + return nil, errors.New("unpacked report has no observations") + } + if n64 >= math.MaxInt8 { + return nil, errors.New("length of observations is invalid") + } + + // Check if the report is big enough + n := int(n64) + expectedLen := prefixSizeBytes + (observationSizeBytes * n) + juelsPerFeeCoinSizeBytes + if rLen < expectedLen { + return nil, errors.New("invalid report length, missing main or juelsPerFeeCoin observations") + } + + // Decode observations + var oo []*big.Int + for i := 0; i < n; i++ { + start := prefixSizeBytes + observationSizeBytes*i + end := start + observationSizeBytes + o := starknet.FeltToSignedBig(&caigotypes.Felt{ + Int: junotypes.BytesToFelt(report[start:end]).Big(), + }) + oo = append(oo, o) + } + + // Check if the report contains sorted observations + _less := func(i, j int) bool { + return oo[i].Cmp(oo[j]) < 0 + } + sorted := sort.SliceIsSorted(oo, _less) + if !sorted { + return nil, errors.New("observations not sorted") + } + + return oo[n/2], nil +} + +func (c ReportCodec) MaxReportLength(n int) int { + return prefixSizeBytes + (n * observationSizeBytes) + juelsPerFeeCoinSizeBytes + gasPriceSizeBytes +} + +func SplitReport(report types.Report) ([][]byte, error) { + chunkSize := junotypes.FeltLength + if len(report)%chunkSize != 0 { + return [][]byte{}, errors.New("invalid report length") + } + + // order is guaranteed by buildReport: + // observation_timestamp + // observers + // observations_len + // observations + // juels_per_fee_coin + slices := [][]byte{} + for i := 0; i < len(report)/chunkSize; i++ { + idx := i * chunkSize + slices = append(slices, report[idx:(idx+chunkSize)]) + } + + return slices, nil +} diff --git a/relayer/pkg/plugin/ocr2/medianreport/report_fuzz_test.go b/relayer/pkg/plugin/ocr2/medianreport/report_fuzz_test.go new file mode 100644 index 0000000..0afe9f9 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/medianreport/report_fuzz_test.go @@ -0,0 +1,35 @@ +//go:build go1.18 +// +build go1.18 + +package medianreport + +import ( + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" +) + +// go test -tags=go1.18 -fuzz ./... +func FuzzReportCodecMedianFromReport(f *testing.F) { + cdc := ReportCodec{} + report, err := cdc.BuildReport([]median.ParsedAttributedObservation{ + {Timestamp: uint32(time.Now().Unix()), Value: big.NewInt(10), JuelsPerFeeCoin: big.NewInt(100000)}, + {Timestamp: uint32(time.Now().Unix()), Value: big.NewInt(10), JuelsPerFeeCoin: big.NewInt(200000)}, + {Timestamp: uint32(time.Now().Unix()), Value: big.NewInt(11), JuelsPerFeeCoin: big.NewInt(300000)}}) + require.NoError(f, err) + + // Seed with valid report + f.Add([]byte(report)) + f.Fuzz(func(t *testing.T, report []byte) { + med, err := cdc.MedianFromReport(report) + if err == nil { + // Should always be able to build a report from the medians extracted + _, err = cdc.BuildReport([]median.ParsedAttributedObservation{{Timestamp: uint32(time.Now().Unix()), Value: med, JuelsPerFeeCoin: med}}) + require.NoError(t, err) + } + }) +} diff --git a/relayer/pkg/plugin/ocr2/medianreport/report_test.go b/relayer/pkg/plugin/ocr2/medianreport/report_test.go new file mode 100644 index 0000000..71389d2 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/medianreport/report_test.go @@ -0,0 +1,155 @@ +package medianreport + +import ( + "fmt" + "math/big" + "testing" + "time" + + junotypes "github.com/NethermindEth/juno/pkg/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-libocr/commontypes" + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" +) + +func TestBuildReport(t *testing.T) { + c := ReportCodec{} + oo := []median.ParsedAttributedObservation{} + + // expected outputs + n := 4 + observers := make([]byte, 32) + v := big.NewInt(0) + v.SetString("1000000000000000000", 10) + + for i := 0; i < n; i++ { + oo = append(oo, median.ParsedAttributedObservation{ + Timestamp: uint32(time.Now().Unix()), + Value: big.NewInt(1234567890), + JuelsPerFeeCoin: v, + Observer: commontypes.OracleID(i), + }) + + // create expected outputs + observers[i] = uint8(i) + } + + report, err := c.BuildReport(oo) + assert.NoError(t, err) + + // validate length + totalLen := prefixSizeBytes + observationSizeBytes*n + juelsPerFeeCoinSizeBytes + gasPriceSizeBytes + assert.Equal(t, totalLen, len(report), "validate length") + + // validate timestamp + timestamp := junotypes.BytesToFelt(report[0:timestampSizeBytes]).Big() + assert.Equal(t, uint64(oo[0].Timestamp), timestamp.Uint64(), "validate timestamp") + + // validate observers + index := timestampSizeBytes + assert.Equal(t, observers, []byte(report[index:index+observersSizeBytes]), "validate observers") + + // validate observer count + index += observersSizeBytes + count := junotypes.BytesToFelt(report[index : index+observationsLenBytes]).Big() + assert.Equal(t, uint8(n), uint8(count.Uint64()), "validate observer count") + + // validate observations + for i := 0; i < n; i++ { + idx := prefixSizeBytes + observationSizeBytes*i + assert.Equal(t, oo[0].Value.FillBytes(make([]byte, observationSizeBytes)), []byte(report[idx:idx+observationSizeBytes]), fmt.Sprintf("validate median observation #%d", i)) + } + + // validate juelsPerFeeCoin + index = prefixSizeBytes + observationSizeBytes*n + assert.Equal(t, v.FillBytes(make([]byte, juelsPerFeeCoinSizeBytes)), []byte(report[index:index+juelsPerFeeCoinSizeBytes]), "validate juelsPerFeeCoin") + + // validate gasPrice + index += juelsPerFeeCoinSizeBytes + expectedGasPrice := big.NewInt(1) + assert.Equal(t, expectedGasPrice.FillBytes(make([]byte, gasPriceSizeBytes)), []byte(report[index:index+gasPriceSizeBytes]), "validate gasPrice") +} + +type medianTest struct { + name string + obs []*big.Int + expectedMedian *big.Int +} + +func TestMedianFromReport(t *testing.T) { + cdc := ReportCodec{} + // Requires at least one obs + _, err := cdc.BuildReport(nil) + require.Error(t, err) + var tt = []medianTest{ + { + name: "2 positive one zero", + obs: []*big.Int{big.NewInt(0), big.NewInt(10), big.NewInt(20)}, + expectedMedian: big.NewInt(10), + }, + { + name: "one zero", + obs: []*big.Int{big.NewInt(0)}, + expectedMedian: big.NewInt(0), + }, + { + name: "two equal", + obs: []*big.Int{big.NewInt(1), big.NewInt(1)}, + expectedMedian: big.NewInt(1), + }, + { + name: "one negative one positive", + obs: []*big.Int{big.NewInt(-1), big.NewInt(1)}, + // sorts to -1, 1 + expectedMedian: big.NewInt(1), + }, + { + name: "two negative", + obs: []*big.Int{big.NewInt(-2), big.NewInt(-1)}, + // will sort to -2, -1 + expectedMedian: big.NewInt(-1), + }, + { + name: "three negative", + obs: []*big.Int{big.NewInt(-5), big.NewInt(-3), big.NewInt(-1)}, + // will sort to -5, -3, -1 + expectedMedian: big.NewInt(-3), + }, + } + + // add cases for observation number from [1..31] + for i := 1; i < 32; i++ { + test := medianTest{ + name: fmt.Sprintf("observations=%d", i), + obs: []*big.Int{}, + expectedMedian: big.NewInt(1), + } + for j := 0; j < i; j++ { + test.obs = append(test.obs, big.NewInt(1)) + } + tt = append(tt, test) + } + + for _, tc := range tt { + tc := tc + t.Run(tc.name, func(t *testing.T) { + var pos []median.ParsedAttributedObservation + for i, obs := range tc.obs { + pos = append(pos, median.ParsedAttributedObservation{ + Value: obs, + JuelsPerFeeCoin: obs, + Observer: commontypes.OracleID(uint8(i))}, + ) + } + report, err := cdc.BuildReport(pos) + require.NoError(t, err) + assert.Equal(t, len(report), cdc.MaxReportLength(len(tc.obs))) + med, err := cdc.MedianFromReport(report) + require.NoError(t, err) + assert.Equal(t, tc.expectedMedian.String(), med.String()) + }) + } + +} diff --git a/relayer/pkg/plugin/ocr2/medianreport/utils.go b/relayer/pkg/plugin/ocr2/medianreport/utils.go new file mode 100644 index 0000000..7a232c3 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/medianreport/utils.go @@ -0,0 +1,15 @@ +package medianreport + +import ( + "github.com/goplugin/plugin-libocr/offchainreporting2/chains/evmutil" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +// NOTE: this should sit in the ocr2 package but that causes import cycles +func RawReportContext(repctx types.ReportContext) [3][32]byte { + rawReportContext := evmutil.RawReportContext(repctx) + // NOTE: Ensure extra_hash is 31 bytes with first byte blanked out + // libocr generates a 32 byte extraHash but we need to fit it into a felt + rawReportContext[2][0] = 0 + return rawReportContext +} diff --git a/relayer/pkg/plugin/ocr2/mocks/OCR2Reader.go b/relayer/pkg/plugin/ocr2/mocks/OCR2Reader.go new file mode 100644 index 0000000..65898e8 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/mocks/OCR2Reader.go @@ -0,0 +1,203 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" + + ocr2 "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + + starknet "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + types "github.com/smartcontractkit/caigo/types" +) + +// OCR2Reader is an autogenerated mock type for the OCR2Reader type +type OCR2Reader struct { + mock.Mock +} + +// BaseReader provides a mock function with given fields: +func (_m *OCR2Reader) BaseReader() starknet.Reader { + ret := _m.Called() + + var r0 starknet.Reader + if rf, ok := ret.Get(0).(func() starknet.Reader); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(starknet.Reader) + } + } + + return r0 +} + +// BillingDetails provides a mock function with given fields: _a0, _a1 +func (_m *OCR2Reader) BillingDetails(_a0 context.Context, _a1 types.Hash) (ocr2.BillingDetails, error) { + ret := _m.Called(_a0, _a1) + + var r0 ocr2.BillingDetails + if rf, ok := ret.Get(0).(func(context.Context, types.Hash) ocr2.BillingDetails); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(ocr2.BillingDetails) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.Hash) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConfigFromEventAt provides a mock function with given fields: _a0, _a1, _a2 +func (_m *OCR2Reader) ConfigFromEventAt(_a0 context.Context, _a1 types.Hash, _a2 uint64) (ocr2.ContractConfig, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 ocr2.ContractConfig + if rf, ok := ret.Get(0).(func(context.Context, types.Hash, uint64) ocr2.ContractConfig); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(ocr2.ContractConfig) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.Hash, uint64) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LatestConfigDetails provides a mock function with given fields: _a0, _a1 +func (_m *OCR2Reader) LatestConfigDetails(_a0 context.Context, _a1 types.Hash) (ocr2.ContractConfigDetails, error) { + ret := _m.Called(_a0, _a1) + + var r0 ocr2.ContractConfigDetails + if rf, ok := ret.Get(0).(func(context.Context, types.Hash) ocr2.ContractConfigDetails); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(ocr2.ContractConfigDetails) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.Hash) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LatestRoundData provides a mock function with given fields: _a0, _a1 +func (_m *OCR2Reader) LatestRoundData(_a0 context.Context, _a1 types.Hash) (ocr2.RoundData, error) { + ret := _m.Called(_a0, _a1) + + var r0 ocr2.RoundData + if rf, ok := ret.Get(0).(func(context.Context, types.Hash) ocr2.RoundData); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(ocr2.RoundData) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.Hash) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LatestTransmissionDetails provides a mock function with given fields: _a0, _a1 +func (_m *OCR2Reader) LatestTransmissionDetails(_a0 context.Context, _a1 types.Hash) (ocr2.TransmissionDetails, error) { + ret := _m.Called(_a0, _a1) + + var r0 ocr2.TransmissionDetails + if rf, ok := ret.Get(0).(func(context.Context, types.Hash) ocr2.TransmissionDetails); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(ocr2.TransmissionDetails) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.Hash) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LinkAvailableForPayment provides a mock function with given fields: _a0, _a1 +func (_m *OCR2Reader) LinkAvailableForPayment(_a0 context.Context, _a1 types.Hash) (*big.Int, error) { + ret := _m.Called(_a0, _a1) + + var r0 *big.Int + if rf, ok := ret.Get(0).(func(context.Context, types.Hash) *big.Int); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.Hash) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewTransmissionsFromEventsAt provides a mock function with given fields: _a0, _a1, _a2 +func (_m *OCR2Reader) NewTransmissionsFromEventsAt(_a0 context.Context, _a1 types.Hash, _a2 uint64) ([]ocr2.NewTransmissionEvent, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 []ocr2.NewTransmissionEvent + if rf, ok := ret.Get(0).(func(context.Context, types.Hash, uint64) []ocr2.NewTransmissionEvent); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ocr2.NewTransmissionEvent) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.Hash, uint64) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewOCR2Reader interface { + mock.TestingT + Cleanup(func()) +} + +// NewOCR2Reader creates a new instance of OCR2Reader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewOCR2Reader(t mockConstructorTestingTNewOCR2Reader) *OCR2Reader { + mock := &OCR2Reader{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/relayer/pkg/plugin/ocr2/providers.go b/relayer/pkg/plugin/ocr2/providers.go new file mode 100644 index 0000000..ab4356d --- /dev/null +++ b/relayer/pkg/plugin/ocr2/providers.go @@ -0,0 +1,153 @@ +package ocr2 + +import ( + "context" + + "github.com/pkg/errors" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2/medianreport" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/txm" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + "github.com/goplugin/plugin-relay/pkg/logger" + relaytypes "github.com/goplugin/plugin-relay/pkg/types" + "github.com/goplugin/plugin-relay/pkg/utils" + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +var _ relaytypes.ConfigProvider = (*configProvider)(nil) + +type configProvider struct { + utils.StartStopOnce + + reader Reader + contractCache *contractCache + digester types.OffchainConfigDigester + + lggr logger.Logger +} + +func NewConfigProvider(chainID string, contractAddress string, basereader starknet.Reader, cfg Config, lggr logger.Logger) (*configProvider, error) { + lggr = logger.Named(lggr, "ConfigProvider") + chainReader, err := NewClient(basereader, lggr) + if err != nil { + return nil, errors.Wrap(err, "err in NewConfigProvider.NewClient") + } + + reader := NewContractReader(contractAddress, chainReader, lggr) + cache := NewContractCache(cfg, reader, lggr) + digester := NewOffchainConfigDigester(chainID, contractAddress) + + return &configProvider{ + reader: reader, + contractCache: cache, + digester: digester, + lggr: lggr, + }, nil +} + +func (p *configProvider) Name() string { + return p.lggr.Name() +} + +func (p *configProvider) Start(context.Context) error { + return p.StartOnce("ConfigProvider", func() error { + p.lggr.Debugf("Config provider starting") + return p.contractCache.Start() + }) +} + +func (p *configProvider) Close() error { + return p.StopOnce("ConfigProvider", func() error { + p.lggr.Debugf("Config provider stopping") + return p.contractCache.Close() + }) +} + +func (p *configProvider) HealthReport() map[string]error { + return map[string]error{p.Name(): p.Healthy()} +} + +func (p *configProvider) ContractConfigTracker() types.ContractConfigTracker { + return p.contractCache +} + +func (p *configProvider) OffchainConfigDigester() types.OffchainConfigDigester { + return p.digester +} + +var _ relaytypes.MedianProvider = (*medianProvider)(nil) + +type medianProvider struct { + *configProvider + transmitter types.ContractTransmitter + transmissionsCache *transmissionsCache + reportCodec median.ReportCodec +} + +func NewMedianProvider(chainID string, contractAddress string, senderAddress string, accountAddress string, basereader starknet.Reader, cfg Config, txm txm.TxManager, lggr logger.Logger) (*medianProvider, error) { + lggr = logger.Named(lggr, "MedianProvider") + configProvider, err := NewConfigProvider(chainID, contractAddress, basereader, cfg, lggr) + if err != nil { + return nil, errors.Wrap(err, "error in NewMedianProvider.NewConfigProvider") + } + + cache := NewTransmissionsCache(cfg, configProvider.reader, lggr) + transmitter := NewContractTransmitter(cache, contractAddress, senderAddress, accountAddress, txm) + + return &medianProvider{ + configProvider: configProvider, + transmitter: transmitter, + transmissionsCache: cache, + reportCodec: medianreport.ReportCodec{}, + }, nil +} + +func (p *medianProvider) Name() string { + return p.lggr.Name() +} + +func (p *medianProvider) Start(context.Context) error { + return p.StartOnce("MedianProvider", func() error { + p.lggr.Debugf("Median provider starting") + // starting both cache services here + // todo: find a better way + if err := p.configProvider.contractCache.Start(); err != nil { + return errors.Wrap(err, "couldn't start contractCache") + } + return p.transmissionsCache.Start() + }) +} + +func (p *medianProvider) Close() error { + return p.StopOnce("MedianProvider", func() error { + p.lggr.Debugf("Median provider stopping") + // stopping both cache services here + // todo: find a better way + if err := p.configProvider.contractCache.Close(); err != nil { + return errors.Wrap(err, "coulnd't stop contractCache") + } + return p.transmissionsCache.Close() + }) +} + +func (p *medianProvider) HealthReport() map[string]error { + return map[string]error{p.Name(): p.Healthy()} +} + +func (p *medianProvider) ContractTransmitter() types.ContractTransmitter { + return p.transmitter +} + +func (p *medianProvider) ReportCodec() median.ReportCodec { + return p.reportCodec +} + +func (p *medianProvider) MedianContract() median.MedianContract { + return p.transmissionsCache +} + +func (p *medianProvider) OnchainConfigCodec() median.OnchainConfigCodec { + return medianreport.OnchainConfigCodec{} +} diff --git a/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzEncoding/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzEncoding/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 new file mode 100644 index 0000000..67322c7 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzEncoding/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("") diff --git a/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/a027c0abbee32f49cd1a35d5c9b9bea24ec8bb8ee322e03d12b98b6a90367d45 b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/a027c0abbee32f49cd1a35d5c9b9bea24ec8bb8ee322e03d12b98b6a90367d45 new file mode 100644 index 0000000..b83d999 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/a027c0abbee32f49cd1a35d5c9b9bea24ec8bb8ee322e03d12b98b6a90367d45 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000") diff --git a/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/ef90fb60d9b326ffdcebdf49782fb2ea099a8dba26e80f2652b621cd5c180bb2 b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/ef90fb60d9b326ffdcebdf49782fb2ea099a8dba26e80f2652b621cd5c180bb2 new file mode 100644 index 0000000..483a977 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/ef90fb60d9b326ffdcebdf49782fb2ea099a8dba26e80f2652b621cd5c180bb2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") diff --git a/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/f285bc28d7b7e7006a25508b22bf71aceb4f9ecd5849401dbc4f549fb9233e53 b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/f285bc28d7b7e7006a25508b22bf71aceb4f9ecd5849401dbc4f549fb9233e53 new file mode 100644 index 0000000..98c4f15 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/testdata/fuzz/FuzzReportCodecMedianFromReport/f285bc28d7b7e7006a25508b22bf71aceb4f9ecd5849401dbc4f549fb9233e53 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000000000000000000000000000000000000000000000000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x0000000000000000000000000000000000") diff --git a/relayer/pkg/plugin/ocr2/transmissions_cache.go b/relayer/pkg/plugin/ocr2/transmissions_cache.go new file mode 100644 index 0000000..309254e --- /dev/null +++ b/relayer/pkg/plugin/ocr2/transmissions_cache.go @@ -0,0 +1,152 @@ +package ocr2 + +import ( + "context" + "fmt" + "math/big" + "sync" + "time" + + "github.com/pkg/errors" + + "github.com/goplugin/plugin-relay/pkg/logger" + "github.com/goplugin/plugin-relay/pkg/utils" + "github.com/goplugin/plugin-libocr/offchainreporting2/reportingplugin/median" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +var _ Tracker = (*transmissionsCache)(nil) +var _ median.MedianContract = (*transmissionsCache)(nil) + +type transmissionsCache struct { + transmissionDetails TransmissionDetails + tdLock sync.RWMutex + tdLastCheckedAt time.Time + + stop, done chan struct{} + + reader Reader + cfg Config + lggr logger.Logger +} + +func NewTransmissionsCache(cfg Config, reader Reader, lggr logger.Logger) *transmissionsCache { + return &transmissionsCache{ + cfg: cfg, + reader: reader, + lggr: lggr, + stop: make(chan struct{}), + done: make(chan struct{}), + transmissionDetails: TransmissionDetails{ + LatestAnswer: big.NewInt(0), // should always return at least 0 and not nil + }, + } +} + +func (c *transmissionsCache) updateTransmission(ctx context.Context) error { + digest, epoch, round, answer, timestamp, err := c.reader.LatestTransmissionDetails(ctx) + if err != nil { + return errors.Wrap(err, "couldn't fetch latest transmission details") + } + + c.tdLock.Lock() + defer c.tdLock.Unlock() + c.tdLastCheckedAt = time.Now() + c.transmissionDetails = TransmissionDetails{ + Digest: digest, + Epoch: epoch, + Round: round, + LatestAnswer: answer, + LatestTimestamp: timestamp, + } + + c.lggr.Debugw("transmission cache update", "details", c.transmissionDetails) + + return nil +} + +func (c *transmissionsCache) Start() error { + ctx, cancel := utils.ContextFromChan(c.stop) + defer cancel() + if err := c.updateTransmission(ctx); err != nil { + c.lggr.Warnf("failed to populate initial transmission details: %v", err) + } + go c.poll() + return nil +} + +func (c *transmissionsCache) Close() error { + close(c.stop) + return nil +} + +func (c *transmissionsCache) poll() { + defer close(c.done) + tick := time.After(0) + for { + select { + case <-c.stop: + return + case <-tick: + ctx, cancel := utils.ContextFromChan(c.stop) + + if err := c.updateTransmission(ctx); err != nil { + c.lggr.Errorf("Failed to update transmission: %v", err) + } + cancel() + + tick = time.After(utils.WithJitter(c.cfg.OCR2CachePollPeriod())) + } + } +} + +func (c *transmissionsCache) LatestTransmissionDetails( + ctx context.Context, +) ( + configDigest types.ConfigDigest, + epoch uint32, + round uint8, + latestAnswer *big.Int, + latestTimestamp time.Time, + err error, +) { + c.tdLock.RLock() + defer c.tdLock.RUnlock() + configDigest = c.transmissionDetails.Digest + epoch = c.transmissionDetails.Epoch + round = c.transmissionDetails.Round + latestAnswer = c.transmissionDetails.LatestAnswer + latestTimestamp = c.transmissionDetails.LatestTimestamp + err = c.assertTransmissionsNotStale() + return +} + +func (c *transmissionsCache) LatestRoundRequested( + ctx context.Context, + lookback time.Duration, +) ( + configDigest types.ConfigDigest, + epoch uint32, + round uint8, + err error, +) { + c.tdLock.RLock() + defer c.tdLock.RUnlock() + configDigest = c.transmissionDetails.Digest + epoch = c.transmissionDetails.Epoch + round = c.transmissionDetails.Round + err = c.assertTransmissionsNotStale() + return +} + +func (c *transmissionsCache) assertTransmissionsNotStale() error { + if c.tdLastCheckedAt.IsZero() { + return errors.New("transmissions cache not yet initialized") + } + + if since := time.Since(c.tdLastCheckedAt); since > c.cfg.OCR2CacheTTL() { + return fmt.Errorf("transmissions cache expired: checked last %s ago", since) + } + + return nil +} diff --git a/relayer/pkg/plugin/ocr2/types.go b/relayer/pkg/plugin/ocr2/types.go new file mode 100644 index 0000000..d1e4329 --- /dev/null +++ b/relayer/pkg/plugin/ocr2/types.go @@ -0,0 +1,96 @@ +package ocr2 + +import ( + "fmt" + "math" + "math/big" + "time" + + "github.com/pkg/errors" + + junotypes "github.com/NethermindEth/juno/pkg/types" + + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +type ContractConfigDetails struct { + Block uint64 + Digest types.ConfigDigest +} + +func NewContractConfigDetails(blockFelt junotypes.Felt, digestFelt junotypes.Felt) (ccd ContractConfigDetails, err error) { + block := blockFelt.Big() + + digest, err := types.BytesToConfigDigest(digestFelt.Bytes()) + if err != nil { + return ccd, errors.Wrap(err, "couldn't decode config digest") + } + + return ContractConfigDetails{ + Block: block.Uint64(), + Digest: digest, + }, nil +} + +type ContractConfig struct { + Config types.ContractConfig + ConfigBlock uint64 +} + +type TransmissionDetails struct { + Digest types.ConfigDigest + Epoch uint32 + Round uint8 + LatestAnswer *big.Int + LatestTimestamp time.Time +} + +type BillingDetails struct { + ObservationPaymentGJuels uint64 + TransmissionPaymentGJuels uint64 +} + +func NewBillingDetails(observationPaymentFelt junotypes.Felt, transmissionPaymentFelt junotypes.Felt) (bd BillingDetails, err error) { + observationPaymentGJuels := observationPaymentFelt.Big() + transmissionPaymentGJuels := transmissionPaymentFelt.Big() + + return BillingDetails{ + ObservationPaymentGJuels: observationPaymentGJuels.Uint64(), + TransmissionPaymentGJuels: transmissionPaymentGJuels.Uint64(), + }, nil +} + +type RoundData struct { + RoundID uint32 + Answer *big.Int + BlockNumber uint64 + StartedAt time.Time + UpdatedAt time.Time +} + +func NewRoundData(felts []junotypes.Felt) (data RoundData, err error) { + if len(felts) != 5 { + return data, fmt.Errorf("expected number of felts to be 5 but got %d", len(felts)) + } + if !felts[0].Big().IsUint64() && felts[0].Big().Uint64() > math.MaxUint32 { + return data, fmt.Errorf("aggregator round id does not fit in a uint32 '%s'", felts[0].Big()) + } + data.RoundID = uint32(felts[0].Big().Uint64()) + data.Answer = felts[1].Big() + blockNumber := felts[2].Big() + if !blockNumber.IsUint64() { + return data, fmt.Errorf("block number '%s' does not fit into uint64", blockNumber.String()) + } + data.BlockNumber = blockNumber.Uint64() + startedAt := felts[3].Big() + if !startedAt.IsInt64() { + return data, fmt.Errorf("startedAt '%s' does not fit into int64", startedAt.String()) + } + data.StartedAt = time.Unix(startedAt.Int64(), 0) + updatedAt := felts[4].Big() + if !updatedAt.IsInt64() { + return data, fmt.Errorf("updatedAt '%s' does not fit into int64", startedAt.String()) + } + data.UpdatedAt = time.Unix(updatedAt.Int64(), 0) + return data, nil +} diff --git a/relayer/pkg/plugin/ocr2/types_test.go b/relayer/pkg/plugin/ocr2/types_test.go new file mode 100644 index 0000000..5cbdecb --- /dev/null +++ b/relayer/pkg/plugin/ocr2/types_test.go @@ -0,0 +1,40 @@ +package ocr2 + +import ( + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +func TestNewRoundData(t *testing.T) { + raw := []string{ + "0x121e", + "0x800000000000010ffffffffffffffffffffffffffffffffffffffffca5b1701", + "0x1087", + "0x633344a3", + "0x633344a5", + } + + felts := starknet.StringsToJunoFelts(raw) + actualRound, err := NewRoundData(felts) + require.NoError(t, err) + expectedRound := RoundData{ + RoundID: 0x121e, + Answer: bigIntFromString("3618502788666131213697322783095070105623107215331596699973092056134972020481"), + BlockNumber: 0x1087, + StartedAt: time.Unix(int64(0x633344a3), 0), + UpdatedAt: time.Unix(int64(0x633344a5), 0), + } + require.Equal(t, expectedRound, actualRound) +} + +// Helpers + +func bigIntFromString(s string) *big.Int { + out, _ := new(big.Int).SetString(s, 10) + return out +} diff --git a/relayer/pkg/plugin/ocr2/utils.go b/relayer/pkg/plugin/ocr2/utils.go new file mode 100644 index 0000000..de402bf --- /dev/null +++ b/relayer/pkg/plugin/ocr2/utils.go @@ -0,0 +1,27 @@ +package ocr2 + +import ( + "encoding/binary" + "math/big" + + junotypes "github.com/NethermindEth/juno/pkg/types" + "github.com/goplugin/plugin-libocr/offchainreporting2/types" +) + +func parseEpochAndRound(felt *big.Int) (epoch uint32, round uint8) { + var epochAndRound [junotypes.FeltLength]byte + felt.FillBytes(epochAndRound[:]) + epoch = binary.BigEndian.Uint32(epochAndRound[junotypes.FeltLength-5 : junotypes.FeltLength-1]) + round = epochAndRound[junotypes.FeltLength-1] + return epoch, round +} + +/* Testing utils - do not use (XXX) outside testing context */ + +func XXXMustBytesToConfigDigest(b []byte) types.ConfigDigest { + c, err := types.BytesToConfigDigest(b) + if err != nil { + panic(err) + } + return c +} diff --git a/relayer/pkg/plugin/relay.go b/relayer/pkg/plugin/relay.go new file mode 100644 index 0000000..435515d --- /dev/null +++ b/relayer/pkg/plugin/relay.go @@ -0,0 +1,117 @@ +package plugin + +import ( + "context" + "encoding/json" + + "github.com/pkg/errors" + + starkchain "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/chain" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/ocr2" + + "github.com/goplugin/plugin-relay/pkg/logger" + relaytypes "github.com/goplugin/plugin-relay/pkg/types" +) + +var _ relaytypes.Relayer = (*relayer)(nil) + +type relayer struct { + chainSet starkchain.ChainSet + ctx context.Context + + lggr logger.Logger + + cancel func() +} + +func NewRelayer(lggr logger.Logger, chainSet starkchain.ChainSet) *relayer { + ctx, cancel := context.WithCancel(context.Background()) + return &relayer{ + chainSet: chainSet, + ctx: ctx, + lggr: lggr, + cancel: cancel, + } +} + +func (r *relayer) Name() string { + return r.lggr.Name() +} + +func (r *relayer) Start(context.Context) error { + return nil +} + +func (r *relayer) Close() error { + r.cancel() + return nil +} + +func (r *relayer) Ready() error { + return r.chainSet.Ready() +} + +func (r *relayer) Healthy() error { return nil } + +func (r *relayer) HealthReport() map[string]error { + return map[string]error{r.Name(): r.Healthy()} +} + +func (r *relayer) NewConfigProvider(args relaytypes.RelayArgs) (relaytypes.ConfigProvider, error) { + var relayConfig RelayConfig + + err := json.Unmarshal(args.RelayConfig, &relayConfig) + if err != nil { + return nil, errors.Wrap(err, "couldn't unmarshal RelayConfig") + } + + chain, err := r.chainSet.Chain(r.ctx, relayConfig.ChainID) + if err != nil { + return nil, errors.Wrap(err, "couldn't initilize Chain") + } + + reader, err := chain.Reader() + if err != nil { + return nil, errors.Wrap(err, "error in NewConfigProvider chain.Reader") + } + configProvider, err := ocr2.NewConfigProvider(relayConfig.ChainID, args.ContractID, reader, chain.Config(), r.lggr) + if err != nil { + return nil, errors.Wrap(err, "coudln't initialize ConfigProvider") + } + + return configProvider, nil +} + +func (r *relayer) NewMedianProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (relaytypes.MedianProvider, error) { + var relayConfig RelayConfig + + err := json.Unmarshal(rargs.RelayConfig, &relayConfig) + if err != nil { + return nil, errors.Wrap(err, "couldn't unmarshal RelayConfig") + } + + if relayConfig.AccountAddress == "" { + return nil, errors.New("no account address in relay config") + } + + chain, err := r.chainSet.Chain(r.ctx, relayConfig.ChainID) + if err != nil { + return nil, errors.Wrap(err, "couldn't initilize Chain") + } + + // todo: use pargs for median provider + reader, err := chain.Reader() + if err != nil { + return nil, errors.Wrap(err, "error in NewMedianProvider chain.Reader") + } + medianProvider, err := ocr2.NewMedianProvider(relayConfig.ChainID, rargs.ContractID, pargs.TransmitterID, relayConfig.AccountAddress, reader, chain.Config(), chain.TxManager(), r.lggr) + if err != nil { + return nil, errors.Wrap(err, "couldn't initilize MedianProvider") + } + + return medianProvider, nil +} + +func (r *relayer) NewMercuryProvider(rargs relaytypes.RelayArgs, pargs relaytypes.PluginArgs) (relaytypes.MercuryProvider, error) { + return nil, errors.New("mercury is not supported for starknet") +} diff --git a/relayer/pkg/plugin/txm/config.go b/relayer/pkg/plugin/txm/config.go new file mode 100644 index 0000000..925386b --- /dev/null +++ b/relayer/pkg/plugin/txm/config.go @@ -0,0 +1,12 @@ +package txm + +import "time" + +//go:generate mockery --name Config --output ./mocks/ --case=underscore --filename config.go + +// txm config +type Config interface { + TxTimeout() time.Duration + TxSendFrequency() time.Duration + TxMaxBatchSize() int +} diff --git a/relayer/pkg/plugin/txm/mocks/config.go b/relayer/pkg/plugin/txm/mocks/config.go new file mode 100644 index 0000000..497bf9b --- /dev/null +++ b/relayer/pkg/plugin/txm/mocks/config.go @@ -0,0 +1,71 @@ +// Code generated by mockery v2.13.0-beta.1. DO NOT EDIT. + +package mocks + +import ( + time "time" + + mock "github.com/stretchr/testify/mock" +) + +// Config is an autogenerated mock type for the Config type +type Config struct { + mock.Mock +} + +// TxMaxBatchSize provides a mock function with given fields: +func (_m *Config) TxMaxBatchSize() int { + ret := _m.Called() + + var r0 int + if rf, ok := ret.Get(0).(func() int); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int) + } + + return r0 +} + +// TxSendFrequency provides a mock function with given fields: +func (_m *Config) TxSendFrequency() time.Duration { + ret := _m.Called() + + var r0 time.Duration + if rf, ok := ret.Get(0).(func() time.Duration); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Duration) + } + + return r0 +} + +// TxTimeout provides a mock function with given fields: +func (_m *Config) TxTimeout() time.Duration { + ret := _m.Called() + + var r0 time.Duration + if rf, ok := ret.Get(0).(func() time.Duration); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Duration) + } + + return r0 +} + +type NewConfigT interface { + mock.TestingT + Cleanup(func()) +} + +// NewConfig creates a new instance of Config. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewConfig(t NewConfigT) *Config { + mock := &Config{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/relayer/pkg/plugin/txm/test_helpers.go b/relayer/pkg/plugin/txm/test_helpers.go new file mode 100644 index 0000000..ba3bd4a --- /dev/null +++ b/relayer/pkg/plugin/txm/test_helpers.go @@ -0,0 +1,90 @@ +package txm + +import ( + "bytes" + "math/big" + "net/http" + "os/exec" + "testing" + "time" + + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-relay/pkg/utils" +) + +var ( + // seed = 0 keys for starknet-devnet + PrivateKeys0Seed = []string{ + "0xe3e70682c2094cac629f6fbed82c07cd", + "0xf728b4fa42485e3a0a5d2f346baa9455", + "0xeb1167b367a9c3787c65c1e582e2e662", + "0xf7c1bd874da5e709d4713d60c8a70639", + "0xe443df789558867f5ba91faf7a024204", + "0x23a7711a8133287637ebdcd9e87a1613", + "0x1846d424c17c627923c6612f48268673", + "0xfcbd04c340212ef7cca5a5a19e4d6e3c", + "0xb4862b21fb97d43588561712e8e5216a", + "0x259f4329e6f4590b9a164106cf6a659e", + } + + // devnet key derivation + // https://github.com/Shard-Labs/starknet-devnet/blob/master/starknet_devnet/account.py + DevnetClassHash, _ = new(big.Int).SetString("1803505466663265559571280894381905521939782500874858933595227108099796801620", 10) + DevnetSalt = big.NewInt(20) +) + +// SetupLocalStarknetNode sets up a local starknet node via cli, and returns the url +func SetupLocalStarknetNode(t *testing.T) string { + port := utils.MustRandomPort(t) + url := "http://127.0.0.1:" + port + cmd := exec.Command("starknet-devnet", + "--seed", "0", // use same seed for testing + "--port", port, + "--lite-mode", + ) + var stdErr bytes.Buffer + cmd.Stderr = &stdErr + require.NoError(t, cmd.Start()) + t.Cleanup(func() { + assert.NoError(t, cmd.Process.Kill()) + if err2 := cmd.Wait(); assert.Error(t, err2) { + if !assert.Contains(t, err2.Error(), "signal: killed", cmd.ProcessState.String()) { + t.Log("starknet-devnet stderr:", stdErr.String()) + } + } + t.Log("starknet-devnet server closed") + }) + + // Wait for api server to boot + var ready bool + for i := 0; i < 30; i++ { + time.Sleep(time.Second) + res, err := http.Get(url + "/is_alive") + if err != nil || res.StatusCode != 200 { + t.Logf("API server not ready yet (attempt %d)\n", i+1) + continue + } + ready = true + t.Logf("API server ready at %s\n", url) + break + } + require.True(t, ready) + return url +} + +func TestKeys(t *testing.T, count int) (rawkeys [][]byte) { + require.True(t, len(PrivateKeys0Seed) >= count, "requested more keys than available") + for i, k := range PrivateKeys0Seed { + // max number of keys to generate + if i >= count { + break + } + + keyBytes := caigotypes.HexToHash(k).Bytes() + rawkeys = append(rawkeys, keyBytes) + } + return rawkeys +} diff --git a/relayer/pkg/plugin/txm/txm.go b/relayer/pkg/plugin/txm/txm.go new file mode 100644 index 0000000..6d87312 --- /dev/null +++ b/relayer/pkg/plugin/txm/txm.go @@ -0,0 +1,231 @@ +package txm + +import ( + "context" + "math/big" + "sync" + "time" + + "github.com/smartcontractkit/caigo" + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/pkg/errors" + + "github.com/goplugin/plugin-relay/pkg/logger" + relaytypes "github.com/goplugin/plugin-relay/pkg/types" + "github.com/goplugin/plugin-relay/pkg/utils" + + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/keys" +) + +const ( + MaxQueueLen = 1000 +) + +type TxManager interface { + Enqueue(caigotypes.Hash, caigotypes.Hash, caigotypes.FunctionCall) error +} + +type Tx struct { + senderAddress caigotypes.Hash + accountAddress caigotypes.Hash + call caigotypes.FunctionCall +} + +type StarkTXM interface { + relaytypes.Service + TxManager +} + +type starktxm struct { + starter utils.StartStopOnce + lggr logger.Logger + done sync.WaitGroup + stop chan struct{} + queue chan Tx + ks keys.Keystore + cfg Config + + // TODO: use lazy loaded client + client *starknet.Client + getClient func() (*starknet.Client, error) +} + +func New(lggr logger.Logger, keystore keys.Keystore, cfg Config, getClient func() (*starknet.Client, error)) (StarkTXM, error) { + return &starktxm{ + lggr: logger.Named(lggr, "StarknetTxm"), + queue: make(chan Tx, MaxQueueLen), + stop: make(chan struct{}), + getClient: getClient, + ks: keystore, + cfg: cfg, + }, nil +} + +func (txm *starktxm) Name() string { + return txm.lggr.Name() +} + +func (txm *starktxm) Start(ctx context.Context) error { + return txm.starter.StartOnce("starktxm", func() error { + txm.done.Add(1) // waitgroup: tx sender + go txm.run() + return nil + }) +} + +func (txm *starktxm) run() { + defer txm.done.Done() + + // TODO: func not available without importing core + // ctx, cancel := utils.ContextFromChan(txm.stop) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + tick := time.After(0) + + for { + select { + case <-tick: + start := time.Now() + + // fetch client if needed (before processing txs to preserve queue) + if txm.client == nil { + var err error + txm.client, err = txm.getClient() + if err != nil { + txm.lggr.Errorw("unable to fetch client", "error", err) + tick = time.After(utils.WithJitter(txm.cfg.TxSendFrequency()) - time.Since(start)) // reset tick + txm.client = nil // reset + continue + } + } + + // calculate total txs to process + txLen := len(txm.queue) + if txLen > txm.cfg.TxMaxBatchSize() { + txLen = txm.cfg.TxMaxBatchSize() + } + + type senderAccountPair struct { + senderAddress caigotypes.Hash + accountAddress caigotypes.Hash + } + + // split the transactions by sender and account address for batching. + // this avoids assuming that there is always a 1:1 mapping from sender addresses + // onto account addresses. + txsByAccount := map[senderAccountPair][]caigotypes.FunctionCall{} + for i := 0; i < txLen; i++ { + tx := <-txm.queue + key := senderAccountPair{ + senderAddress: tx.senderAddress, + accountAddress: tx.accountAddress, + } + txsByAccount[key] = append(txsByAccount[key], tx.call) + } + txm.lggr.Infow("creating batch", "totalTxCount", txLen, "batchCount", len(txsByAccount)) + txm.lggr.Debugw("batch details", "batches", txsByAccount) + + // async process of tx batches + var wg sync.WaitGroup + wg.Add(len(txsByAccount)) + for key, txs := range txsByAccount { + go func(senderAddress caigotypes.Hash, accountAddress caigotypes.Hash, txs []caigotypes.FunctionCall) { + // fetch key matching sender address + key, err := txm.ks.Get(senderAddress.String()) + if err != nil { + txm.lggr.Errorw("failed to retrieve key", "id", senderAddress, "error", err) + } else { + // parse key to expected format + privKeyBytes := key.Raw() + privKey := caigotypes.BigToHex(caigotypes.BytesToBig(privKeyBytes)) + + // broadcast batch based on account address + hash, err := txm.broadcastBatch(ctx, privKey, accountAddress, txs) + if err != nil { + txm.lggr.Errorw("transaction failed to broadcast", "error", err, "account", accountAddress, "batchTx", txs) + } else { + txm.lggr.Infow("transaction broadcast", "txhash", hash) + } + } + wg.Done() + }(key.senderAddress, key.accountAddress, txs) + } + wg.Wait() + tick = time.After(utils.WithJitter(txm.cfg.TxSendFrequency()) - time.Since(start)) + case <-txm.stop: + return + } + } +} + +const FEE_MARGIN uint64 = 115 + +func (txm *starktxm) broadcastBatch(ctx context.Context, privKey string, accountAddress caigotypes.Hash, txs []caigotypes.FunctionCall) (txhash string, err error) { + // create new account + account, err := caigo.NewGatewayAccount(privKey, accountAddress.String(), txm.client.Gw, caigo.AccountVersion1) + if err != nil { + return txhash, errors.Errorf("failed to create new account: %s", err) + } + + // get fee for txm + feeEstimate, err := account.EstimateFee(ctx, txs, caigotypes.ExecuteDetails{}) + if err != nil { + return txhash, errors.Errorf("failed to estimate fee: %s", err) + } + + fee, _ := big.NewInt(0).SetString(string(feeEstimate.OverallFee), 0) + expandedFee := big.NewInt(0).Mul(fee, big.NewInt(int64(FEE_MARGIN))) + max := big.NewInt(0).Div(expandedFee, big.NewInt(100)) + details := caigotypes.ExecuteDetails{ + MaxFee: max, + } + + // TODO: investigate if nonce management is needed (nonce is requested queried by the sdk for now) + // transmit txs + execCtx, execCancel := context.WithTimeout(ctx, txm.cfg.TxTimeout()*time.Second) + defer execCancel() + res, err := account.Execute(execCtx, txs, details) + if err != nil { + return txhash, errors.Errorf("failed to invoke tx: %s", err) + } + + // handle nil pointer + if res == nil { + return txhash, errors.New("execute response and error are nil") + } + + return res.TransactionHash, nil +} + +func (txm *starktxm) Close() error { + return txm.starter.StopOnce("starktxm", func() error { + close(txm.stop) + txm.done.Wait() + return nil + }) +} + +func (txm *starktxm) Healthy() error { + return txm.starter.Healthy() +} + +func (txm *starktxm) Ready() error { + return txm.starter.Ready() +} + +func (txm *starktxm) HealthReport() map[string]error { + return map[string]error{txm.Name(): txm.Healthy()} +} + +func (txm *starktxm) Enqueue(senderAddress caigotypes.Hash, accountAddress caigotypes.Hash, tx caigotypes.FunctionCall) error { + select { + case txm.queue <- Tx{senderAddress: senderAddress, accountAddress: accountAddress, call: tx}: + default: + return errors.Errorf("failed to enqueue transaction: %+v", tx) + } + + return nil +} diff --git a/relayer/pkg/plugin/txm/txm_test.go b/relayer/pkg/plugin/txm/txm_test.go new file mode 100644 index 0000000..d30305a --- /dev/null +++ b/relayer/pkg/plugin/txm/txm_test.go @@ -0,0 +1,108 @@ +//go:build integration + +package txm + +import ( + "context" + "encoding/hex" + "sync" + "testing" + "time" + + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/pkg/errors" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-relay/pkg/logger" + + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/keys" + "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/keys/mocks" + txmmock "github.com/goplugin/plugin-starknet/relayer/pkg/plugin/txm/mocks" + "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" +) + +func TestIntegration_Txm(t *testing.T) { + url := SetupLocalStarknetNode(t) + rawLocalKeys := TestKeys(t, 2) // generate 2 keys + + // parse keys into expected format + localKeys := map[string]keys.Key{} + for _, k := range rawLocalKeys { + key := keys.Raw(k).Key() + account := "0x" + hex.EncodeToString(keys.PubKeyToAccount(key.PublicKey(), DevnetClassHash, DevnetSalt)) + localKeys[account] = key + } + + // mock keystore + ks := new(mocks.Keystore) + ks.On("Get", mock.AnythingOfType("string")).Return( + func(id string) keys.Key { + return localKeys[id] + }, + func(id string) error { + + _, ok := localKeys[id] + if !ok { + return errors.New("key does not exist") + } + return nil + }, + ) + + lggr, err := logger.New() + require.NoError(t, err) + timeout := 10 * time.Second + client, err := starknet.NewClient("devnet", url, lggr, &timeout) + require.NoError(t, err) + + // test fail first client + failed := false + var wg sync.WaitGroup + wg.Add(2) + + // should be called twice + getClient := func() (*starknet.Client, error) { + wg.Done() + if !failed { + failed = true + + // test return not nil + return &starknet.Client{}, errors.New("random test error") + } + + return client, nil + } + + // mock config to prevent import cycle + cfg := new(txmmock.Config) + cfg.On("TxMaxBatchSize").Return(100) + cfg.On("TxSendFrequency").Return(15 * time.Second) + cfg.On("TxTimeout").Return(10 * time.Second) + + txm, err := New(lggr, ks, cfg, getClient) + require.NoError(t, err) + + // ready fail if start not called + require.Error(t, txm.Ready()) + + // start txm + checks + require.NoError(t, txm.Start(context.Background())) + require.NoError(t, txm.Ready()) + + for k := range localKeys { + key := caigotypes.HexToHash(k) + for i := 0; i < 5; i++ { + require.NoError(t, txm.Enqueue(key, key, caigotypes.FunctionCall{ + ContractAddress: key, // send to self + EntryPointSelector: "get_nonce", + })) + } + } + time.Sleep(30 * time.Second) + wg.Wait() + + // stop txm + require.NoError(t, txm.Close()) + require.Error(t, txm.Ready()) +} diff --git a/relayer/pkg/plugin/types.go b/relayer/pkg/plugin/types.go new file mode 100644 index 0000000..baf7b3b --- /dev/null +++ b/relayer/pkg/plugin/types.go @@ -0,0 +1,8 @@ +package plugin + +// [relayConfig] member of Plugin's job spec v2 (OCR2 only currently) +type RelayConfig struct { + ChainID string `json:"chainID"` + AccountAddress string `json:"accountAddress"` // address of the account contract + NodeName string `json:"nodeName"` // optional, defaults to random node with 'chainID' +} diff --git a/relayer/pkg/starknet/client.go b/relayer/pkg/starknet/client.go new file mode 100644 index 0000000..e65b076 --- /dev/null +++ b/relayer/pkg/starknet/client.go @@ -0,0 +1,297 @@ +package starknet + +import ( + "context" + "math/big" + "time" + + "github.com/pkg/errors" + + caigogw "github.com/smartcontractkit/caigo/gateway" + caigotypes "github.com/smartcontractkit/caigo/types" + + "github.com/goplugin/plugin-relay/pkg/logger" +) + +//go:generate mockery --name Reader --output ./mocks/ + +type Reader interface { + CallContract(context.Context, CallOps) ([]string, error) + LatestBlockHeight(context.Context) (uint64, error) + BlockByNumberGateway(context.Context, uint64) (*caigogw.Block, error) + + // provider interface + BlockByHash(context.Context, string, string) (*caigogw.Block, error) + BlockByNumber(context.Context, *big.Int, string) (*caigogw.Block, error) + Call(context.Context, caigotypes.FunctionCall, string) ([]string, error) + ChainID(context.Context) (string, error) +} + +type Writer interface { + AccountNonce(context.Context, caigotypes.Hash) (*big.Int, error) + Invoke(context.Context, caigotypes.FunctionInvoke) (*caigotypes.AddInvokeTransactionOutput, error) + TransactionByHash(context.Context, string) (*caigogw.Transaction, error) + TransactionReceipt(context.Context, string) (*caigogw.TransactionReceipt, error) + EstimateFee(context.Context, caigotypes.FunctionInvoke, string) (*caigotypes.FeeEstimate, error) +} + +type ReaderWriter interface { + Reader + Writer +} + +var _ ReaderWriter = (*Client)(nil) + +// var _ caigotypes.Provider = (*Client)(nil) + +type Client struct { + Gw *caigogw.GatewayProvider + lggr logger.Logger + defaultTimeout time.Duration +} + +// pass nil or 0 to timeout to not use built in default timeout +func NewClient(chainID string, baseURL string, lggr logger.Logger, timeout *time.Duration) (*Client, error) { + client := &Client{ + Gw: caigogw.NewProvider(caigogw.WithChain(chainID)), + lggr: lggr, + } + + // make copy to preserve value + // defensive in case the timeout reference is ever garbage collected or removed + if timeout == nil { + client.defaultTimeout = 0 + } else { + client.defaultTimeout = *timeout + } + + client.set(baseURL, chainID) // hack: change the base URL & chainID (not supported in caigo) + + return client, nil +} + +func (c *Client) set(baseURL, chainID string) { + if chainID != "" { + c.Gw.Gateway.ChainId = chainID // note: gateway API in caigo does not query endpoint, uses what is set + } + + if baseURL != "" { + c.Gw.Gateway.Base = baseURL + c.Gw.Gateway.Feeder = baseURL + "/feeder_gateway" + c.Gw.Gateway.Gateway = baseURL + "/gateway" + } +} + +// -- Custom Wrapped Func -- + +func (c *Client) CallContract(ctx context.Context, ops CallOps) (res []string, err error) { + tx := caigotypes.FunctionCall{ + ContractAddress: ops.ContractAddress, + EntryPointSelector: ops.Selector, + Calldata: ops.Calldata, + } + + res, err = c.Call(ctx, tx, "") + if err != nil { + return res, errors.Wrap(err, "error in client.CallContract") + } + + return +} + +func (c *Client) LatestBlockHeight(ctx context.Context) (height uint64, err error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + block, err := c.Gw.Block(ctx, &caigogw.BlockOptions{Tag: "latest"}) + if err != nil { + return height, errors.Wrap(err, "error in client.LatestBlockHeight") + } + + return uint64(block.BlockNumber), nil +} + +func (c *Client) BlockByNumberGateway(ctx context.Context, blockNum uint64) (block *caigogw.Block, err error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + block, err = c.Gw.Block(ctx, &caigogw.BlockOptions{ + BlockNumber: &blockNum, + }) + if err != nil { + return block, errors.Wrap(err, "couldn't get block by number") + } + if block == nil { + return block, NilResultError("client.BlockByNumberGateway") + } + + return block, nil +} + +// -- caigo.Provider interface -- + +func (c *Client) BlockByHash(ctx context.Context, hash string, _ string) (*caigogw.Block, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.BlockByHash(ctx, hash, "") + if err != nil { + return out, errors.Wrap(err, "error in client.BlockByHash") + } + if out == nil { + return out, NilResultError("client.BlockByHash") + } + return out, nil +} + +func (c *Client) BlockByNumber(ctx context.Context, num *big.Int, _ string) (*caigogw.Block, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.BlockByNumber(ctx, num, "") + if err != nil { + return out, errors.Wrap(err, "error in client.BlockByNumber") + } + if out == nil { + return out, NilResultError("client.BlockByNumber") + } + return out, nil + +} + +func (c *Client) Call(ctx context.Context, calls caigotypes.FunctionCall, blockHashOrTag string) ([]string, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.Call(ctx, calls, blockHashOrTag) + if err != nil { + return out, errors.Wrap(err, "error in client.Call") + } + if out == nil { + return out, NilResultError("client.Call") + } + return out, nil + +} + +func (c *Client) ChainID(ctx context.Context) (string, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.ChainID(ctx) + if err != nil { + return out, errors.Wrap(err, "error in client.ChainID") + } + return out, nil + +} + +func (c *Client) AccountNonce(ctx context.Context, address caigotypes.Hash) (*big.Int, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.AccountNonce(ctx, address) + if err != nil { + return out, errors.Wrap(err, "error in client.AccountNonce") + } + + if out == nil { + return out, NilResultError("client.AccountNonce") + } + + return out, nil + +} + +func (c *Client) Invoke(ctx context.Context, invoke caigotypes.FunctionInvoke) (*caigotypes.AddInvokeTransactionOutput, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.Invoke(ctx, invoke) + if err != nil { + return out, errors.Wrap(err, "error in client.Invoke") + } + if out == nil { + return out, NilResultError("client.Invoke") + } + return out, nil + +} + +func (c *Client) TransactionByHash(ctx context.Context, hash string) (*caigogw.Transaction, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.TransactionByHash(ctx, hash) + if err != nil { + return out, errors.Wrap(err, "error in client.TransactionByHash") + } + if out == nil { + return out, NilResultError("client.TransactionByHash") + } + return out, nil + +} + +func (c *Client) TransactionReceipt(ctx context.Context, hash string) (*caigogw.TransactionReceipt, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.TransactionReceipt(ctx, hash) + if err != nil { + return out, errors.Wrap(err, "error in client.TransactionReceipt") + } + if out == nil { + return out, NilResultError("client.TransactionReceipt") + } + return out, nil + +} + +func (c *Client) EstimateFee(ctx context.Context, call caigotypes.FunctionInvoke, hash string) (*caigotypes.FeeEstimate, error) { + if c.defaultTimeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.defaultTimeout) + defer cancel() + } + + out, err := c.Gw.EstimateFee(ctx, call, hash) + if err != nil { + return out, errors.Wrap(err, "error in client.EstimateFee") + } + if out == nil { + return out, NilResultError("client.EstimateFee") + } + return out, nil + +} diff --git a/relayer/pkg/starknet/client_test.go b/relayer/pkg/starknet/client_test.go new file mode 100644 index 0000000..9607103 --- /dev/null +++ b/relayer/pkg/starknet/client_test.go @@ -0,0 +1,69 @@ +package starknet + +import ( + "context" + "net/http" + "net/http/httptest" + "sync" + "testing" + "time" + + "github.com/smartcontractkit/caigo/gateway" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/goplugin/plugin-relay/pkg/logger" +) + +var ( + chainID = gateway.GOERLI_ID + timeout = 10 * time.Second +) + +func TestGatewayClient(t *testing.T) { + var wg sync.WaitGroup + wg.Add(1) // mock endpoint only called once + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte(`{"parent_block_hash": "0x0", "status": "ACCEPTED_ON_L2", "timestamp": 1660840417, "gas_price": "0x174876e800", "sequencer_address": "0x4bbfb0d1aab5bf33eec5ada3a1040c41ed902a1eeb38c78a753d6f6359f1666", "transactions": [], "transaction_receipts": [], "state_root": "030c9b7339aabef2d6c293c40d4f0ec6ffae303cb7df5b705dce7acc00306b06", "starknet_version": "0.9.1", "block_hash": "0x0", "block_number": 0}`)) + require.NoError(t, err) + wg.Done() + })) + defer mockServer.Close() + + lggr := logger.Test(t) + client, err := NewClient(chainID, mockServer.URL, lggr, &timeout) + require.NoError(t, err) + assert.Equal(t, timeout, client.defaultTimeout) + + // does not call endpoint - chainID returned from gateway client + t.Run("get chain id", func(t *testing.T) { + id, err := client.ChainID(context.Background()) + assert.NoError(t, err) + assert.Equal(t, id, chainID) + }) + + t.Run("get block height", func(t *testing.T) { + _, err := client.LatestBlockHeight(context.Background()) + assert.NoError(t, err) + }) + wg.Wait() +} + +func TestGatewayClient_DefaultTimeout(t *testing.T) { + client, err := NewClient(gateway.GOERLI_ID, "", logger.Test(t), nil) + require.NoError(t, err) + assert.Zero(t, client.defaultTimeout) +} + +func TestGatewayClient_CustomURLChainID(t *testing.T) { + client, err := NewClient("test", "test", logger.Test(t), nil) + require.NoError(t, err) + + id, err := client.ChainID(context.TODO()) + require.NoError(t, err) + assert.Equal(t, "test", id) + + assert.Equal(t, "test", client.Gw.Gateway.Base) + assert.Equal(t, "test/feeder_gateway", client.Gw.Gateway.Feeder) + assert.Equal(t, "test/gateway", client.Gw.Gateway.Gateway) +} diff --git a/relayer/pkg/starknet/events.go b/relayer/pkg/starknet/events.go new file mode 100644 index 0000000..0b64464 --- /dev/null +++ b/relayer/pkg/starknet/events.go @@ -0,0 +1,12 @@ +package starknet + +import ( + caigogw "github.com/smartcontractkit/caigo/gateway" + caigotypes "github.com/smartcontractkit/caigo/types" +) + +func IsEventFromContract(event *caigogw.Event, address caigotypes.Hash, eventName string) bool { + eventKey := caigotypes.GetSelectorFromName(eventName) + // encoded event name guaranteed to be at index 0 + return CompareAddress(event.FromAddress, address.String()) && event.Keys[0].Cmp(eventKey) == 0 +} diff --git a/relayer/pkg/starknet/events_test.go b/relayer/pkg/starknet/events_test.go new file mode 100644 index 0000000..227a928 --- /dev/null +++ b/relayer/pkg/starknet/events_test.go @@ -0,0 +1,35 @@ +package starknet + +import ( + "testing" + + caigogw "github.com/smartcontractkit/caigo/gateway" + caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/stretchr/testify/assert" +) + +var ( + testEventSelector = "transfer" +) + +func TestIsEventFromContract(t *testing.T) { + event := caigogw.Event{ + Order: 0, + FromAddress: "0x00", + Keys: []*caigotypes.Felt{caigotypes.BigToFelt(caigotypes.GetSelectorFromName(testEventSelector))}, + Data: []*caigotypes.Felt{}, + } + + // test zeros + assert.True(t, IsEventFromContract(&event, caigotypes.HexToHash("0x000000"), testEventSelector)) + + // test mismatch selector + assert.False(t, IsEventFromContract(&event, caigotypes.HexToHash("0x00"), "bad_selector")) + + // test mismatch addresses + event.FromAddress = "0x00002432012bcda2bfa339c51b3be731118f2bd3bac6b63c5ca664c154bf636f" + assert.False(t, IsEventFromContract(&event, caigotypes.HexToHash("0x3002432012bcda2bfa339c51b3be731118f2bd3bac6b63c5ca664c154bf6"), testEventSelector)) + + // test different length addresses + assert.True(t, IsEventFromContract(&event, caigotypes.HexToHash("0x2432012bcda2bfa339c51b3be731118f2bd3bac6b63c5ca664c154bf636f"), testEventSelector)) +} diff --git a/relayer/pkg/starknet/mocks/Reader.go b/relayer/pkg/starknet/mocks/Reader.go new file mode 100644 index 0000000..46a7a31 --- /dev/null +++ b/relayer/pkg/starknet/mocks/Reader.go @@ -0,0 +1,193 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + gateway "github.com/smartcontractkit/caigo/gateway" + + mock "github.com/stretchr/testify/mock" + + starknet "github.com/goplugin/plugin-starknet/relayer/pkg/starknet" + + types "github.com/smartcontractkit/caigo/types" +) + +// Reader is an autogenerated mock type for the Reader type +type Reader struct { + mock.Mock +} + +// BlockByHash provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Reader) BlockByHash(_a0 context.Context, _a1 string, _a2 string) (*gateway.Block, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 *gateway.Block + if rf, ok := ret.Get(0).(func(context.Context, string, string) *gateway.Block); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gateway.Block) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BlockByNumber provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Reader) BlockByNumber(_a0 context.Context, _a1 *big.Int, _a2 string) (*gateway.Block, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 *gateway.Block + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, string) *gateway.Block); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gateway.Block) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, string) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BlockByNumberGateway provides a mock function with given fields: _a0, _a1 +func (_m *Reader) BlockByNumberGateway(_a0 context.Context, _a1 uint64) (*gateway.Block, error) { + ret := _m.Called(_a0, _a1) + + var r0 *gateway.Block + if rf, ok := ret.Get(0).(func(context.Context, uint64) *gateway.Block); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gateway.Block) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Call provides a mock function with given fields: _a0, _a1, _a2 +func (_m *Reader) Call(_a0 context.Context, _a1 types.FunctionCall, _a2 string) ([]string, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 []string + if rf, ok := ret.Get(0).(func(context.Context, types.FunctionCall, string) []string); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, types.FunctionCall, string) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CallContract provides a mock function with given fields: _a0, _a1 +func (_m *Reader) CallContract(_a0 context.Context, _a1 starknet.CallOps) ([]string, error) { + ret := _m.Called(_a0, _a1) + + var r0 []string + if rf, ok := ret.Get(0).(func(context.Context, starknet.CallOps) []string); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, starknet.CallOps) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ChainID provides a mock function with given fields: _a0 +func (_m *Reader) ChainID(_a0 context.Context) (string, error) { + ret := _m.Called(_a0) + + var r0 string + if rf, ok := ret.Get(0).(func(context.Context) string); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LatestBlockHeight provides a mock function with given fields: _a0 +func (_m *Reader) LatestBlockHeight(_a0 context.Context) (uint64, error) { + ret := _m.Called(_a0) + + var r0 uint64 + if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(uint64) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewReader interface { + mock.TestingT + Cleanup(func()) +} + +// NewReader creates a new instance of Reader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewReader(t mockConstructorTestingTNewReader) *Reader { + mock := &Reader{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/relayer/pkg/starknet/testdata/fuzz/FuzzEncodeDecodeFelts/8dd7c6d4e51a9d0d2fd249dc251e4b7cc673a85738e29a86310d186cd8e2ce1b b/relayer/pkg/starknet/testdata/fuzz/FuzzEncodeDecodeFelts/8dd7c6d4e51a9d0d2fd249dc251e4b7cc673a85738e29a86310d186cd8e2ce1b new file mode 100644 index 0000000..cf2a1c1 --- /dev/null +++ b/relayer/pkg/starknet/testdata/fuzz/FuzzEncodeDecodeFelts/8dd7c6d4e51a9d0d2fd249dc251e4b7cc673a85738e29a86310d186cd8e2ce1b @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x00") diff --git a/relayer/pkg/starknet/types.go b/relayer/pkg/starknet/types.go new file mode 100644 index 0000000..087dd53 --- /dev/null +++ b/relayer/pkg/starknet/types.go @@ -0,0 +1,11 @@ +package starknet + +import ( + caigotypes "github.com/smartcontractkit/caigo/types" +) + +type CallOps struct { + ContractAddress caigotypes.Hash + Selector string + Calldata []string +} diff --git a/relayer/pkg/starknet/utils.go b/relayer/pkg/starknet/utils.go new file mode 100644 index 0000000..da04cc3 --- /dev/null +++ b/relayer/pkg/starknet/utils.go @@ -0,0 +1,169 @@ +package starknet + +import ( + "bytes" + "encoding/hex" + "fmt" + "math/big" + + junotypes "github.com/NethermindEth/juno/pkg/types" + caigotypes "github.com/smartcontractkit/caigo/types" + + "github.com/pkg/errors" + "golang.org/x/exp/constraints" +) + +const chunkSize = 31 + +// padd bytes to specific length +func PadBytes(a []byte, length int) []byte { + if len(a) < length { + pad := make([]byte, length-len(a)) + return append(pad, a...) + } + + // return original if length is >= to specified length + return a +} + +func NilResultError(funcName string) error { + return fmt.Errorf("nil result in %s", funcName) +} + +func Min[T constraints.Ordered](a, b T) T { + if a < b { + return a + } + return b +} + +// EncodeFelts takes a byte slice and splits as bunch of felts. First felt indicates the total byte size. +func EncodeFelts(data []byte) (felts []*big.Int) { + // prefix with len + length := big.NewInt(int64(len(data))) + felts = append(felts, length) + + // chunk every 31 bytes + for i := 0; i < len(data); i += chunkSize { + chunk := data[i:Min(i+chunkSize, len(data))] + // cast to int + felt := new(big.Int).SetBytes(chunk) + felts = append(felts, felt) + } + + return felts +} + +// DecodeFelts is the reverse of EncodeFelts +func DecodeFelts(felts []*big.Int) ([]byte, error) { + if len(felts) == 0 { + return []byte{}, nil + } + + data := []byte{} + buf := make([]byte, chunkSize) + length := felts[0].Uint64() + + for _, felt := range felts[1:] { + bytesLen := Min(chunkSize, length) + bytesBuffer := buf[:bytesLen] + + // TODO: this is inefficient because Bytes() and FillBytes() duplicate work + // reuse felt.Bytes() + if bytesLen < uint64(len(felt.Bytes())) { + return nil, errors.New("invalid: felt array can't be decoded") + } + + felt.FillBytes(bytesBuffer) + data = append(data, bytesBuffer...) + + length -= uint64(bytesLen) + } + + if length != 0 { + return nil, errors.New("invalid: contained less bytes than the specified length") + } + + return data, nil +} + +// SignedBigToFelt wraps negative values correctly into felt +func SignedBigToFelt(num *big.Int) *big.Int { + return new(big.Int).Mod(num, caigotypes.MaxFelt.Big()) +} + +// FeltToSigned unwraps felt into negative values +func FeltToSignedBig(felt *caigotypes.Felt) (num *big.Int) { + num = felt.Big() + prime := caigotypes.MaxFelt.Big() + half := new(big.Int).Div(prime, big.NewInt(2)) + // if num > PRIME/2, then -PRIME to convert to negative value + if num.Cmp(half) > 0 { + return new(big.Int).Sub(num, prime) + } + return num +} + +func HexToSignedBig(str string) (num *big.Int) { + felt := junotypes.HexToFelt(str) + return FeltToSignedBig(&caigotypes.Felt{Int: felt.Big()}) +} + +func FeltsToBig(in []*caigotypes.Felt) (out []*big.Int) { + for _, f := range in { + out = append(out, f.Int) + } + + return out +} + +// StringsToFelt maps felts from 'string' (hex) representation to 'caigo.Felt' representation +func StringsToFelt(in []string) (out []*caigotypes.Felt, _ error) { + if in == nil { + return nil, errors.New("invalid: input value") + } + + for _, f := range in { + felt := caigotypes.StrToFelt(f) + if felt == nil { + return nil, errors.New("invalid: string value") + } + + out = append(out, felt) + } + + return out, nil +} + +func StringsToJunoFelts(in []string) []junotypes.Felt { + out := make([]junotypes.Felt, len(in)) + for i := 0; i < len(in); i++ { + out[i] = junotypes.HexToFelt(in[i]) + } + return out +} + +// CompareAddress compares different hex starknet addresses with potentially different 0 padding +func CompareAddress(a, b string) bool { + aBytes, err := caigotypes.HexToBytes(a) + if err != nil { + return false + } + + bBytes, err := caigotypes.HexToBytes(b) + if err != nil { + return false + } + + return bytes.Equal(PadBytes(aBytes, 32), PadBytes(bBytes, 32)) +} + +/* Testing utils - do not use (XXX) outside testing context */ + +func XXXMustHexDecodeString(data string) []byte { + bytes, err := hex.DecodeString(data) + if err != nil { + panic(err) + } + return bytes +} diff --git a/relayer/pkg/starknet/utils_fuzz_test.go b/relayer/pkg/starknet/utils_fuzz_test.go new file mode 100644 index 0000000..56a353f --- /dev/null +++ b/relayer/pkg/starknet/utils_fuzz_test.go @@ -0,0 +1,21 @@ +//go:build go1.18 +// +build go1.18 + +package starknet + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func FuzzEncodeDecodeFelts(f *testing.F) { + f.Add([]byte{1, 2, 3}) + f.Fuzz(func(t *testing.T, data []byte) { + encodedData := EncodeFelts(data) + decodedData, err := DecodeFelts(encodedData) + require.NoError(t, err) + + require.Equal(t, data, decodedData) + }) +} diff --git a/relayer/pkg/starknet/utils_test.go b/relayer/pkg/starknet/utils_test.go new file mode 100644 index 0000000..52aa506 --- /dev/null +++ b/relayer/pkg/starknet/utils_test.go @@ -0,0 +1,142 @@ +package starknet + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + lengths = []int{1, 31, 32, 40} + length = 32 +) + +func TestPadBytes(t *testing.T) { + for i, v := range lengths { + + // generate random + in := make([]byte, v) + _, err := rand.Read(in) + require.NoError(t, err) + require.Equal(t, lengths[i], len(in)) + + out := PadBytes(in, length) + expectLen := length + if v > expectLen { + expectLen = v + } + assert.Equal(t, expectLen, len(out)) + + start := 0 + if v < length { + start = length - v + } + assert.Equal(t, in, out[start:]) + } +} + +func TestHexToSignedBig(t *testing.T) { + // Positive value (99) + answer := HexToSignedBig("0x63") + assert.Equal(t, big.NewInt(99), answer) + + // Negative value (-10) + answer = HexToSignedBig("0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff7") + assert.Equal(t, big.NewInt(-10), answer) +} + +func TestDecodeFeltFails(t *testing.T) { + val, _ := new(big.Int).SetString("1231927389172389172983712738127391273891", 10) + + array := make([]*big.Int, 2) + array[0] = val + array[1] = val + + _, err := DecodeFelts(array) + assert.Equal(t, err.Error(), "invalid: contained less bytes than the specified length") +} + +func TestDecodeFeltsSuccesses(t *testing.T) { + b, _ := new(big.Int).SetString("1231927389172389172983712738127391273891", 10) + bBytesLen := int64(len(b.Bytes())) + a := big.NewInt(bBytesLen) + + array := make([]*big.Int, 2) + array[0] = a + array[1] = b + + fBytes, err := DecodeFelts(array) + assert.Equal(t, int64(len(fBytes)), bBytesLen) + require.NoError(t, err) +} + +func TestEncodeThenDecode(t *testing.T) { + const dataLen = 232 + + // create random bytes + data := make([]byte, dataLen) + _, err := rand.Read(data) + require.NoError(t, err) + + encodedData := EncodeFelts(data) + decodedData, err := DecodeFelts(encodedData) + require.NoError(t, err) + + assert.Equal(t, data, decodedData) +} + +func TestDecodeThenEncode(t *testing.T) { + const numOfFelts = 12 + + // Create random array of felts + felts := make([]*big.Int, numOfFelts+1) + felts[0] = big.NewInt(numOfFelts * 31) + for i := 1; i <= numOfFelts; i++ { + feltRaw := make([]byte, 31) + _, err := rand.Read(feltRaw) + require.NoError(t, err) + + felt := new(big.Int).SetBytes(feltRaw) + felts[i] = felt + } + + decodedFelts, err := DecodeFelts(felts) + require.NoError(t, err) + + encodedFelts := EncodeFelts(decodedFelts) + assert.Equal(t, encodedFelts, felts) +} + +func TestIncorrectDecode(t *testing.T) { + felts := make([]*big.Int, 3) + felts[0] = big.NewInt(35) + // bytes length can be less than 31 + felts[1] = new(big.Int).SetBytes([]byte{0x1, 0x2, 0x3, 0x4}) + felts[2] = new(big.Int).SetBytes([]byte{0x11, 0x21}) + + _, err := DecodeFelts(felts) + + require.NoError(t, err) +} + +func TestDecodeFelts(t *testing.T) { + a, _ := new(big.Int).SetString("1231927389172389172983712738127391273891", 10) + array := make([]*big.Int, 2) + array[0] = a + array[1] = a + _, err := DecodeFelts(array) + require.Error(t, err) +} + +func TestDecodeFelts2(t *testing.T) { + a, _ := new(big.Int).SetString("1", 10) + b, _ := new(big.Int).SetString("1231927389172389172983712738127391273891", 10) + array := make([]*big.Int, 2) + array[0] = a + array[1] = b + _, err := DecodeFelts(array) + require.Error(t, err) +} diff --git a/scripts/generate-codegraph.sh b/scripts/generate-codegraph.sh new file mode 100755 index 0000000..3db4712 --- /dev/null +++ b/scripts/generate-codegraph.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +if ! command -v godepgraph &> /dev/null +then + echo 'godepgraph not found! \nCheck https://github.com/kisielk/godepgraph for instructions!' + exit +fi + +if ! command -v dot &> /dev/null +then + echo 'dot not found! \nCheck https://graphviz.org/ for instructions!' + exit +fi + +usage="usage: $(basename "$0") [-h] [-a] [-p GO_PACKAGE] [-o OUTPUT_PNG_PATH] +Create a dependency diagram for the provided go module: + -h show this tip + -a include all dependencies (otherwise include only github.com/smartcontractkit dependencies) + -p package name (i.e. github.com/goplugin/plugin-starknet/relayer/pkg/plugin) + -o output PNG path" + +options=':hap:o:' +while getopts $options option; do + case "$option" in + h) echo "$usage"; exit;; + a) ALL_DEPENDENCIES=1;; + p) GO_MODULE_PATH=$OPTARG;; + o) OUTPUT_PNG_PATH=$OPTARG;; + esac +done + +if [ ! "$GO_MODULE_PATH" ]; +then + echo "-p argument must be provided" + echo "$usage" >&2; exit 1 +fi + +if [ ! "$OUTPUT_PNG_PATH" ]; +then + OUTPUT_PNG_PATH="./godepgraph.png" +fi + +if [ ! "$ALL_DEPENDENCIES" ]; +then + godepgraph -s -o .,github.com/smartcontractkit $GO_MODULE_PATH | dot -Tpng -o $OUTPUT_PNG_PATH +else + godepgraph -s $GO_MODULE_PATH | dot -Tpng -o $OUTPUT_PNG_PATH +fi + +echo "Finished!" + + + + + + + + diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..c4b13f8 --- /dev/null +++ b/shell.nix @@ -0,0 +1,44 @@ +{ stdenv, pkgs, lib }: + +# juno requires building with clang, not gcc +(pkgs.mkShell.override { stdenv = pkgs.clangStdenv; }) { + buildInputs = with pkgs; [ + python39 + python39Packages.pip + python39Packages.venvShellHook + python39Packages.fastecdsa # so libgmp is correctly sourced + zlib # for numpy + gmp + nodejs-18_x + (yarn.override { nodejs = nodejs-18_x; }) + nodePackages.typescript + nodePackages.typescript-language-server + nodePackages.npm + + go_1_20 + gopls + delve + golangci-lint + gotools + + kube3d + kubectl + k9s + kubernetes-helm + + ] ++ lib.optionals stdenv.isLinux [ + # ledger specific packages + libudev-zero + libusb1 + ]; + + LD_LIBRARY_PATH = lib.makeLibraryPath [pkgs.zlib stdenv.cc.cc.lib]; # lib64 + HELM_REPOSITORY_CONFIG=./.helm-repositories.yaml; + + venvDir = "./.venv"; + + postShellHook = '' + pip install -r ${./contracts/requirements.txt} -c ${./contracts/constraints.txt} + helm repo update + ''; +} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..d8b6363 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,39 @@ +{ + "compilerOptions": { + /* Basic Options */ + "incremental": true /* Enable incremental compilation */, + "target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, + "composite": true /* Enable project compilation */, + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "noEmit": false /* Do not emit outputs. */, + "noErrorTruncation": true /* Do not truncate error messages */, + "skipLibCheck": true /* Skip type checking of declaration files. Requires TypeScript version 2.0 or later. */, + "importHelpers": true /* Import emit helpers from 'tslib'. */, + + /* Strict Type-Checking Options */ + /* "strict": true, */ /* Enable all strict type-checking options. */ + + /* Additional Checks */ + /* "noUnusedParameters": true, */ /* Report errors on unused parameters. */ + /* "noImplicitReturns": true, */ /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + + /* Source Map Options */ + "inlineSourceMap": true /* Emit a single file with source maps instead of having a separate file. */, + "inlineSources": true /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */, + + /* Experimental Options */ + "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, + "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, + + "resolveJsonModule": true /* Allows importing modules with a ‘.json’ extension */ + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cb4dd77 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,40 @@ +{ + "extends": "./tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./packages-ts/starknet" + }, + { + "path": "./packages-ts/starknet-gauntlet" + }, + { + "path": "./packages-ts/starknet-gauntlet-oz" + }, + { + "path": "./packages-ts/starknet-gauntlet-argent" + }, + { + "path": "./packages-ts/starknet-gauntlet-multisig" + }, + { + "path": "./packages-ts/starknet-gauntlet-example" + }, + { + "path": "./packages-ts/starknet-gauntlet-token" + }, + { + "path": "./packages-ts/starknet-gauntlet-ocr2" + }, + { + "path": "./packages-ts/starknet-gauntlet-emergency-protocol" + }, + { + "path": "./packages-ts/starknet-gauntlet-ledger" + }, + { + "path": "./packages-ts/starknet-gauntlet-cli" + }, + ] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..f975178 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,7728 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.20.0": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" + integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.6.tgz#7122ae4f5c5a37c0946c066149abd8e75f81540f" + integrity sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.19.6" + "@babel/helper-compilation-targets" "^7.19.3" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helpers" "^7.19.4" + "@babel/parser" "^7.19.6" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.6" + "@babel/types" "^7.19.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/generator@7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" + integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== + dependencies: + "@babel/types" "^7.18.2" + "@jridgewell/gen-mapping" "^0.3.0" + jsesc "^2.5.1" + +"@babel/generator@^7.19.6", "@babel/generator@^7.20.1", "@babel/generator@^7.7.2": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.1.tgz#ef32ecd426222624cbd94871a7024639cf61a9fa" + integrity sha512-u1dMdBUmA7Z0rBB97xh8pIhviK7oItYOkjbsCxTWMknyvbQRBwX7/gn4JXurRdirWMFh+ZtYARqkA6ydogVZpg== + dependencies: + "@babel/types" "^7.20.0" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.19.3": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== + dependencies: + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + semver "^6.3.0" + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.6.tgz#6c52cc3ac63b70952d33ee987cbee1c9368b533f" + integrity sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.19.4" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.6" + "@babel/types" "^7.19.4" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" + integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== + +"@babel/helper-simple-access@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz#be553f4951ac6352df2567f7daa19a0ee15668e7" + integrity sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg== + dependencies: + "@babel/types" "^7.19.4" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helpers@^7.19.4": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" + integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.0" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@7.18.4": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef" + integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow== + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.19.6", "@babel/parser@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.1.tgz#3e045a92f7b4623cafc2425eddcb8cf2e54f9cc5" + integrity sha512-hp0AYxaZJhxULfM1zyp7Wgr+pSUKBcP3M+PHnSzWGdXOzg/kHWIgiUWARvubhUKGOEw3xqY4x+lyZ9ytBVcELw== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/runtime@^7.10.4", "@babel/runtime@^7.5.5": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" + integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg== + dependencies: + regenerator-runtime "^0.13.10" + +"@babel/template@^7.18.10", "@babel/template@^7.3.3": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.19.6", "@babel/traverse@^7.20.1", "@babel/traverse@^7.7.2": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" + integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.1" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.1" + "@babel/types" "^7.20.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@7.18.4": + version "7.18.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354" + integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.2", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.19.4", "@babel/types@^7.20.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.0.tgz#52c94cf8a7e24e89d2a194c25c35b17a64871479" + integrity sha512-Jlgt3H0TajCW164wkTOTzHkZb075tMQMULzrLUoUeKmO7eFL96GgDxf7/Axhc5CAuKE3KFyVW1p6ysKsi2oXAg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@pluginv3.0-dev/starkgate-open-zeppelin@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@pluginv3.0-dev/starkgate-open-zeppelin/-/starkgate-open-zeppelin-0.5.0.tgz#9fea55dfb599b4de1e4608260968ddc2ab51c330" + integrity sha512-q9xslzDu4fclArGxH29pz8/u0VVp8kexhgpMC5nLb/NFQKcaHjBcm20zbaURrTTWTUeQRW4eVgIXyduFkWVjtw== + +"@pluginv3.0/contracts@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@pluginv3.0/contracts/-/contracts-0.4.2.tgz#2928a35e8da94664b8ffeb8f5a54b1a3f14d5b3f" + integrity sha512-wVI/KZ9nIH0iqoebVxYrZfNVWO23vwds1UrHdbF+S0JwyixtT+54xYGlot723jCrAeBeQHsDRQXnEhhbUEHpgQ== + dependencies: + "@eth-optimism/contracts" "^0.5.21" + +"@pluginv3.0/evm-gauntlet@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@pluginv3.0/evm-gauntlet/-/evm-gauntlet-0.1.0.tgz#cf5cdbf66f1126b5b1d23fa8d494ab4598317674" + integrity sha512-59/1BoS0ENuE8jQTenSM3ymvWVHmElF2rwb+LlRMhqNjnvYy3zRTwx2dlCXGf2j0H6E4NJFs+naBq2cJr43Eag== + dependencies: + "@pluginv3.0/gauntlet-core" "0.3.1" + ethers "^5.6.9" + +"@pluginv3.0/evm-gauntlet@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@pluginv3.0/evm-gauntlet/-/evm-gauntlet-0.0.2.tgz#8827070c228aa466bfe069ff92ac9b661097bdcb" + integrity sha512-e6uDeoVluro5QBFcK2N0Ctk2g0daY0SUDfZblKb64QeIE7X+d5SoRMFgwhr20L4pL8ihvLkkXDETsIgT/r9cpw== + dependencies: + "@pluginv3.0/gauntlet-core" "0.3.1" + ethers "^5.6.9" + +"@pluginv3.0/evm-gauntlet@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@pluginv3.0/evm-gauntlet/-/evm-gauntlet-0.4.0.tgz#95a5a63eaab641e9558c910dba5cead6ce56b862" + integrity sha512-gQAzl7o/Hesz+UPY3rBw/kkHqjUxReYCIQdtdqKT6hRHDOqncVrAO4iAcHuKLSHtnQ79kSaDCfTSlUn1nTrrTQ== + dependencies: + "@pluginv3.0/gauntlet-core" "0.3.1" + ethers "^5.6.9" + +"@pluginv3.0/gauntlet-contracts-example@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pluginv3.0/gauntlet-contracts-example/-/gauntlet-contracts-example-0.1.1.tgz#bf7827460dcb404ba3683245cec1df61ee5ee5c5" + integrity sha512-7qAg0504cQYJIiQY3QxWW/wvfAJzGokIk6qpn94Em3fOYpPFYJ+WH665B+lxwtjZLUef6DyK04Tiu55amPpCWQ== + dependencies: + "@pluginv3.0/gauntlet-core" "*" + +"@pluginv3.0/gauntlet-contracts-ocr2@0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@pluginv3.0/gauntlet-contracts-ocr2/-/gauntlet-contracts-ocr2-0.2.2.tgz#b2e6deab8c52abea588cad7c152bf8cc7a03ca28" + integrity sha512-Wmxl3lwlEFVO+jQ7CvOnOV4UA67XguIs6tCY2ayf4KdnNVARgPatI5emAniooNd27n0zgDT+61s5gEpVzWBEqw== + dependencies: + "@pluginv3.0/gauntlet-core" "*" + +"@pluginv3.0/gauntlet-core@*": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@pluginv3.0/gauntlet-core/-/gauntlet-core-0.4.0.tgz#bf830090dd9996ea2cb893c2bf120213932fbd00" + integrity sha512-hCCK3gbDKH4jZeoiwEWB/4fpaq3qoFaKbkDPvfxSJiuXcwD3oKOMxnhqRQNwG9aw/30CN/FUmb+KHDJfk03tRQ== + dependencies: + "@ethersproject/keccak256" "^5.5.0" + axios "^0.24.0" + bn.js "^5.2.0" + protobufjs "^6.11.2" + +"@pluginv3.0/gauntlet-core@0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@pluginv3.0/gauntlet-core/-/gauntlet-core-0.3.1.tgz#27badd597ef6a2db8cfdb56367b9ea5ca0866976" + integrity sha512-T/L3zswTw62r5oKpDkvg8xR8JhBNItGkfaoGL8h/B1+4HN4mRcl4L5iIY21CF53rHx9PootZoxUEKAorhBxOqA== + dependencies: + "@ethersproject/keccak256" "^5.5.0" + axios "^0.24.0" + bn.js "^5.2.0" + protobufjs "^6.11.2" + +"@chainsafe/as-sha256@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" + integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== + +"@chainsafe/persistent-merkle-tree@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" + integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/persistent-merkle-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" + integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/ssz@^0.10.0": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" + integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.5.0" + +"@chainsafe/ssz@^0.9.2": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" + integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.4.2" + case "^1.6.3" + +"@changesets/apply-release-plan@^6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@changesets/apply-release-plan/-/apply-release-plan-6.1.2.tgz#cfb7da323f34e9e9173ffd9bf9f03c0b8cecc8fe" + integrity sha512-H8TV9E/WtJsDfoDVbrDGPXmkZFSv7W2KLqp4xX4MKZXshb0hsQZUNowUa8pnus9qb/5OZrFFRVsUsDCVHNW/AQ== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/config" "^2.2.0" + "@changesets/get-version-range-type" "^0.3.2" + "@changesets/git" "^1.5.0" + "@changesets/types" "^5.2.0" + "@manypkg/get-packages" "^1.1.3" + detect-indent "^6.0.0" + fs-extra "^7.0.1" + lodash.startcase "^4.4.0" + outdent "^0.5.0" + prettier "^2.7.1" + resolve-from "^5.0.0" + semver "^5.4.1" + +"@changesets/assemble-release-plan@^5.2.2": + version "5.2.2" + resolved "https://registry.yarnpkg.com/@changesets/assemble-release-plan/-/assemble-release-plan-5.2.2.tgz#9824f14a7a6e411c7153f1ccc2a42bbe35688129" + integrity sha512-B1qxErQd85AeZgZFZw2bDKyOfdXHhG+X5S+W3Da2yCem8l/pRy4G/S7iOpEcMwg6lH8q2ZhgbZZwZ817D+aLuQ== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/errors" "^0.1.4" + "@changesets/get-dependents-graph" "^1.3.4" + "@changesets/types" "^5.2.0" + "@manypkg/get-packages" "^1.1.3" + semver "^5.4.1" + +"@changesets/changelog-git@^0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@changesets/changelog-git/-/changelog-git-0.1.13.tgz#182e130add456255d8ee2b4c8eaf88048944aaaf" + integrity sha512-zvJ50Q+EUALzeawAxax6nF2WIcSsC5PwbuLeWkckS8ulWnuPYx8Fn/Sjd3rF46OzeKA8t30loYYV6TIzp4DIdg== + dependencies: + "@changesets/types" "^5.2.0" + +"@changesets/cli@^2.22.0": + version "2.25.2" + resolved "https://registry.yarnpkg.com/@changesets/cli/-/cli-2.25.2.tgz#fc5e894aa6f85c60749a035352dec3dcbd275c71" + integrity sha512-ACScBJXI3kRyMd2R8n8SzfttDHi4tmKSwVwXBazJOylQItSRSF4cGmej2E4FVf/eNfGy6THkL9GzAahU9ErZrA== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/apply-release-plan" "^6.1.2" + "@changesets/assemble-release-plan" "^5.2.2" + "@changesets/changelog-git" "^0.1.13" + "@changesets/config" "^2.2.0" + "@changesets/errors" "^0.1.4" + "@changesets/get-dependents-graph" "^1.3.4" + "@changesets/get-release-plan" "^3.0.15" + "@changesets/git" "^1.5.0" + "@changesets/logger" "^0.0.5" + "@changesets/pre" "^1.0.13" + "@changesets/read" "^0.5.8" + "@changesets/types" "^5.2.0" + "@changesets/write" "^0.2.2" + "@manypkg/get-packages" "^1.1.3" + "@types/is-ci" "^3.0.0" + "@types/semver" "^6.0.0" + ansi-colors "^4.1.3" + chalk "^2.1.0" + enquirer "^2.3.0" + external-editor "^3.1.0" + fs-extra "^7.0.1" + human-id "^1.0.2" + is-ci "^3.0.1" + meow "^6.0.0" + outdent "^0.5.0" + p-limit "^2.2.0" + preferred-pm "^3.0.0" + resolve-from "^5.0.0" + semver "^5.4.1" + spawndamnit "^2.0.0" + term-size "^2.1.0" + tty-table "^4.1.5" + +"@changesets/config@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@changesets/config/-/config-2.2.0.tgz#382f6cd801fa56273942659114c8060378dfe066" + integrity sha512-GGaokp3nm5FEDk/Fv2PCRcQCOxGKKPRZ7prcMqxEr7VSsG75MnChQE8plaW1k6V8L2bJE+jZWiRm19LbnproOw== + dependencies: + "@changesets/errors" "^0.1.4" + "@changesets/get-dependents-graph" "^1.3.4" + "@changesets/logger" "^0.0.5" + "@changesets/types" "^5.2.0" + "@manypkg/get-packages" "^1.1.3" + fs-extra "^7.0.1" + micromatch "^4.0.2" + +"@changesets/errors@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@changesets/errors/-/errors-0.1.4.tgz#f79851746c43679a66b383fdff4c012f480f480d" + integrity sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q== + dependencies: + extendable-error "^0.1.5" + +"@changesets/get-dependents-graph@^1.3.4": + version "1.3.4" + resolved "https://registry.yarnpkg.com/@changesets/get-dependents-graph/-/get-dependents-graph-1.3.4.tgz#d8bf537f45a7ff773da99143675f49e250996838" + integrity sha512-+C4AOrrFY146ydrgKOo5vTZfj7vetNu1tWshOID+UjPUU9afYGDXI8yLnAeib1ffeBXV3TuGVcyphKpJ3cKe+A== + dependencies: + "@changesets/types" "^5.2.0" + "@manypkg/get-packages" "^1.1.3" + chalk "^2.1.0" + fs-extra "^7.0.1" + semver "^5.4.1" + +"@changesets/get-release-plan@^3.0.15": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@changesets/get-release-plan/-/get-release-plan-3.0.15.tgz#55577b235b785125a462d5d2a2dffe4dbf94e590" + integrity sha512-W1tFwxE178/en+zSj/Nqbc3mvz88mcdqUMJhRzN1jDYqN3QI4ifVaRF9mcWUU+KI0gyYEtYR65tour690PqTcA== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/assemble-release-plan" "^5.2.2" + "@changesets/config" "^2.2.0" + "@changesets/pre" "^1.0.13" + "@changesets/read" "^0.5.8" + "@changesets/types" "^5.2.0" + "@manypkg/get-packages" "^1.1.3" + +"@changesets/get-version-range-type@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@changesets/get-version-range-type/-/get-version-range-type-0.3.2.tgz#8131a99035edd11aa7a44c341cbb05e668618c67" + integrity sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg== + +"@changesets/git@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@changesets/git/-/git-1.5.0.tgz#71bbcf11f3b346d56eeaf3d3201e6dc3e270ea5a" + integrity sha512-Xo8AT2G7rQJSwV87c8PwMm6BAc98BnufRMsML7m7Iw8Or18WFvFmxqG5aOL5PBvhgq9KrKvaeIBNIymracSuHg== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/errors" "^0.1.4" + "@changesets/types" "^5.2.0" + "@manypkg/get-packages" "^1.1.3" + is-subdir "^1.1.1" + spawndamnit "^2.0.0" + +"@changesets/logger@^0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@changesets/logger/-/logger-0.0.5.tgz#68305dd5a643e336be16a2369cb17cdd8ed37d4c" + integrity sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw== + dependencies: + chalk "^2.1.0" + +"@changesets/parse@^0.3.15": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@changesets/parse/-/parse-0.3.15.tgz#1bc74f8c43b0861d71f4fccf78950411004ba308" + integrity sha512-3eDVqVuBtp63i+BxEWHPFj2P1s3syk0PTrk2d94W9JD30iG+OER0Y6n65TeLlY8T2yB9Fvj6Ev5Gg0+cKe/ZUA== + dependencies: + "@changesets/types" "^5.2.0" + js-yaml "^3.13.1" + +"@changesets/pre@^1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@changesets/pre/-/pre-1.0.13.tgz#49c3ae8bb444a1ce3e0fe4cb21f238318b6763e9" + integrity sha512-jrZc766+kGZHDukjKhpBXhBJjVQMied4Fu076y9guY1D3H622NOw8AQaLV3oQsDtKBTrT2AUFjt9Z2Y9Qx+GfA== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/errors" "^0.1.4" + "@changesets/types" "^5.2.0" + "@manypkg/get-packages" "^1.1.3" + fs-extra "^7.0.1" + +"@changesets/read@^0.5.8": + version "0.5.8" + resolved "https://registry.yarnpkg.com/@changesets/read/-/read-0.5.8.tgz#84e24fd12e6759cef090088261c08b1dfe0f350e" + integrity sha512-eYaNfxemgX7f7ELC58e7yqQICW5FB7V+bd1lKt7g57mxUrTveYME+JPaBPpYx02nP53XI6CQp6YxnR9NfmFPKw== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/git" "^1.5.0" + "@changesets/logger" "^0.0.5" + "@changesets/parse" "^0.3.15" + "@changesets/types" "^5.2.0" + chalk "^2.1.0" + fs-extra "^7.0.1" + p-filter "^2.1.0" + +"@changesets/types@^4.0.1": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@changesets/types/-/types-4.1.0.tgz#fb8f7ca2324fd54954824e864f9a61a82cb78fe0" + integrity sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw== + +"@changesets/types@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@changesets/types/-/types-5.2.0.tgz#c4927f5bf9668f778c12b4226cfd07a1f5b79c9b" + integrity sha512-km/66KOqJC+eicZXsm2oq8A8bVTSpkZJ60iPV/Nl5Z5c7p9kk8xxh6XGRTlnludHldxOOfudhnDN2qPxtHmXzA== + +"@changesets/write@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@changesets/write/-/write-0.2.2.tgz#f3ffb1be06f7c31265eb4ec3d7166b91f9c25c9b" + integrity sha512-kCYNHyF3xaId1Q/QE+DF3UTrHTyg3Cj/f++T8S8/EkC+jh1uK2LFnM9h+EzV+fsmnZDrs7r0J4LLpeI/VWC5Hg== + dependencies: + "@babel/runtime" "^7.10.4" + "@changesets/types" "^5.2.0" + fs-extra "^7.0.1" + human-id "^1.0.2" + prettier "^2.7.1" + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@eth-optimism/contracts@^0.5.21": + version "0.5.37" + resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.5.37.tgz#3aaca1ca1f49ef895d4165cc7bf29c8d1f5b0f56" + integrity sha512-HbNUUDIM1dUAM0hWPfGp3l9/Zte40zi8QhVbUSIwdYRA7jG7cZgbteqavrjW8wwFqxkWX9IrtA0KAR7pNlSAIQ== + dependencies: + "@eth-optimism/core-utils" "0.10.1" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + +"@eth-optimism/core-utils@0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.10.1.tgz#44515fbca627532a24c6fd433395f00be8525832" + integrity sha512-IJvG5UtYvyz6An9QdohlCLoeB3NBFxx2lRJKlPzvYYlfugUNNCHsajRIWIwJTcPRRma0WPd46JUsKACLJDdNrA== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/contracts" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/providers" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bufio "^1.0.7" + chai "^4.3.4" + +"@ethereum-waffle/mock-contract@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-4.0.4.tgz#f13fea29922d87a4d2e7c4fc8fe72ea04d2c13de" + integrity sha512-LwEj5SIuEe9/gnrXgtqIkWbk2g15imM/qcJcxpLyAkOj981tQxXmtV4XmQMZsdedEsZ/D/rbUAOtZbgwqgUwQA== + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.6.1", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.5.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/providers@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.1.tgz#b0799b616d5579cd1067a8ebf1fc1ec74c1e122c" + integrity sha512-vZveG/DLyo+wk4Ga1yx6jSEHrLPgmTt+dFv0dv8URpVCRf0jVhalps1jq/emN/oXnMRsC7cQgAF32DcXLL7BPQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.3.tgz#2030606ec03a18c31803b8a36382762e447655df" + integrity sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw== + dependencies: + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + slash "^3.0.0" + +"@jest/core@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.3.tgz#0ebf2bd39840f1233cd5f2d1e6fc8b71bd5a1ac7" + integrity sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA== + dependencies: + "@jest/console" "^28.1.3" + "@jest/reporters" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^28.1.3" + jest-config "^28.1.3" + jest-haste-map "^28.1.3" + jest-message-util "^28.1.3" + jest-regex-util "^28.0.2" + jest-resolve "^28.1.3" + jest-resolve-dependencies "^28.1.3" + jest-runner "^28.1.3" + jest-runtime "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" + jest-watcher "^28.1.3" + micromatch "^4.0.4" + pretty-format "^28.1.3" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.3.tgz#abed43a6b040a4c24fdcb69eab1f97589b2d663e" + integrity sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA== + dependencies: + "@jest/fake-timers" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + jest-mock "^28.1.3" + +"@jest/expect-utils@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525" + integrity sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA== + dependencies: + jest-get-type "^28.0.2" + +"@jest/expect@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.3.tgz#9ac57e1d4491baca550f6bdbd232487177ad6a72" + integrity sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw== + dependencies: + expect "^28.1.3" + jest-snapshot "^28.1.3" + +"@jest/fake-timers@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.3.tgz#230255b3ad0a3d4978f1d06f70685baea91c640e" + integrity sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw== + dependencies: + "@jest/types" "^28.1.3" + "@sinonjs/fake-timers" "^9.1.2" + "@types/node" "*" + jest-message-util "^28.1.3" + jest-mock "^28.1.3" + jest-util "^28.1.3" + +"@jest/globals@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.3.tgz#a601d78ddc5fdef542728309894895b4a42dc333" + integrity sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/expect" "^28.1.3" + "@jest/types" "^28.1.3" + +"@jest/reporters@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.3.tgz#9adf6d265edafc5fc4a434cfb31e2df5a67a369a" + integrity sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@jridgewell/trace-mapping" "^0.3.13" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + jest-worker "^28.1.3" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + terminal-link "^2.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905" + integrity sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg== + dependencies: + "@sinclair/typebox" "^0.24.1" + +"@jest/source-map@^28.1.2": + version "28.1.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-28.1.2.tgz#7fe832b172b497d6663cdff6c13b0a920e139e24" + integrity sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww== + dependencies: + "@jridgewell/trace-mapping" "^0.3.13" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.3.tgz#5eae945fd9f4b8fcfce74d239e6f725b6bf076c5" + integrity sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg== + dependencies: + "@jest/console" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz#9d0c283d906ac599c74bde464bc0d7e6a82886c3" + integrity sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw== + dependencies: + "@jest/test-result" "^28.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + slash "^3.0.0" + +"@jest/transform@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.3.tgz#59d8098e50ab07950e0f2fc0fc7ec462371281b0" + integrity sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^28.1.3" + "@jridgewell/trace-mapping" "^0.3.13" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + jest-regex-util "^28.0.2" + jest-util "^28.1.3" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.1" + +"@jest/types@^28.1.3": + version "28.1.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.3.tgz#b05de80996ff12512bc5ceb1d208285a7d11748b" + integrity sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ== + dependencies: + "@jest/schemas" "^28.1.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@ledgerhq/devices@^7.0.3": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-7.0.3.tgz#bdd7e8ce078399fe644067a7e1ca9a9d2e249c02" + integrity sha512-URlcgq6yKklWxj35nIu/eTF0UpGLGUOp69xp8uHeyoMK2wqVC0GNGeD2MvKyJ+ul83edqMEI98GycA98Y7trsg== + dependencies: + "@ledgerhq/errors" "^6.11.1" + "@ledgerhq/logs" "^6.10.1" + rxjs "6" + semver "^7.3.5" + +"@ledgerhq/errors@^6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.11.1.tgz#a8a81bda6d28ac43c757e109b1ff079ddeec54a6" + integrity sha512-HT1PFvNrejcN5z3ba6xikacIdHWMkjBeE9U5FFoGHhaKBKGjC74mnCeEo0/oJunyuVId+9mhGnv6lrBl6Mkqdg== + +"@ledgerhq/hw-app-starknet@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-starknet/-/hw-app-starknet-2.0.3.tgz#3d964321ef96ae1cdc210b8f87ba945363d37849" + integrity sha512-wRr0MAvm8UunwoPOGgLOW7PnZLlN6X2yHsFGqyIWUtqKu8DZ7AuVTx5GGbOUBOYWL9xIYAYZnTACCFABuuY6qw== + dependencies: + "@ledgerhq/hw-transport" "^6.27.1" + "@types/bn.js" "^5.1.1" + bn.js "^5.2.1" + +"@ledgerhq/hw-transport-node-hid-noevents@^6.27.6": + version "6.27.6" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.6.tgz#1ad5e9ae886bbd6b245ba733b519f8a2619a684d" + integrity sha512-9WvUBUhk0eRSZjXgEsdNVGkxHuDLoh6fR1PJIeXKHgC8dzTREYrGKytx8ECqO5OPotXeAZURC3yB00XZrKIupw== + dependencies: + "@ledgerhq/devices" "^7.0.3" + "@ledgerhq/errors" "^6.11.1" + "@ledgerhq/hw-transport" "^6.27.6" + "@ledgerhq/logs" "^6.10.1" + node-hid "2.1.1" + +"@ledgerhq/hw-transport-node-hid@^6.27.6": + version "6.27.6" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.27.6.tgz#0ff7d0d5c8a423da57ca071d384a10fb90b5ef3e" + integrity sha512-ZQGKTydb3niMfGBrhbYR7zDiykOadiXRj05qfrjkCvvLXEq3KkUy8WnhfoSQEgaQpOx+i4SUJwzzfAih5eP3GA== + dependencies: + "@ledgerhq/devices" "^7.0.3" + "@ledgerhq/errors" "^6.11.1" + "@ledgerhq/hw-transport" "^6.27.6" + "@ledgerhq/hw-transport-node-hid-noevents" "^6.27.6" + "@ledgerhq/logs" "^6.10.1" + lodash "^4.17.21" + node-hid "2.1.1" + usb "^1.7.0" + +"@ledgerhq/hw-transport@^6.27.1", "@ledgerhq/hw-transport@^6.27.6": + version "6.27.6" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.27.6.tgz#87f886591bad047c18e76920519aceb9d844667b" + integrity sha512-DRGUsB8WfbeEPuU42nAtwYpA5D6Bq3q1CvC2VjDinkukLcf6XMc22YUJl9mxt+h+/cLTU1Ff/pz+fqYqeELLEA== + dependencies: + "@ledgerhq/devices" "^7.0.3" + "@ledgerhq/errors" "^6.11.1" + events "^3.3.0" + +"@ledgerhq/logs@^6.10.1": + version "6.10.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-6.10.1.tgz#5bd16082261d7364eabb511c788f00937dac588d" + integrity sha512-z+ILK8Q3y+nfUl43ctCPuR4Y2bIxk/ooCQFwZxhtci1EhAtMDzMAx2W25qx8G1PPL9UUOdnUax19+F0OjXoj4w== + +"@manypkg/find-root@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@manypkg/find-root/-/find-root-1.1.0.tgz#a62d8ed1cd7e7d4c11d9d52a8397460b5d4ad29f" + integrity sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA== + dependencies: + "@babel/runtime" "^7.5.5" + "@types/node" "^12.7.1" + find-up "^4.1.0" + fs-extra "^8.1.0" + +"@manypkg/get-packages@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@manypkg/get-packages/-/get-packages-1.1.3.tgz#e184db9bba792fa4693de4658cfb1463ac2c9c47" + integrity sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A== + dependencies: + "@babel/runtime" "^7.5.5" + "@changesets/types" "^4.0.1" + "@manypkg/find-root" "^1.1.0" + fs-extra "^8.1.0" + globby "^11.0.0" + read-yaml-file "^1.1.0" + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@noble/curves@^0.8.2": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-0.8.3.tgz#ad6d48baf2599cf1d58dcb734c14d5225c8996e0" + integrity sha512-OqaOf4RWDaCRuBKJLDURrgVxjLmneGsiCXGuzYB5y95YithZMA6w4uk34DHSm0rKMrrYiaeZj48/81EvaAScLQ== + dependencies: + "@noble/hashes" "1.3.0" + +"@noble/curves@~1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" + integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== + dependencies: + "@noble/hashes" "1.3.0" + +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + +"@noble/hashes@1.3.0", "@noble/hashes@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" + integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== + +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nomicfoundation/ethereumjs-block@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" + integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + +"@nomicfoundation/ethereumjs-blockchain@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" + integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-ethash" "3.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + level "^8.0.0" + lru-cache "^5.1.1" + memory-level "^1.0.0" + +"@nomicfoundation/ethereumjs-common@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" + integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.1" + crc-32 "^1.2.0" + +"@nomicfoundation/ethereumjs-ethash@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" + integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + bigint-crypto-utils "^3.0.23" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-evm@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" + integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== + dependencies: + "@ethersproject/providers" "^5.7.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/ethereumjs-rlp@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" + integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== + +"@nomicfoundation/ethereumjs-statemanager@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" + integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + js-sdsl "^4.1.4" + +"@nomicfoundation/ethereumjs-trie@6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" + integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@types/readable-stream" "^2.3.13" + ethereum-cryptography "0.1.3" + readable-stream "^3.6.0" + +"@nomicfoundation/ethereumjs-tx@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" + integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== + dependencies: + "@chainsafe/ssz" "^0.9.2" + "@ethersproject/providers" "^5.7.2" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-util@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" + integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== + dependencies: + "@chainsafe/ssz" "^0.10.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-vm@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" + integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/hardhat-chai-matchers@^1.0.3": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-1.0.6.tgz#72a2e312e1504ee5dd73fe302932736432ba96bc" + integrity sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@types/chai-as-promised" "^7.1.3" + chai-as-promised "^7.1.1" + deep-eql "^4.0.1" + ordinal "^1.0.3" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz#4c858096b1c17fe58a474fe81b46815f93645c15" + integrity sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz#6e25ccdf6e2d22389c35553b64fe6f3fdaec432c" + integrity sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA== + +"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz#0a224ea50317139caeebcdedd435c28a039d169c" + integrity sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz#dfa085d9ffab9efb2e7b383aed3f557f7687ac2b" + integrity sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz#c9e06b5d513dd3ab02a7ac069c160051675889a4" + integrity sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz#8d328d16839e52571f72f2998c81e46bf320f893" + integrity sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz#9b49d0634b5976bb5ed1604a1e1b736f390959bb" + integrity sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w== + +"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz#e2867af7264ebbcc3131ef837878955dd6a3676f" + integrity sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg== + +"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz#0685f78608dd516c8cdfb4896ed451317e559585" + integrity sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz#c9a44f7108646f083b82e851486e0f6aeb785836" + integrity sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz#f5f4d36d3f66752f59a57e7208cd856f3ddf6f2d" + integrity sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.1" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" + +"@nomiclabs/hardhat-docker@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" + integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== + dependencies: + dockerode "^2.5.8" + fs-extra "^7.0.1" + node-fetch "^2.6.0" + +"@nomiclabs/hardhat-ethers@^2.0.5", "@nomiclabs/hardhat-ethers@^2.1.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" + integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== + +"@openzeppelin/contracts@^4.7.3": + version "4.8.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.3.tgz#cbef3146bfc570849405f59cba18235da95a252a" + integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + +"@scure/base@~1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== + dependencies: + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== + dependencies: + "@noble/hashes" "~1.2.0" + "@scure/base" "~1.1.0" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@shardlabs/starknet-hardhat-plugin@^0.8.0-alpha.0": + version "0.8.0-alpha.0" + resolved "https://registry.yarnpkg.com/@shardlabs/starknet-hardhat-plugin/-/starknet-hardhat-plugin-0.8.0-alpha.0.tgz#0421863938025e3c401c8d9896872e35c0da07d8" + integrity sha512-1v8i9Fcdo6zzr7etIosqqNFRVZCaV1T2YddeexklrmYDCP6WtmKj6G4hVOt1cOjZ1c1c+Pe1s/iD6hoi/2rFSQ== + dependencies: + "@nomiclabs/hardhat-docker" "^2.0.2" + axios "^0.24.0" + exit-hook "2.2.1" + form-data "^4.0.0" + glob "^7.2.0" + json-bigint "^1.0.0" + shelljs "^0.8.5" + starknet "^3.15.0" + +"@sinclair/typebox@^0.24.1": + version "0.24.51" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" + integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== + +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^9.1.2": + version "9.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" + integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@solidity-parser/parser@^0.14.1": + version "0.14.5" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" + integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@types/babel__core@^7.1.14": + version "7.1.19" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" + integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.2.tgz#235bf339d17185bdec25e024ca19cce257cc7309" + integrity sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg== + dependencies: + "@babel/types" "^7.3.0" + +"@types/bn.js@*", "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + +"@types/bn.js@^4.11.3": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/chai-as-promised@^7.1.3": + version "7.1.5" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.3.3": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" + integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== + +"@types/elliptic@^6.4.14": + version "6.4.14" + resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.14.tgz#7bbaad60567a588c1f08b10893453e6b9b4de48e" + integrity sha512-z4OBcDAU0GVwDTuwJzQCiL6188QvZMkvoERgcVjq0/mPM8jCfdwZ3x5zQEVoL9WCAru3aG5wl3Z5Ww5wBWn7ZQ== + dependencies: + "@types/bn.js" "*" + +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/graceful-fs@^4.1.3": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/is-ci@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/is-ci/-/is-ci-3.0.0.tgz#7e8910af6857601315592436f030aaa3ed9783c3" + integrity sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ== + dependencies: + ci-info "^3.1.0" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^28.1.0": + version "28.1.8" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-28.1.8.tgz#6936409f3c9724ea431efd412ea0238a0f03b09b" + integrity sha512-8TJkV++s7B6XqnDrzR1m/TT0A0h948Pnl/097veySPN67VRAgQ4gZ7n2KfJo2rVq6njQjdxU3GCCyDvAeuHoiw== + dependencies: + expect "^28.0.0" + pretty-format "^28.0.0" + +"@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/minimatch@*": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + +"@types/minimist@^1.2.0": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== + +"@types/mocha@^9.1.1": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + +"@types/node@*": + version "18.15.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.12.tgz#833756634e78c829e1254db006468dadbb0c696b" + integrity sha512-Wha1UwsB3CYdqUm2PPzh/1gujGCNtWVUYF0mB00fJFoR4gTyWTDPjSm+zBF787Ahw8vSGgBja90MkgFwvB86Dg== + +"@types/node@>=13.7.0": + version "18.11.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.2.tgz#c59b7641832531264fda3f1ba610362dc9a7dfc8" + integrity sha512-BWN3M23gLO2jVG8g/XHIRFWiiV4/GckeFIqbU/C4V3xpoBBWSMk4OZomouN0wCkfQFPqgZikyLr7DOYDysIkkw== + +"@types/node@^12.7.1": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/node@^18.7.11": + version "18.15.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.10.tgz#4ee2171c3306a185d1208dad5f44dae3dee4cfe3" + integrity sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ== + +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.5": + version "2.7.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" + integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== + +"@types/readable-stream@^2.3.13": + version "2.3.15" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" + integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== + dependencies: + "@types/node" "*" + safe-buffer "~5.1.1" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@types/semver@^6.0.0": + version "6.2.3" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.3.tgz#5798ecf1bec94eaa64db39ee52808ec0693315aa" + integrity sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A== + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.13" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" + integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== + dependencies: + "@types/yargs-parser" "*" + +JSONStream@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" + integrity sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== + dependencies: + buffer "^6.0.3" + catering "^2.1.0" + is-buffer "^2.0.5" + level-supports "^4.0.0" + level-transcoder "^1.0.1" + module-error "^1.0.1" + queue-microtask "^1.2.3" + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + +address@^1.0.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" + integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== + +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-colors@^4.1.1, ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + +anymatch@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +anymatch@~3.1.1, anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.flat@^1.2.3: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" + integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-shim-unscopables "^1.0.0" + +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +async@1.x: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + +babel-jest@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.3.tgz#c1187258197c099072156a0a121c11ee1e3917d5" + integrity sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q== + dependencies: + "@jest/transform" "^28.1.3" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^28.1.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz#1952c4d0ea50f2d6d794353762278d1d8cca3fbe" + integrity sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz#5dfc20b99abed5db994406c2b9ab94c73aaa419d" + integrity sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A== + dependencies: + babel-plugin-jest-hoist "^28.1.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +better-path-resolve@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/better-path-resolve/-/better-path-resolve-1.0.0.tgz#13a35a1104cdd48a7b74bf8758f96a1ee613f99d" + integrity sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g== + dependencies: + is-windows "^1.0.0" + +bigint-crypto-utils@^3.0.23: + version "3.2.2" + resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz#e30a49ec38357c6981cd3da5aaa6480b1f752ee4" + integrity sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw== + +bignumber.js@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== + +bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +breakword@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/breakword/-/breakword-1.0.5.tgz#fd420a417f55016736b5b615161cae1c8f819810" + integrity sha512-ex5W9DoOQ/LUEU3PMdLs9ua/CYZl1678NUkKOdUSi8Aw5F1idieaiRURCBFJCwVcrD1J8Iy3vfWSloaMwO2qFg== + dependencies: + wcwidth "^1.0.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-level@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" + integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.1" + module-error "^1.0.2" + run-parallel-limit "^1.1.0" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserslist@^4.21.3: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bufio@^1.0.7: + version "1.1.3" + resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.1.3.tgz#7f8e524fd719ced2caa563a09d50550f283f745f" + integrity sha512-W0ydG8t+ST+drUpEwl1N+dU9Ije06g8+43CLtvEIzfKo9nPFLXbKqDYE2XSg4w6RugsBcCj7pEU7jOpBC6BqrA== + +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001400: + version "1.0.30001422" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001422.tgz#f2d7c6202c49a8359e6e35add894d88ef93edba1" + integrity sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog== + +case@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" + integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== + +catering@^2.1.0, catering@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" + integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== + dependencies: + check-error "^1.0.2" + +chai@^4.3.4: + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chai@^4.3.6: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + +chokidar@3.5.3, chokidar@^3.4.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.0.1, chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.1.0, ci-info@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.5.0.tgz#bfac2a29263de4c829d806b1ab478e35091e171f" + integrity sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +classic-level@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.3.0.tgz#5e36680e01dc6b271775c093f2150844c5edd5c8" + integrity sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.0" + module-error "^1.0.1" + napi-macros "^2.2.2" + node-gyp-build "^4.3.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +csv-generate@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/csv-generate/-/csv-generate-3.4.3.tgz#bc42d943b45aea52afa896874291da4b9108ffff" + integrity sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw== + +csv-parse@^4.16.3: + version "4.16.3" + resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.16.3.tgz#7ca624d517212ebc520a36873c3478fa66efbaf7" + integrity sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg== + +csv-stringify@^5.6.5: + version "5.6.5" + resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-5.6.5.tgz#c6d74badda4b49a79bf4e72f91cce1e33b94de00" + integrity sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A== + +csv@^5.5.0: + version "5.5.3" + resolved "https://registry.yarnpkg.com/csv/-/csv-5.5.3.tgz#cd26c1e45eae00ce6a9b7b27dcb94955ec95207d" + integrity sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g== + dependencies: + csv-generate "^3.4.3" + csv-parse "^4.16.3" + csv-stringify "^5.6.5" + stream-transform "^2.1.3" + +death@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== + +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize-keys@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deep-eql@^4.0.1, deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +detect-indent@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" + integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +detect-port@^1.3.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" + integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== + dependencies: + address "^1.0.1" + debug "4" + +diff-sequences@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6" + integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw== + +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +difflib@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e" + integrity sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w== + dependencies: + heap ">= 0.2.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +docker-modem@^1.0.8: + version "1.0.9" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-1.0.9.tgz#a1f13e50e6afb6cf3431b2d5e7aac589db6aaba8" + integrity sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw== + dependencies: + JSONStream "1.3.2" + debug "^3.2.6" + readable-stream "~1.0.26-4" + split-ca "^1.0.0" + +dockerode@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-2.5.8.tgz#1b661e36e1e4f860e25f56e0deabe9f87f1d0acc" + integrity sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw== + dependencies: + concat-stream "~1.6.2" + docker-modem "^1.0.8" + tar-fs "~1.16.3" + +dotenv@^16.0.1: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + +elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emittery@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" + integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.0: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.19.0, es-abstract@^1.19.2, es-abstract@^1.19.5: + version "1.20.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861" + integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.2" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" + +es-abstract@^1.20.4: + version "1.21.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" + integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.4" + is-array-buffer "^3.0.1" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.2" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A== + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-cryptography@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + +ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^7.1.0: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethers@^5.6.8, ethers@^5.6.9, ethers@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit-hook@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.1.tgz#007b2d92c6428eda2b76e7016a34351586934593" + integrity sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw== + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + +expect@^28.0.0, expect@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.3.tgz#90a7c1a124f1824133dd4533cce2d2bdcb6603ec" + integrity sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g== + dependencies: + "@jest/expect-utils" "^28.1.3" + jest-get-type "^28.0.2" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + +extendable-error@^0.1.5: + version "0.1.7" + resolved "https://registry.yarnpkg.com/extendable-error/-/extendable-error-0.1.7.tgz#60b9adf206264ac920058a7395685ae4670c2b96" + integrity sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg== + +external-editor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +fast-glob@^3.0.3, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-yarn-workspace-root2@1.2.16: + version "1.2.16" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz#60287009dd2f324f59646bdb4b7610a6b301c2a9" + integrity sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA== + dependencies: + micromatch "^4.0.2" + pkg-dir "^4.2.0" + +flat@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== + dependencies: + is-buffer "~2.0.3" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +follow-redirects@^1.12.1, follow-redirects@^1.14.4: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +from2@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +fsevents@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-intrinsic@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +ghost-testrpc@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz#c4de9557b1d1ae7b2d20bbe474a91378ca90ce92" + integrity sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ== + dependencies: + chalk "^2.4.2" + node-emoji "^1.10.0" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + +glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globby@^11.0.0, globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graceful-fs@^4.1.5, graceful-fs@^4.2.0, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +handlebars@^4.0.1: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + +hardhat@^*, hardhat@^2.10.2: + version "2.14.0" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.14.0.tgz#b60c74861494aeb1b50803cf04cc47865a42b87a" + integrity sha512-73jsInY4zZahMSVFurSK+5TNCJTXMv+vemvGia0Ac34Mm19fYp6vEPVGF3sucbumszsYxiTT2TbS8Ii2dsDSoQ== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-vm" "7.0.1" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + qs "^6.7.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +"heap@>= 0.2.0": + version "0.2.7" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" + integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +human-id@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/human-id/-/human-id-1.0.2.tgz#e654d4b2b0d8b07e45da9f6020d8af17ec0a5df3" + integrity sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.13, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.1.1: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +immutable@^4.0.0-rc.12: + version "4.3.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be" + integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^1.3.5, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +internal-slot@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" + integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + side-channel "^1.0.4" + +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +into-stream@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-6.0.0.tgz#4bfc1244c0128224e18b8870e85b2de8e66c6702" + integrity sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA== + dependencies: + from2 "^2.3.0" + p-is-promise "^3.0.0" + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +is-array-buffer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" + integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-typed-array "^1.1.10" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^2.0.5, is-buffer@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-ci@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== + dependencies: + ci-info "^3.2.0" + +is-core-module@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + dependencies: + has "^1.0.3" + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-subdir@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-subdir/-/is-subdir-1.2.0.tgz#b791cd28fab5202e91a08280d51d9d7254fd20d4" + integrity sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw== + dependencies: + better-path-resolve "1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isomorphic-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" + integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== + dependencies: + node-fetch "^2.6.1" + whatwg-fetch "^3.4.1" + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-28.1.3.tgz#d9aeee6792be3686c47cb988a8eaf82ff4238831" + integrity sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA== + dependencies: + execa "^5.0.0" + p-limit "^3.1.0" + +jest-circus@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.3.tgz#d14bd11cf8ee1a03d69902dc47b6bd4634ee00e4" + integrity sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/expect" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + is-generator-fn "^2.0.0" + jest-each "^28.1.3" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-runtime "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + p-limit "^3.1.0" + pretty-format "^28.1.3" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.3.tgz#558b33c577d06de55087b8448d373b9f654e46b2" + integrity sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ== + dependencies: + "@jest/core" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" + prompts "^2.0.1" + yargs "^17.3.1" + +jest-config@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.3.tgz#e315e1f73df3cac31447eed8b8740a477392ec60" + integrity sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^28.1.3" + "@jest/types" "^28.1.3" + babel-jest "^28.1.3" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^28.1.3" + jest-environment-node "^28.1.3" + jest-get-type "^28.0.2" + jest-regex-util "^28.0.2" + jest-resolve "^28.1.3" + jest-runner "^28.1.3" + jest-util "^28.1.3" + jest-validate "^28.1.3" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^28.1.3" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.3.tgz#948a192d86f4e7a64c5264ad4da4877133d8792f" + integrity sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw== + dependencies: + chalk "^4.0.0" + diff-sequences "^28.1.1" + jest-get-type "^28.0.2" + pretty-format "^28.1.3" + +jest-docblock@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-28.1.1.tgz#6f515c3bf841516d82ecd57a62eed9204c2f42a8" + integrity sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA== + dependencies: + detect-newline "^3.0.0" + +jest-each@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.3.tgz#bdd1516edbe2b1f3569cfdad9acd543040028f81" + integrity sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g== + dependencies: + "@jest/types" "^28.1.3" + chalk "^4.0.0" + jest-get-type "^28.0.2" + jest-util "^28.1.3" + pretty-format "^28.1.3" + +jest-environment-node@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.3.tgz#7e74fe40eb645b9d56c0c4b70ca4357faa349be5" + integrity sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/fake-timers" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + jest-mock "^28.1.3" + jest-util "^28.1.3" + +jest-get-type@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" + integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA== + +jest-haste-map@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.3.tgz#abd5451129a38d9841049644f34b034308944e2b" + integrity sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA== + dependencies: + "@jest/types" "^28.1.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^28.0.2" + jest-util "^28.1.3" + jest-worker "^28.1.3" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz#a6685d9b074be99e3adee816ce84fd30795e654d" + integrity sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA== + dependencies: + jest-get-type "^28.0.2" + pretty-format "^28.1.3" + +jest-matcher-utils@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz#5a77f1c129dd5ba3b4d7fc20728806c78893146e" + integrity sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw== + dependencies: + chalk "^4.0.0" + jest-diff "^28.1.3" + jest-get-type "^28.0.2" + pretty-format "^28.1.3" + +jest-message-util@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.3.tgz#232def7f2e333f1eecc90649b5b94b0055e7c43d" + integrity sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^28.1.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^28.1.3" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.3.tgz#d4e9b1fc838bea595c77ab73672ebf513ab249da" + integrity sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA== + dependencies: + "@jest/types" "^28.1.3" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + +jest-regex-util@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead" + integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw== + +jest-resolve-dependencies@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz#8c65d7583460df7275c6ea2791901fa975c1fe66" + integrity sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA== + dependencies: + jest-regex-util "^28.0.2" + jest-snapshot "^28.1.3" + +jest-resolve@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.3.tgz#cfb36100341ddbb061ec781426b3c31eb51aa0a8" + integrity sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + jest-pnp-resolver "^1.2.2" + jest-util "^28.1.3" + jest-validate "^28.1.3" + resolve "^1.20.0" + resolve.exports "^1.1.0" + slash "^3.0.0" + +jest-runner@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.3.tgz#5eee25febd730b4713a2cdfd76bdd5557840f9a1" + integrity sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA== + dependencies: + "@jest/console" "^28.1.3" + "@jest/environment" "^28.1.3" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.10.2" + graceful-fs "^4.2.9" + jest-docblock "^28.1.1" + jest-environment-node "^28.1.3" + jest-haste-map "^28.1.3" + jest-leak-detector "^28.1.3" + jest-message-util "^28.1.3" + jest-resolve "^28.1.3" + jest-runtime "^28.1.3" + jest-util "^28.1.3" + jest-watcher "^28.1.3" + jest-worker "^28.1.3" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.3.tgz#a57643458235aa53e8ec7821949e728960d0605f" + integrity sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw== + dependencies: + "@jest/environment" "^28.1.3" + "@jest/fake-timers" "^28.1.3" + "@jest/globals" "^28.1.3" + "@jest/source-map" "^28.1.2" + "@jest/test-result" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^28.1.3" + jest-message-util "^28.1.3" + jest-mock "^28.1.3" + jest-regex-util "^28.0.2" + jest-resolve "^28.1.3" + jest-snapshot "^28.1.3" + jest-util "^28.1.3" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.3.tgz#17467b3ab8ddb81e2f605db05583d69388fc0668" + integrity sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^28.1.3" + "@jest/transform" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/babel__traverse" "^7.0.6" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^28.1.3" + graceful-fs "^4.2.9" + jest-diff "^28.1.3" + jest-get-type "^28.0.2" + jest-haste-map "^28.1.3" + jest-matcher-utils "^28.1.3" + jest-message-util "^28.1.3" + jest-util "^28.1.3" + natural-compare "^1.4.0" + pretty-format "^28.1.3" + semver "^7.3.5" + +jest-util@^28.0.0, jest-util@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.3.tgz#f4f932aa0074f0679943220ff9cbba7e497028b0" + integrity sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ== + dependencies: + "@jest/types" "^28.1.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.3.tgz#e322267fd5e7c64cea4629612c357bbda96229df" + integrity sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA== + dependencies: + "@jest/types" "^28.1.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^28.0.2" + leven "^3.1.0" + pretty-format "^28.1.3" + +jest-watcher@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.3.tgz#c6023a59ba2255e3b4c57179fc94164b3e73abd4" + integrity sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g== + dependencies: + "@jest/test-result" "^28.1.3" + "@jest/types" "^28.1.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.10.2" + jest-util "^28.1.3" + string-length "^4.0.1" + +jest-worker@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.3.tgz#7e3c4ce3fa23d1bb6accb169e7f396f98ed4bb98" + integrity sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^28.1.0: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.3.tgz#e9c6a7eecdebe3548ca2b18894a50f45b36dfc6b" + integrity sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA== + dependencies: + "@jest/core" "^28.1.3" + "@jest/types" "^28.1.3" + import-local "^3.0.2" + jest-cli "^28.1.3" + +js-sdsl@^4.1.4: + version "4.4.0" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" + integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg== + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@3.x, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.6.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + +jsonschema@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" + integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== + +keccak@^3.0.0, keccak@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +kind-of@^6.0.2, kind-of@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +kleur@^4.1.4: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + +level-supports@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" + integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== + +level-transcoder@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" + integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== + dependencies: + buffer "^6.0.3" + module-error "^1.0.1" + +level@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" + integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== + dependencies: + browser-level "^1.0.1" + classic-level "^1.2.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +load-yaml-file@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/load-yaml-file/-/load-yaml-file-0.2.0.tgz#af854edaf2bea89346c07549122753c07372f64d" + integrity sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw== + dependencies: + graceful-fs "^4.1.5" + js-yaml "^3.13.0" + pify "^4.0.1" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.startcase@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz#9436e34ed26093ed7ffae1936144350915d9add8" + integrity sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg== + +lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + +lossless-json@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-2.0.8.tgz#dd0e14f7d327e9e11fe89123b583c011f2ad0917" + integrity sha512-7/GaZldUc7H5oNZlSk6bF06cRbtA7oF8zWXwbfMZm8yrYC2debx0KvWTBbQIbj6fh08LsXTWg+YtHJshXgYKow== + +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@1.x, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +memory-level@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" + integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== + dependencies: + abstract-level "^1.0.0" + functional-red-black-tree "^1.0.1" + module-error "^1.0.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +meow@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.1.tgz#1ad64c4b76b2a24dfb2f635fddcadf320d251467" + integrity sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "^4.0.2" + normalize-package-data "^2.5.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.13.1" + yargs-parser "^18.1.3" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micro-starknet@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/micro-starknet/-/micro-starknet-0.2.3.tgz#ff4e7caf599255d2110e9c57bb483dfaf493ccb3" + integrity sha512-6XBcC+GerlwJSR4iA0VaeXtS2wrayWFcA4PEzrJPMuFmWCaUtuGIq5K/DB5F/XgnL54/zl2Bxo690Lj7mYVA8A== + dependencies: + "@noble/curves" "~1.0.0" + "@noble/hashes" "~1.3.0" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimist-options@^4.0.2: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mixme@^0.5.1: + version "0.5.4" + resolved "https://registry.yarnpkg.com/mixme/-/mixme-0.5.4.tgz#8cb3bd0cd32a513c161bf1ca99d143f0bcf2eff3" + integrity sha512-3KYa4m4Vlqx98GPdOHghxSdNtTvcP8E0kkaJ5Dlh+h2DRzF7zpuVVcA8B0QpKd11YJeP9QQ7ASkKzOeu195Wzw== + +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp@0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mkdirp@0.5.x, mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.2.tgz#8e40d198acf91a52ace122cd7599c9ab857b29e6" + integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + chokidar "3.3.0" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "3.0.0" + minimatch "3.0.4" + mkdirp "0.5.5" + ms "2.1.1" + node-environment-flags "1.0.6" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "1.6.0" + +mocha@^10.0.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +module-error@^1.0.1, module-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" + integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multistream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/multistream/-/multistream-4.1.0.tgz#7bf00dfd119556fbc153cff3de4c6d477909f5a8" + integrity sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw== + dependencies: + once "^1.4.0" + readable-stream "^3.6.0" + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== + +napi-macros@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.2.2.tgz#817fef20c3e0e40a963fbf7b37d1600bd0201044" + integrity sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +neo-async@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-abi@^2.21.0: + version "2.30.1" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.1.tgz#c437d4b1fe0e285aaf290d45b45d4d7afedac4cf" + integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w== + dependencies: + semver "^5.4.1" + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-addon-api@^3.0.2: + version "3.2.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + +node-addon-api@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + +node-emoji@^1.10.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== + dependencies: + lodash "^4.17.21" + +node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +node-fetch@2.6.7, node-fetch@^2.6.6: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.0, node-fetch@^2.6.1: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + +node-hid@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-2.1.1.tgz#f83c8aa0bb4e6758b5f7383542477da93f67359d" + integrity sha512-Skzhqow7hyLZU93eIPthM9yjot9lszg9xrKxESleEs05V2NcbUptZc5HFqzjOkSmL0sFlZFr3kmvaYebx06wrw== + dependencies: + bindings "^1.5.0" + node-addon-api "^3.0.2" + prebuild-install "^6.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== + dependencies: + abbrev "1" + +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npmlog@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-keys@^1.0.11, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.0.3: + version "2.1.5" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz#db5a9002489b64eef903df81d6623c07e5b4b4d3" + integrity sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw== + dependencies: + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== + +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +ordinal@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" + integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +outdent@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/outdent/-/outdent-0.5.0.tgz#9e10982fdc41492bb473ad13840d22f9655be2ff" + integrity sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q== + +p-filter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c" + integrity sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw== + dependencies: + p-map "^2.0.0" + +p-is-promise@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-3.0.0.tgz#58e78c7dfe2e163cf2a04ff869e7c1dba64a5971" + integrity sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + +parse-json@^5.0.0, parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pirates@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-fetch@3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/pkg-fetch/-/pkg-fetch-3.4.2.tgz#6f68ebc54842b73f8c0808959a9df3739dcb28b7" + integrity sha512-0+uijmzYcnhC0hStDjm/cl2VYdrmVVBpe7Q8k9YBojxmR5tG8mvR9/nooQq3QSXiQqORDVOTY3XqMEqJVIzkHA== + dependencies: + chalk "^4.1.2" + fs-extra "^9.1.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.6" + progress "^2.0.3" + semver "^7.3.5" + tar-fs "^2.1.1" + yargs "^16.2.0" + +pkg@^5.2.1: + version "5.8.0" + resolved "https://registry.yarnpkg.com/pkg/-/pkg-5.8.0.tgz#a77644aeff0b94a1656d7f76558837f7c754a4c0" + integrity sha512-8h9PUDYFi+LOMLbIyGRdP21g08mAtHidSpofSrf8LWhxUWGHymaRzcopEGiynB5EhQmZUKM6PQ9kCImV2TpdjQ== + dependencies: + "@babel/generator" "7.18.2" + "@babel/parser" "7.18.4" + "@babel/types" "7.18.4" + chalk "^4.1.2" + fs-extra "^9.1.0" + globby "^11.1.0" + into-stream "^6.0.0" + is-core-module "2.9.0" + minimist "^1.2.6" + multistream "^4.1.0" + pkg-fetch "3.4.2" + prebuild-install "6.1.4" + resolve "^1.22.0" + stream-meter "^1.0.4" + +prebuild-install@6.1.4, prebuild-install@^6.0.0: + version "6.1.4" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.4.tgz#ae3c0142ad611d58570b89af4986088a4937e00f" + integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^2.21.0" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + +preferred-pm@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/preferred-pm/-/preferred-pm-3.0.3.tgz#1b6338000371e3edbce52ef2e4f65eb2e73586d6" + integrity sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ== + dependencies: + find-up "^5.0.0" + find-yarn-workspace-root2 "1.2.16" + path-exists "^4.0.0" + which-pm "2.0.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +prettier@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6" + integrity sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw== + +prettier@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== + +pretty-format@^28.0.0, pretty-format@^28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.3.tgz#c9fba8cedf99ce50963a11b27d982a9ae90970d5" + integrity sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q== + dependencies: + "@jest/schemas" "^28.1.3" + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +protobufjs@^6.11.2: + version "6.11.3" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" + integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +qs@^6.7.0: + version "6.11.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" + integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ== + dependencies: + side-channel "^1.0.4" + +queue-microtask@^1.2.2, queue-microtask@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +raw-body@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +read-yaml-file@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-yaml-file/-/read-yaml-file-1.1.0.tgz#9362bbcbdc77007cc8ea4519fe1c0b821a7ce0d8" + integrity sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA== + dependencies: + graceful-fs "^4.1.5" + js-yaml "^3.6.1" + pify "^4.0.1" + strip-bom "^3.0.0" + +readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.1.4: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.26-4: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== + dependencies: + resolve "^1.1.6" + +recursive-readdir@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" + integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== + dependencies: + minimatch "^3.0.5" + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + +regenerator-runtime@^0.13.10: + version "0.13.10" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" + integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw== + +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" + integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.2.8: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-parallel-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" + integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== + dependencies: + queue-microtask "^1.2.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +rxjs@6: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sc-istanbul@^0.4.5: + version "0.4.6" + resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" + integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +scrypt-js@3.0.1, scrypt-js@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@7.x, semver@^7.3.4, semver@^7.3.5: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shelljs@^0.8.3, shelljs@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smartwrap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/smartwrap/-/smartwrap-2.0.2.tgz#7e25d3dd58b51c6ca4aba3a9e391650ea62698a4" + integrity sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA== + dependencies: + array.prototype.flat "^1.2.3" + breakword "^1.0.5" + grapheme-splitter "^1.0.4" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + yargs "^15.1.0" + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solidity-coverage@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.2.tgz#bc39604ab7ce0a3fa7767b126b44191830c07813" + integrity sha512-cv2bWb7lOXPE9/SSleDO6czkFiMHgP4NXPj+iW9W7iEKLBk7Cj0AGBiNmGX3V1totl9wjPrT0gHmABZKZt65rQ== + dependencies: + "@ethersproject/abi" "^5.0.9" + "@solidity-parser/parser" "^0.14.1" + chalk "^2.4.2" + death "^1.1.0" + detect-port "^1.3.0" + difflib "^0.2.4" + fs-extra "^8.1.0" + ghost-testrpc "^0.0.2" + global-modules "^2.0.0" + globby "^10.0.1" + jsonschema "^1.2.4" + lodash "^4.17.15" + mocha "7.1.2" + node-emoji "^1.10.0" + pify "^4.0.1" + recursive-readdir "^2.2.2" + sc-istanbul "^0.4.5" + semver "^7.3.4" + shelljs "^0.8.3" + web3-utils "^1.3.6" + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA== + dependencies: + amdefine ">=0.0.4" + +spawndamnit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawndamnit/-/spawndamnit-2.0.0.tgz#9f762ac5c3476abb994b42ad592b5ad22bb4b0ad" + integrity sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA== + dependencies: + cross-spawn "^5.1.0" + signal-exit "^3.0.2" + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.12" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" + integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + +split-ca@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + dependencies: + escape-string-regexp "^2.0.0" + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +starknet@^3.15.0, starknet@^3.5.1: + version "3.19.0" + resolved "https://registry.yarnpkg.com/starknet/-/starknet-3.19.0.tgz#b3ce7fc87a3062f126b7dd92f38d6f70e509f192" + integrity sha512-1iUJdGtRDu2j3G8sS+yzRhp9O3O5Dr803oDfrm234Qmn05JTh5bU/wZwFPw9zWmMI0jyNZgjS+8dxPpBcpLgrQ== + dependencies: + "@ethersproject/bytes" "^5.6.1" + bn.js "^5.2.1" + cross-fetch "^3.1.5" + elliptic "^6.5.4" + ethereum-cryptography "^1.0.3" + hash.js "^1.1.7" + json-bigint "^1.0.0" + minimalistic-assert "^1.0.1" + pako "^2.0.4" + ts-custom-error "^3.2.0" + url-join "^4.0.1" + +starknet@^4.17.1: + version "4.22.0" + resolved "https://registry.yarnpkg.com/starknet/-/starknet-4.22.0.tgz#8d0c628e2a8e868ee9b4757afe89f07b05ec55ff" + integrity sha512-jC9Taxb6a/ht9zmS1LU/DSLfwJKpgCJnE9AktVksc5SE/+jQMpqxsq6fm7PRiqupjiqRC1DOS8N47cj+KaGv4Q== + dependencies: + "@ethersproject/bytes" "^5.6.1" + bn.js "^5.2.1" + elliptic "^6.5.4" + ethereum-cryptography "^1.0.3" + hash.js "^1.1.7" + isomorphic-fetch "^3.0.0" + json-bigint "^1.0.0" + minimalistic-assert "^1.0.1" + pako "^2.0.4" + ts-custom-error "^3.3.1" + url-join "^4.0.1" + +starknet@^5.2.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/starknet/-/starknet-5.8.0.tgz#ac18f7eb978aa5649e51defbb50b03f1ef6c2f43" + integrity sha512-PZ1+ulh9lxSNG1ukWx+rguWAHdxhyI6EBrWkJH/ifHAxK6tWoRJslI7PSD+Zt3nGJKC27b+RAE2UhD617K1t+g== + dependencies: + "@noble/curves" "^0.8.2" + isomorphic-fetch "^3.0.0" + lossless-json "^2.0.8" + micro-starknet "^0.2.1" + pako "^2.0.4" + url-join "^4.0.1" + +starsign-multisig@0.3.0, starsign-multisig@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/starsign-multisig/-/starsign-multisig-0.3.0.tgz#de4ed470f3c692902d003e94cde65406e62e2bc6" + integrity sha512-GbUHI+9CtvXKca4HrKqBrHpqo7Sv2Aad6lBjf+eyK4f2AA9RemV+cIl0A8819Z4KLaRSdOQioyHNL1siFMV1Ew== + dependencies: + starknet "^3.5.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stream-meter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/stream-meter/-/stream-meter-1.0.4.tgz#52af95aa5ea760a2491716704dbff90f73afdd1d" + integrity sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ== + dependencies: + readable-stream "^2.1.4" + +stream-transform@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/stream-transform/-/stream-transform-2.1.3.tgz#a1c3ecd72ddbf500aa8d342b0b9df38f5aa598e3" + integrity sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ== + dependencies: + mixme "^0.5.1" + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@2.0.1, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + +supports-color@8.1.1, supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tar-fs@^2.0.0, tar-fs@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-fs@~1.16.3: + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" + integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-stream@^1.1.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +term-size@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" + integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + +ts-custom-error@^3.2.0, ts-custom-error@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1" + integrity sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A== + +ts-jest@^28.0.7: + version "28.0.8" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-28.0.8.tgz#cd204b8e7a2f78da32cf6c95c9a6165c5b99cc73" + integrity sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^28.0.0" + json5 "^2.2.1" + lodash.memoize "4.x" + make-error "1.x" + semver "7.x" + yargs-parser "^21.0.1" + +ts-node@^10.8.0: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^1.9.0, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tty-table@^4.1.5: + version "4.1.6" + resolved "https://registry.yarnpkg.com/tty-table/-/tty-table-4.1.6.tgz#6bd58338f36c94cce478c3337934d8a65ab40a73" + integrity sha512-kRj5CBzOrakV4VRRY5kUWbNYvo/FpOsz65DzI5op9P+cHov3+IqPbo1JE1ZnQGkHdZgNFDsrEjrfqqy/Ply9fw== + dependencies: + chalk "^4.1.2" + csv "^5.5.0" + kleur "^4.1.4" + smartwrap "^2.0.2" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + yargs "^17.1.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" + integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +typescript@4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4" + integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A== + +uglify-js@^3.1.4: + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undici@^5.14.0: + version "5.21.2" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.21.2.tgz#329f628aaea3f1539a28b9325dccc72097d29acd" + integrity sha512-f6pTQ9RF4DQtwoWSaC42P/NKlUjvezVvd9r155ohqkwFNRyBKM3f3pcty3ouusefNRyM25XhIQEbeQ46sZDJfQ== + dependencies: + busboy "^1.6.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +usb@^1.7.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/usb/-/usb-1.9.2.tgz#fb6b36f744ecc707a196c45a6ec72442cb6f2b73" + integrity sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg== + dependencies: + node-addon-api "^4.2.0" + node-gyp-build "^4.3.0" + +utf8@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" + integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +web3-utils@^1.3.6: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" + integrity sha512-LgnM9p6V7rHHUGfpMZod+NST8cRfGzJ1BTXAyNo7A9cJX9LczBfSRxJp+U/GInYe9mby40t3v22AJdlELibnsQ== + dependencies: + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-fetch@^3.4.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + +which-pm@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-pm/-/which-pm-2.0.0.tgz#8245609ecfe64bf751d0eef2f376d83bf1ddb7ae" + integrity sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w== + dependencies: + load-yaml-file "^0.2.0" + path-exists "^4.0.0" + +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wide-align@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^18.1.2, yargs-parser@^18.1.3: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.0.0, yargs-parser@^21.0.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@13.3.2, yargs@^13.3.0: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + +yargs@16.2.0, yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^15.1.0: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.1.1, yargs@^17.3.1: + version "17.6.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.1.tgz#712508771045019cda059bc1ba3ae091aaa1402e" + integrity sha512-leBuCGrL4dAd6ispNOGsJlhd0uZ6Qehkbu/B9KCR+Pxa/NVdNwi+i31lo0buCm6XxhJQFshXCD0/evfV4xfoUg== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==