diff --git a/.github/workflows/contracts-ecdsa.yml b/.github/workflows/contracts-ecdsa.yml index c68b350e80..071a8898ee 100644 --- a/.github/workflows/contracts-ecdsa.yml +++ b/.github/workflows/contracts-ecdsa.yml @@ -264,9 +264,15 @@ jobs: contracts-deployment-testnet: needs: [contracts-build-and-test] - if: | - github.event_name == 'workflow_dispatch' - && github.ref != 'refs/heads/dapp-development' + # The ethers v6 deployment exports break existing ethers v5 consumers. + # Block workflow_dispatch publication to the `` tag; this + # gate replaces the original dispatch condition, kept here so it can be + # restored: + # github.event_name == 'workflow_dispatch' + # && github.ref != 'refs/heads/dapp-development' + # Re-enable only after the consumer migration and release pins are ready; + # see solidity/docs/ethers-v6-compatibility.md#limits-and-release-gates. + if: ${{ false }} runs-on: ubuntu-latest defaults: run: @@ -364,9 +370,15 @@ jobs: # `dapp-development`. contracts-dapp-development-deployment-testnet: needs: [contracts-build-and-test] - if: | - github.event_name == 'workflow_dispatch' - && github.ref == 'refs/heads/dapp-development' + # The ethers v6 deployment exports break existing ethers v5 consumers. + # Block workflow_dispatch publication to the + # `dapp-development-` tag; this gate replaces the original + # dispatch condition, kept here so it can be restored: + # github.event_name == 'workflow_dispatch' + # && github.ref == 'refs/heads/dapp-development' + # Re-enable only after the consumer migration and release pins are ready; + # see solidity/docs/ethers-v6-compatibility.md#limits-and-release-gates. + if: ${{ false }} runs-on: ubuntu-latest defaults: run: diff --git a/.github/workflows/contracts-random-beacon.yml b/.github/workflows/contracts-random-beacon.yml index 1857b3b100..0f86ebe501 100644 --- a/.github/workflows/contracts-random-beacon.yml +++ b/.github/workflows/contracts-random-beacon.yml @@ -37,6 +37,7 @@ jobs: runs-on: ubuntu-latest outputs: path-filter: ${{ steps.filter.outputs.path-filter }} + bundled-beacon-export-filter: ${{ steps.filter.outputs.bundled-beacon-export-filter }} steps: - uses: actions/checkout@v3 if: github.event_name == 'pull_request' @@ -50,6 +51,12 @@ jobs: - './.github/workflows/contracts-random-beacon.yml' - './.github/actions/install-yarn-deps/**' - './.github/actions/docker-build-push/**' + bundled-beacon-export-filter: + - './solidity/random-beacon/deploy/**' + - './solidity/random-beacon/tasks/**' + - './solidity/random-beacon/utils/**' + - './solidity/ecdsa/external/random-beacon-export/**' + - './.github/workflows/contracts-random-beacon.yml' contracts-lint: needs: contracts-detect-changes @@ -251,11 +258,71 @@ jobs: fi echo 'export byte-identity OK' + # ECDSA bundles the compiled Beacon deployment scripts, tasks and utilities + # under solidity/ecdsa/external/random-beacon-export/ so it can deploy + # against a v6 Beacon while the published Beacon package is still ethers v5. + # That bundle is generated from this package's TypeScript sources, so any + # change under deploy/, tasks/ or utils/ silently makes it stale - until now + # only the manual + # solidity/scripts/ethers-v6-compatibility/pack-and-capture.cjs script + # checked it, and that script never runs in CI. This job regenerates the + # exports and byte-compares them against the committed bundle, so drift + # fails here instead of shipping. + bundled-beacon-export-freshness: + needs: contracts-detect-changes + if: github.event_name != 'pull_request' || needs.contracts-detect-changes.outputs.bundled-beacon-export-filter == 'true' + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./solidity/random-beacon + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + # Pinned to match the Dockerfiles exactly so CI and the image cannot + # drift apart. Node 24 requires hardhat >= 2.26 - below it, the solc + # download fails with HH502 (see PR description for details). + node-version: "24.11.1" + + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/random-beacon + + - name: Build solidity contracts + run: yarn build + + - name: Generate packed export artifacts + run: yarn prepack + + - name: Verify bundled Beacon export is up to date + run: | + set -e + bundle=../ecdsa/external/random-beacon-export + staging="$(mktemp -d)" + mkdir -p "$staging/deploy" "$staging/utils" "$staging/tasks/utils" + cp export/deploy/*.js "$staging/deploy/" + cp export/utils/wait-for-confirmations.js "$staging/utils/" + cp export/tasks/initialize.js export/tasks/unlock-eth-accounts.js "$staging/tasks/" + cp export/tasks/utils/*.js "$staging/tasks/utils/" + if ! diff -r --exclude=README.md "$staging" "$bundle"; then + echo '::error::solidity/ecdsa/external/random-beacon-export/ is stale - it no longer matches solidity/random-beacon/export/.' + echo '::error::Regenerate it with the commands documented in solidity/ecdsa/external/random-beacon-export/README.md and commit the result alongside this change.' + exit 1 + fi + echo 'bundled Beacon export freshness OK' + contracts-deployment-testnet: needs: [contracts-build-and-test] - if: | - github.event_name == 'workflow_dispatch' - && github.ref != 'refs/heads/dapp-development' + # The ethers v6 deployment exports break existing ethers v5 consumers. + # Block workflow_dispatch publication to the `` tag; this + # gate replaces the original dispatch condition, kept here so it can be + # restored: + # github.event_name == 'workflow_dispatch' + # && github.ref != 'refs/heads/dapp-development' + # Re-enable only after the consumer migration and release pins are ready; + # see solidity/docs/ethers-v6-compatibility.md#limits-and-release-gates. + if: ${{ false }} runs-on: ubuntu-latest defaults: run: @@ -351,9 +418,15 @@ jobs: # `dapp-development`. contracts-dapp-development-deployment-testnet: needs: [contracts-build-and-test] - if: | - github.event_name == 'workflow_dispatch' - && github.ref == 'refs/heads/dapp-development' + # The ethers v6 deployment exports break existing ethers v5 consumers. + # Block workflow_dispatch publication to the + # `dapp-development-` tag; this gate replaces the original + # dispatch condition, kept here so it can be restored: + # github.event_name == 'workflow_dispatch' + # && github.ref == 'refs/heads/dapp-development' + # Re-enable only after the consumer migration and release pins are ready; + # see solidity/docs/ethers-v6-compatibility.md#limits-and-release-gates. + if: ${{ false }} runs-on: ubuntu-latest defaults: run: diff --git a/.github/workflows/npm-ecdsa.yml b/.github/workflows/npm-ecdsa.yml index ceb3f34d97..f9d4fa8a90 100644 --- a/.github/workflows/npm-ecdsa.yml +++ b/.github/workflows/npm-ecdsa.yml @@ -8,14 +8,24 @@ on: - "solidity/ecdsa/contracts/**" - "solidity/ecdsa/deploy/**" - "solidity/ecdsa/tasks/**" + - "solidity/ecdsa/utils/**" + - "solidity/ecdsa/external/**" - "solidity/ecdsa/hardhat.config.ts" - "solidity/ecdsa/package.json" - "solidity/ecdsa/yarn.lock" + - "solidity/ecdsa/.nvmrc" + - "solidity/ecdsa/.yarnrc.yml" + - "solidity/ecdsa/.yarn/patches/**" - ".github/workflows/npm-ecdsa.yml" workflow_dispatch: jobs: npm-compile-publish-contracts: + # The ethers v6 deployment exports break existing ethers v5 consumers. + # Block both push and workflow_dispatch publication, including latest. + # Re-enable only after the consumer migration and release pins are ready; + # see solidity/docs/ethers-v6-compatibility.md#limits-and-release-gates. + if: ${{ false }} runs-on: ubuntu-latest defaults: run: diff --git a/.github/workflows/npm-random-beacon.yml b/.github/workflows/npm-random-beacon.yml index ce3ac7c2b5..7e8cb00dc3 100644 --- a/.github/workflows/npm-random-beacon.yml +++ b/.github/workflows/npm-random-beacon.yml @@ -8,14 +8,23 @@ on: - "solidity/random-beacon/contracts/**" - "solidity/random-beacon/deploy/**" - "solidity/random-beacon/tasks/**" + - "solidity/random-beacon/utils/**" - "solidity/random-beacon/hardhat.config.ts" - "solidity/random-beacon/package.json" - "solidity/random-beacon/yarn.lock" + - "solidity/random-beacon/.nvmrc" + - "solidity/random-beacon/.yarnrc.yml" + - "solidity/random-beacon/.yarn/patches/**" - ".github/workflows/npm-random-beacon.yml" workflow_dispatch: jobs: npm-compile-publish-contracts: + # The ethers v6 deployment exports break existing ethers v5 consumers. + # Block both push and workflow_dispatch publication, including latest. + # Re-enable only after the consumer migration and release pins are ready; + # see solidity/docs/ethers-v6-compatibility.md#limits-and-release-gates. + if: ${{ false }} runs-on: ubuntu-latest defaults: run: @@ -35,18 +44,9 @@ jobs: with: working-directory: ./solidity/random-beacon - - name: Resolve latest contracts - # `@threshold-network/solidity-contracts` is pinned to 1.3.0-dev.11 - # (the version used by the last successful publish, 2.1.0-dev.18) - # because the `development` dist-tag was bumped to 1.3.0-dev.16, - # which refactored `TokenStaking` and removed `approveApplication` - # (called by `deploy/05_approve_random_beacon_in_token_staking.ts`). - # Unpin once the deploy scripts and Go ABI bindings are migrated - # to the new TokenStaking API. - run: | - yarn up --exact \ - @keep-network/sortition-pools \ - @threshold-network/solidity-contracts@1.3.0-dev.11 + - name: Install locked dependencies + # Preserve the tested Threshold version and its local ethers v6 patch. + run: yarn install --immutable # Deploy contracts to a local network to generate deployment artifacts that # are required by dashboard and client compilation. diff --git a/solidity/.gitattributes b/solidity/.gitattributes new file mode 100644 index 0000000000..2ef444a895 --- /dev/null +++ b/solidity/.gitattributes @@ -0,0 +1,2 @@ +# Unified patch context lines intentionally preserve source whitespace. +*/.yarn/patches/*.patch -whitespace diff --git a/solidity/docs/ethers-v6-compatibility.md b/solidity/docs/ethers-v6-compatibility.md new file mode 100644 index 0000000000..601345c084 --- /dev/null +++ b/solidity/docs/ethers-v6-compatibility.md @@ -0,0 +1,208 @@ +# Ethers v6 compatibility checks + +This prepares the two Solidity packages for +[#4295](https://github.com/threshold-network/keep-core/issues/4295). It retains +Hardhat 2.29.0, hardhat-deploy 1.0.4 and ES2020/CommonJS deployment exports. The +comparison baseline is commit `4f7fa861b`: the strict TypeScript/Waffle-removal +stack plus maintained deploy v1, Node 24/Yarn 4 and ethers 5.8.0. Contract sources, +committed live deployment records and OpenZeppelin manifests are unchanged. + +## Runtime and patches + +Tested with Node 24.11.1 and Yarn 4.12.0. Both immutable lockfile installs pass. +The active client is ethers 6.17.0, with Hardhat ethers 3.1.3, Chai Matchers 2.1.2, +TypeChain Hardhat 9.1.0, helpers 0.7.2, OpenZeppelin Upgrades 2.5.1 and Tenderly +2.1.1. Mocha/Chai and strict TypeScript are retained. Tenderly automatic +verification is explicitly disabled; existing explicit verification calls remain. + +Each package carries four reproducible Yarn patches: + +| Package | Reason | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| hardhat-helpers 0.7.2 | Accept ethers v6 BaseContract typings, preserve the old proxy deployment receipt fields, and select an explicit v4/v5 ProxyAdmin artifact for preparation with the retained upgrade plugin. | +| OpenZeppelin Upgrades 2.5.1 | Add the chain ID to Etherscan v2 verification queries used by hardhat-verify 2.1.3. This retains the v4 shared-admin creation behavior. | +| TypeChain ethers-v6 0.5.1 | Handle a contract function named `target`, which conflicts with the ethers v6 base-contract property. | +| Threshold contracts 1.3.0-dev.14 | Port three deployment API uses: the deployed staking address, JSON interface formatting and ZeroAddress. Solidity and artifacts are unchanged by this patch. | + +The helper's old deploy/OZ peer ranges and OZ 2's verify-v1 peer produce expected +peer warnings. They are not suppressed; the selected patched combinations are +covered by the checks below. Yarn resolutions and devDependency patches do not +propagate automatically into a downstream package installation. Consumers must +adopt the same compatible runtime and upstream fixes before release. + +## Test and build evidence + +- Both full suites pass: 962 Beacon tests and 679 ECDSA tests, with + ECDSA's existing 44 pending tests unchanged. +- Four additional Beacon confirmation tests pass using the local ethers provider: + one confirmation, a mined second confirmation, timeout, and missing transaction. +- Three additional initialization task tests pass: new stake/authorization/operator + setup, a rerun without transactions, and a stake top-up with increased authorization. +- Both strict TypeScript checks, CommonJS export builds and prepack artifact + exports pass. Full lint completes with warnings but no errors. +- WalletRegistry upgrade tests exercise layout rejection, existing proxy upgrades, + shared-admin ownership and authorized versus unauthorized calls. + +The confirmation helper uses `getTransaction(...).wait(...)` because the Hardhat +ethers v6 provider does not implement `waitForTransaction`. Published Beacon +scripts include its compiled `export/utils/wait-for-confirmations.js` dependency. +ECDSA's bundled Beacon scripts are regenerated from the same TypeScript sources, +including the missing-approval-function and already-approved guards. + +ECDSA's Beacon task imports use the same export resolver as deployments. Source +checkouts prefer a sibling Beacon build and otherwise load the committed v6 +task bundle. Packed ECDSA includes that bundle, so its compiled task entrypoints +also work with the pinned v5 Beacon dependency; an adjacent installed package is +not mistaken for a sibling source build. `RANDOM_BEACON_EXPORT_PATH` selects the +task exports too and never falls back if they are missing. + +Six ECDSA task regressions cover staking with distinct beneficiary/authorizer +accounts, direct registration, complete initialization with minimum +authorization and beta membership, idempotent reruns, stake/authorization +increases, and the development account-unlock provider API. The unlock check uses +an in-memory provider with no RPC connection. Before the task import fix, all +five initialization/registration checks failed at the pinned v5 API calls. + +## Production-contract deployment comparison + +Fresh deployments use real contracts and external producer scripts on a +non-forked in-process Hardhat network. The clock starts at 2024-01-01 UTC and +advances one second per transaction, so timestamp immutables in SortitionPools +are comparable. Each capture retains full blocks/receipts, deployment records, +exported artifacts and selected readers/code. The comparator checks the EVM +state root after every block, covering storage and balances beyond the selected +owner/governance readers. + +| Check | Beacon | ECDSA | +| ----------------------------------------------- | ------------- | -------------------------------- | +| Deployments | 16 | 22 | +| Transactions with identical resulting EVM state | 28 | 46 | +| `export.json` bytes | Identical | Identical | +| Addresses, runtime code, proxy slots and owners | Identical | Identical | +| Raw deployment-record bytes | Identical | Hash differences described below | +| Artifact inventory | Same 51 files | Same 52 files | + +Export SHA-256 values: + +```text +Beacon a7fe677b015af93102a99a276263bb1e8cbc84a06055c6dc98a636b681750083 +ECDSA 35e1886a916255779b9a02cda1ee75e84ec1cc6918965347682b8f1f82487333 +``` + +Six ECDSA transactions (blocks 33, 34, 35, 42, 45 and 46) use Hardhat's configured +16,777,216 gas limit through the new ethers signer. The baseline limits were +5,222,326; 443,289; 1,065,225; 15,799,896; 809,383; and 683,960 respectively. Only +the gas-limit field and derived signatures, transaction hashes and block headers +differ. Actual gas used, receipt contents other than hashes, transaction inputs, +fee prices, event data, state roots and ownership all match. The comparator +permits these exact gas changes and translates only their known hash fields; +it rejects other record changes. Raw ECDSA deployment records are consequently +not byte-identical. + +In each package, only the TokenStaking artifact changes: OpenZeppelin's newer +compiler integration adds `storageLayout` to this compiler-override artifact. +The layout matches the actual compiler build-info output. Removing that added +field leaves an identical parsed artifact, including ABI, bytecode, deployed +bytecode and metadata. Every other artifact is byte-identical. The comparison +does not silently waive arbitrary artifact differences. + +## Reproduce + +Install and run `yarn prepack` in both packages at the baseline and candidate. +Use Node 24 and the checked-in lockfiles. From each package directory, capture +into a new directory with the candidate's isolated configuration: + +```sh +COMPAT_DIR=/absolute/path/to/candidate/solidity/scripts/ethers-v6-compatibility +HARDHAT_CONFIG="$COMPAT_DIR/hardhat.config.cjs" \ + USE_EXTERNAL_DEPLOY=true MIGRATION_CAPTURE_DIR=/tmp/new-capture \ + node "$COMPAT_DIR/capture.cjs" +``` + +Leave `TEST_USE_STUBS_BEACON`, `TEST_USE_STUBS_ECDSA`, `FORKING_URL` and +`FORKING_BLOCK` unset. The capture rejects a fork, a public network, test stubs or +an existing destination. Compare matching package captures: + +```sh +node "$COMPAT_DIR/compare.cjs" /tmp/v5-capture /tmp/v6-capture --ethers-v6 +``` + +After both candidate prepack steps, run from `solidity/ecdsa`: + +```sh +node ../scripts/ethers-v6-compatibility/pack-and-capture.cjs \ + /tmp/new-packed-consumer /tmp/v6-ecdsa-capture +``` + +This packs and extracts the actual two npm archives and checks their exported +files, artifact counts and Beacon support module. It reuses the installed ECDSA +consumer's plugins; it does not validate dependency installation from scratch. +It executes both producers' compiled deployment scripts through explicit packed +paths and requires byte-identical state, exports, artifacts and deployment +records versus the ethers v6 source capture, without the v5 gas exceptions. +It also compares all bundled JavaScript with Beacon's compiled source and runs +the six ECDSA task checks through the packed ECDSA entrypoints: first with the +explicit packed v6 Beacon exports, then with the pinned v5 dependency installed +beside ECDSA to exercise its shipped task bundle. +`RANDOM_BEACON_EXPORT_PATH` fails on missing export directories (including +`tasks/`) rather than using sibling or bundled sources. `ECDSA_EXPORT_PATH` is +confined to the capture config. + +For the committed fallback check, temporarily move Beacon's ignored `export/` +directory aside in **both** trees, capture ECDSA, and restore the directories. +Compare those matching v5/v6 fallback captures with `--ethers-v6`. This check +also passes: all 46 transaction state roots and the selected code/state match, +with the same six gas-limit changes and TokenStaking layout addition described +above. The captured `inputs.json` confirms the bundled deploy path was selected. + +The fallback deliberately obtains artifacts from the pinned old Beacon npm +package. Nine Beacon contracts consequently have older compiler metadata than +the sibling build, on both toolchains. Do not compare a fallback capture with a +sibling-build capture and ignore those code differences. The bundled JavaScript +itself must exactly match the newly compiled source. The full ECDSA suite is also +run with the sibling export unavailable. + +## Publication lifecycle + +Both `prepublishOnly` hooks use helpers 0.7.2's `export-deployment-artifacts` +task. They honor npm's `--network` option and default to `hardhat` when it is +omitted. From a fresh copy of either package with dependencies installed: + +```sh +yarn deploy:test --network hardhat --write true +npm publish --dry-run --offline --registry=http://127.0.0.1:1 \ + --access=public --tag=development --network=hardhat +``` + +This exercises `prepublishOnly`, `prepack`, and ECDSA's `prepare` without +publishing a package. The deployment export requires an empty `artifacts/` +directory. Check that the exported records match `deployments/hardhat/` and +appear in npm's package contents. Use separate fresh copies to check the +omitted-network default and `--network=sepolia` with the checked-in Sepolia +deployment snapshots. + +## Limits and release gates + +The publishing jobs in +[`npm-random-beacon.yml`](../../.github/workflows/npm-random-beacon.yml) and +[`npm-ecdsa.yml`](../../.github/workflows/npm-ecdsa.yml) are disabled with +`if: ${{ false }}`. This blocks both automatic pushes to `main` and manual +dispatches on any ref, protecting the existing `development` and `latest` npm +tags. Re-enable the jobs in a coordinated release change only after the consumer +runtime migration, upstream fixes, release channel agreement, and ECDSA's pin to +a compatible published Beacon version are ready and the actual packed producers +pass the full ECDSA and tbtc-v2 consumer checks. Local packing and the offline +publication lifecycle checks above remain available while the jobs are disabled. + +These checks do not deploy to mainnet/Sepolia, contact explorer verification +services, run the full tbtc-v2 consumer, or authorize package publication. The +manual WalletRegistry V2 script is ported to v6 (and now saves a parsed ABI array) +but its complete operator workflow is not exercised here. The deputy-admin +script remains disabled. The separate Rocketh experiment covers a representative +proxy path, not all of these scripts. + +Do not publish these executable exports into an ethers v5 consumer line. Obtain +upstream helper/Threshold fixes or carry the reviewed patches in each consumer, +publish Beacon on the agreed release channel, pin ECDSA to that new release, then +validate the actual tbtc-v2 consumer. See the [migration decision and remaining +gates](hardhat-3-migration.md). Keep #4295 open. diff --git a/solidity/docs/hardhat-3-migration.md b/solidity/docs/hardhat-3-migration.md index 421ebcab40..5b620e42d4 100644 --- a/solidity/docs/hardhat-3-migration.md +++ b/solidity/docs/hardhat-3-migration.md @@ -1,94 +1,83 @@ # Hardhat 3 and deployment export migration -Status: migration preparation, 2026-09-07. Track the runtime migration in -[#4209](https://github.com/threshold-network/keep-core/issues/4209), the remaining -plugin namespace changes in -[#4213](https://github.com/threshold-network/keep-core/issues/4213), and the +Status: ethers v6 preparation on Hardhat 2, 2026-09-08. Track the runtime migration +in [#4209](https://github.com/threshold-network/keep-core/issues/4209), plugin +changes in [#4213](https://github.com/threshold-network/keep-core/issues/4213), and cross-package deployment conversion in [#4295](https://github.com/threshold-network/keep-core/issues/4295). -## Completed preparation +## Decision -Both packages can use Hardhat Chai Matchers on ethers v5. Random Beacon now uses -Hardhat Network Helpers for its snapshot fixtures and `ethers.provider` for -provider access, removing its Waffle dependencies. Existing deployment fixtures -still use hardhat-deploy v1 APIs. Verification uses -`@nomicfoundation/hardhat-verify` in both packages. +Target Hardhat 3, hardhat-deploy v2 and Rocketh, with viem in the deployment layer +and ethers v6 plus Mocha/Chai for tests. Keep Hardhat 2 and maintained +hardhat-deploy v1 available while consumers migrate. Prefer separate, versioned +release lines for the CommonJS/v1 and ESM/Rocketh executable APIs. Same-package +dual publication is possible, but adds a second runtime contract to every +producer and remains an alternative requiring consumer agreement. -The preceding stack updates TypeChain, enables strict TypeScript, raises the -published JavaScript target to ES2020 while retaining CommonJS, updates runtime -types, and modernizes lint/format tooling. These changes do not convert deployment -scripts to Rocketh. The independent maintained-v1 update is -[#4294](https://github.com/threshold-network/keep-core/pull/4294). - -## Public deployment API - -The packages execute upstream deployment scripts from published npm packages: +The dependency order is: ```text @threshold-network/solidity-contracts -> random-beacon -> ecdsa -> tbtc-v2 ``` -`hardhat.config.ts` in each package loads -`@threshold-network/solidity-contracts/export/deploy`. ECDSA additionally loads -Random Beacon's `export/deploy` through `resolveRandomBeaconExport`. Downstream -tbtc-v2 executes ECDSA's published exports. Therefore the module format and script -entry points in `export/deploy` are a public API, alongside `export/artifacts`, -`export.json`, and the committed `deployments/{mainnet,sepolia}` records. - -Raising the ES target does not change this CommonJS API. The ES2020 migration was -checked against ES5 using fresh local deployments: the exported JSON was identical -for all 16 beacon and 22 ECDSA contracts. A switch to ESM/Rocketh needs a separate -consumer compatibility check. - -## Proposed direction and remaining blockers - -Use ethers v6 for tests with viem confined to the Rocketh deployment layer. This -matches the direction recorded in +Consumers execute the producers' `export/deploy` scripts. Module format, runtime +plugins and imported support files are therefore public APIs. Treat them +separately from the data APIs: `export/artifacts`, `export.json`, and committed +network deployment records. CommonJS alone does not make an ethers v6 script +compatible with an ethers v5 consumer. + +## Preparation in this stack + +Both packages use ethers v6, its Hardhat Chai Matchers integration and TypeChain +generator, while retaining Hardhat 2.29.0, maintained hardhat-deploy 1.0.4 and +ES2020/CommonJS exports. Waffle is removed. Strict TypeScript remains enabled. +Tests, tasks, deployment scripts and mock helpers use bigint and ethers v6 APIs. + +The helper moves to 0.7.2, which already uses ethers v6. Its declared deployment +and upgrade peers still need compatibility patches: this stack retains +OpenZeppelin Upgrades 2.5.1 and the shared OpenZeppelin v4 ProxyAdmin behavior. +Other patches preserve proxy receipt fields, support the verification plugin's +Etherscan v2 API, handle a TypeChain reserved name and adapt the three ethers v5 +API uses in the pinned Threshold deployment export. See the +[checks and patch inventory](ethers-v6-compatibility.md). + +ECDSA pins the existing Beacon dependency to `2.1.0-dev.18`. Until coordinated +publication supplies an ethers v6 Beacon package, ECDSA's source checkout uses +its sibling or refreshed bundled deployment scripts and tasks. Packed ECDSA +exports carry the executable bundle too. The explicit +`RANDOM_BEACON_EXPORT_PATH` override allows actual tarball checks without those +fallbacks. The pin is a reproducibility measure, not a claim that the old npm +scripts gained ethers v6 compatibility. + +## Remaining gates + +| Gate | Required work | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Release contract | Agree new major versions/channels and the maintenance period for old consumers. Publish upstream contracts, Beacon, ECDSA, then tbtc-v2. Update ECDSA to the newly published Beacon version before releasing executable ethers v6 exports. | +| Hardhat 3 test runtime | Move to compatible Hardhat 3 ethers/Mocha/Chai plugins after this ethers v6 preparation. Inventory each remaining plugin, task and configuration hook. | +| Shared helpers | Port or replace the used Hardhat 2 helper APIs. Version 0.7.2 is an ethers v6 preparation path, not a Hardhat 3 implementation. Move temporary patches upstream or explicitly carry them in each consumer. | +| Producer scripts | Convert the Threshold, Beacon and ECDSA deployment scripts to the agreed ESM/Rocketh API. Convert fixture loading, named-account resolution, tags and dependency ordering together. | +| Data exports | Provide a deliberately compatible legacy exporter. Compare actual production-contract output, receipts, start blocks, ABIs, libraries, initialization and artifacts; native Rocketh JSON is a different schema. | +| Proxies and upgrades | Preserve storage validation, manifests, existing-proxy import, shared-admin ownership and upgrade authorization. Account explicitly for the disabled deputy-admin script and manual V2 upgrade path. | +| Consumers | Run real packed producers in ECDSA and tbtc-v2 with sibling/bundled fallbacks disabled. Run both full suites and fresh integrated deployments. Test the old release line until the last consumer migrates. | + +The package versions inspected for the feasibility work were +[hardhat-deploy 2.0.26](https://registry.npmjs.org/hardhat-deploy/2.0.26), +[Rocketh node 0.21.0](https://registry.npmjs.org/@rocketh%2fnode/0.21.0), and +[OpenZeppelin Hardhat Upgrades 4.1.0](https://registry.npmjs.org/@openzeppelin%2fhardhat-upgrades/4.1.0). +The published deploy-v2 CommonJS entry throws a migration error; it is not a +working v1 adapter. Rocketh node supports multiple script directories, giving a +mechanism for external producer discovery. OpenZeppelin supplies a Hardhat 3 +plugin, so plugin absence is no longer a blocker; compatibility with this +repository's complete proxy workflow still needs proof. + +The isolated feasibility experiment validates a representative packed producer, +legacy exporter and explicit OpenZeppelin v4 proxy/admin flow. That evidence +supports proceeding with staged implementation; it does not establish the full +cross-repository release gate. Coordinate proxy defaults with +[tbtc-v2 #1130](https://github.com/threshold-network/tbtc-v2/issues/1130) and the +client-library direction with [tbtc-v2 #1128](https://github.com/threshold-network/tbtc-v2/issues/1128). -Prefer dual publication during the transition: retain the current CommonJS -`export/deploy` entry point and introduce a separate, explicitly versioned ESM -entry point. These are implementation proposals; the export path, shared source -strategy, and release sequence still need agreement with downstream maintainers. -Do not replace the existing export in place before that agreement. - -The following gates remain: - -| Gate | Evidence and required next step | -| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| ethers v6 | Both packages still use ethers v5 and `@nomiclabs/hardhat-ethers` 2.x. Port BigNumber arithmetic, provider/contract APIs, TypeChain target, and tests before replacing this plugin. | -| Chai / Mocha / Hardhat | Migrate together to the compatible Hardhat 3 Mocha/ethers toolchain after ethers v6. The current Chai 4/Mocha 10 type declarations intentionally match the Hardhat 2 runtime. | -| hardhat-deploy v2 | Published `hardhat-deploy@2.0.26` requires Hardhat `^3.6.0`, Rocketh `^0.21.0`, and `@rocketh/node ^0.21.0`. It is a deployment API conversion, not a drop-in version bump. | -| Shared helpers | The installed `@keep-network/hardhat-helpers@0.6.0-pre.15` peers with hardhat-deploy `~0.11.11`. The published `0.7.2` line still peers with Hardhat `^2.19.4` and deploy `^0.11.45`; it does not provide a Hardhat 3 migration path. Port or replace the used helper APIs first. | -| Other plugins | Beacon's installed OpenZeppelin Upgrades 1.20.0, Tenderly 1.0.12, and TypeChain Hardhat 7.0.0 plugins all declare Hardhat 2 peers. Inventory both packages' integrations and select compatible versions or replacements before the cutover. | -| Upstream deployment scripts | Both packages consume `@threshold-network/solidity-contracts@1.3.0-dev.14`. Its current export supplies v1 scripts. Obtain compatible v2 exports before converting dependent deployment paths. | -| Cross-package script discovery | The v2 migration guide does not document a replacement for `external.contracts[].deploy`. Establish and test how one package executes another package's scripts before selecting the new export layout. | -| Artifact/export compatibility | `@rocketh/export` exists, but equivalence with the current `--export export.json` and `hardhat export-artifacts` output has not been established. Compare actual output and account for every consumer before changing it. | - -The v2 package includes a CommonJS compatibility entry, but that does not make the -Rocketh deployment API or the existing v1 scripts interchangeable. The upstream -[migration guide](https://github.com/wighawag/rocketh/blob/main/hardhat-deploy/documentation/how-to/migration-from-v1/index.md) -describes ESM scripts, Rocketh configuration and extensions, and replacement -fixture loaders. Version evidence is available in the published metadata for -[hardhat-deploy 2.0.26](https://registry.npmjs.org/hardhat-deploy/2.0.26) and -[hardhat-helpers 0.7.2](https://registry.npmjs.org/@keep-network%2fhardhat-helpers/0.7.2). - -## Cutover acceptance checks - -1. Agree and test the cross-package ESM entry point and dual-publishing strategy - with the upstream contracts package and tbtc-v2. Keep the current CJS exports - available until the last v1 consumer migrates. -2. Land the ethers v6 and helper migrations with full test coverage, then introduce - the compatible Chai/Mocha/Hardhat 3 and Rocketh toolchain together. -3. Convert and publish upstream contracts first, then Random Beacon's 9 deploy - scripts, then ECDSA's 22 deploy scripts. Convert the deployment fixture loaders - and external-script integration alongside each package's scripts. -4. Run both full suites and fresh local deployments that exercise the external - scripts. Compare addresses, ABIs, start blocks, exported artifacts, and committed - network deployment records against the v1 baseline; review and coordinate every - intentional format difference. -5. Validate the published package tarballs in ECDSA and tbtc-v2, including the old - CJS consumer path and new ESM path during dual publication. Retire the CJS path - only in an agreed breaking release. -Keep #4209, #4213, and #4295 open until their respective migrations are complete. +Keep #4209, #4213 and #4295 open until their respective migrations are complete. diff --git a/solidity/ecdsa/.dockerignore b/solidity/ecdsa/.dockerignore index 17165d83c9..1e58a46276 100644 --- a/solidity/ecdsa/.dockerignore +++ b/solidity/ecdsa/.dockerignore @@ -2,6 +2,12 @@ .* !.yarnrc.yml +# Include local dependency patches, but exclude Yarn caches and install state. +!.yarn +.yarn/** +!.yarn/patches +!.yarn/patches/** + # Documentation docs/ diff --git a/solidity/ecdsa/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch b/solidity/ecdsa/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch new file mode 100644 index 0000000000..3acb0a3521 --- /dev/null +++ b/solidity/ecdsa/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch @@ -0,0 +1,520 @@ +diff --git a/dist/contracts.d.ts b/dist/contracts.d.ts +index e67607c..de33123 100644 +--- a/dist/contracts.d.ts ++++ b/dist/contracts.d.ts +@@ -1,7 +1,7 @@ +-import type { Contract } from "ethers"; ++import type { BaseContract, Contract } from "ethers"; + import type { HardhatRuntimeEnvironment } from "hardhat/types"; + export interface HardhatContractsHelpers { +- getContract(deploymentName: string): Promise; ++ getContract(deploymentName: string): Promise; + } + export default function (hre: HardhatRuntimeEnvironment): HardhatContractsHelpers; + //# sourceMappingURL=contracts.d.ts.map +\ No newline at end of file +diff --git a/dist/upgrades.d.ts b/dist/upgrades.d.ts +index 2eb5874..a07f2ae 100644 +--- a/dist/upgrades.d.ts ++++ b/dist/upgrades.d.ts +@@ -1,24 +1,24 @@ + import "@openzeppelin/hardhat-upgrades"; +-import type { Contract, ContractTransaction } from "ethers"; ++import type { BaseContract, Contract, ContractTransaction } from "ethers"; + import type { FactoryOptions, HardhatRuntimeEnvironment } from "hardhat/types"; + import type { Deployment } from "hardhat-deploy/dist/types"; + import type { DeployProxyOptions, UpgradeProxyOptions } from "@openzeppelin/hardhat-upgrades/src/utils/options"; + import { Libraries } from "hardhat-deploy/types"; + export interface HardhatUpgradesHelpers { +- deployProxy(name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; +- upgradeProxy(currentContractName: string, newContractName: string, opts?: UpgradesUpgradeOptions): Promise<[T, Deployment]>; ++ deployProxy(name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; ++ upgradeProxy(currentContractName: string, newContractName: string, opts?: UpgradesUpgradeOptions): Promise<[T, Deployment]>; + prepareProxyUpgrade(proxyDeploymentName: string, newContractName: string, opts?: UpgradesPrepareProxyUpgradeOptions): Promise<{ + newImplementationAddress: string; + preparedTransaction: ContractTransaction; + }>; + } + type CustomFactoryOptions = FactoryOptions & { + libraries?: Libraries; + }; + export interface UpgradesDeployOptions { + contractName?: string; + initializerArgs?: unknown[]; + factoryOpts?: CustomFactoryOptions; + proxyOpts?: DeployProxyOptions; + } + export interface UpgradesUpgradeOptions { +@@ -27,19 +27,19 @@ export interface UpgradesUpgradeOptions { + factoryOpts?: CustomFactoryOptions; + proxyOpts?: UpgradeProxyOptions; + } + export interface UpgradesPrepareProxyUpgradeOptions { + contractName?: string; + factoryOpts?: CustomFactoryOptions; + callData?: string; + } + /** + * Deploys contract as a TransparentProxy. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} name Contract Name + * @param {UpgradesDeployOptions} opts + */ +-export declare function deployProxy(hre: HardhatRuntimeEnvironment, name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; ++export declare function deployProxy(hre: HardhatRuntimeEnvironment, name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; + export default function (hre: HardhatRuntimeEnvironment): HardhatUpgradesHelpers; + export {}; + //# sourceMappingURL=upgrades.d.ts.map +\ No newline at end of file +diff --git a/dist/upgrades.js b/dist/upgrades.js +index 6367def..cfb0e32 100644 +--- a/dist/upgrades.js ++++ b/dist/upgrades.js +@@ -1,54 +1,85 @@ + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.deployProxy = void 0; + require("@openzeppelin/hardhat-upgrades"); +-const utils_1 = require("@openzeppelin/hardhat-upgrades/dist/utils"); ++const ProxyAdminV4 = require("@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json"); ++const ProxyAdminV5 = require("@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts-v5/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json"); + const upgrades_core_1 = require("@openzeppelin/upgrades-core"); + /** + * Deploys contract as a TransparentProxy. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} name Contract Name + * @param {UpgradesDeployOptions} opts + */ ++// Preserve the receipt metadata published by hardhat-helpers 0.6. ++function toDeploymentReceipt(receipt) { ++ return { ++ to: receipt.to, ++ from: receipt.from, ++ contractAddress: receipt.contractAddress, ++ transactionIndex: receipt.index, ++ gasUsed: receipt.gasUsed.toString(), ++ logsBloom: receipt.logsBloom, ++ blockHash: receipt.blockHash, ++ transactionHash: receipt.hash, ++ logs: receipt.logs.map((log) => ({ ++ transactionIndex: log.transactionIndex, ++ blockNumber: log.blockNumber, ++ transactionHash: log.transactionHash, ++ address: log.address, ++ topics: [...log.topics], ++ data: log.data, ++ logIndex: log.index, ++ blockHash: log.blockHash, ++ // Mined receipt logs omit the removed field in the existing export format. ++ removed: undefined, ++ })), ++ blockNumber: receipt.blockNumber, ++ cumulativeGasUsed: receipt.cumulativeGasUsed.toString(), ++ status: receipt.status, ++ byzantium: receipt.status !== null, ++ } ++} + async function deployProxy(hre, name, opts) { + const { ethers, upgrades, deployments, artifacts } = hre; + const { log } = deployments; + const existingDeployment = await deployments.getOrNull(name); + if (existingDeployment) { + throw new Error(`${name} was already deployed at ${existingDeployment.address}`); + } + const contractFactory = await ethers.getContractFactory(opts?.contractName || name, opts?.factoryOpts); + const contractInstance = (await upgrades.deployProxy(contractFactory, opts?.initializerArgs, opts?.proxyOpts)); + const deploymentTransaction = contractInstance.deploymentTransaction(); + // Let the transaction propagate across the ethereum nodes. This is mostly to + // wait for all Alchemy nodes to catch up their state. + const transactionReceipt = await deploymentTransaction?.wait(1); + const contractAddress = await contractInstance.getAddress(); + const transactionHash = deploymentTransaction?.hash; + log(`Deployed ${name} as ${opts?.proxyOpts?.kind || "transparent"} proxy at ${contractAddress} (tx: ${transactionHash})`); + const artifact = artifacts.readArtifactSync(opts?.contractName || name); + const implementation = await upgrades.erc1967.getImplementationAddress(contractAddress); + if (!transactionReceipt || !transactionHash) { + throw new Error(`Could not find transaction receipt for transaction hash: ${transactionHash}`); + } + const deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + }; + await deployments.save(name, deployment); + return [contractInstance, deployment]; + } + exports.deployProxy = deployProxy; + /** + * Upgrades previously deployed contract. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} proxyDeploymentName Name of the proxy deployment that will be + * upgraded. + * @param {string} newContractName Name of the new implementation contract. +@@ -72,30 +103,31 @@ async function upgradeProxy(hre, proxyDeploymentName, newContractName, opts) { + const contractAddress = await newContractInstance.getAddress(); + const transactionHash = deploymentTransaction?.hash; + log(`Upgraded ${proxyDeploymentName} proxy contract (address: ${proxyDeployment.address}) ` + + `in tx: ${transactionHash}`); + const artifact = artifacts.readArtifactSync(opts?.contractName || newContractName); + const implementation = await upgrades.erc1967.getImplementationAddress(contractAddress); + log(`New ${proxyDeploymentName} proxy contract implementation address is: ${implementation}`); + if (!transactionReceipt || !transactionHash) { + throw new Error(`Could not find transaction receipt for transaction hash: ${transactionHash}`); + } + const deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + }; + await deployments.save(proxyDeploymentName, deployment); + return [newContractInstance, deployment]; + } + /** + * Prepare upgrade of deployed contract. + * It deploys new implementation contract and prepares transaction to upgrade + * the proxy contract to the new implementation thorough a Proxy Admin instance. + * The transaction has to be executed by the owner of the Proxy Admin. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} proxyDeploymentName Name of the proxy deployment that will be +@@ -108,40 +140,40 @@ async function prepareProxyUpgrade(hre, proxyDeploymentName, newContractName, op + const signer = await ethers.provider.getSigner(); + const { log } = deployments; + const proxyDeployment = await deployments.get(proxyDeploymentName); + const implementationContractFactory = await ethers.getContractFactory(opts?.contractName || newContractName, opts?.factoryOpts); + const newImplementationAddress = (await upgrades.prepareUpgrade(proxyDeployment.address, implementationContractFactory, { + kind: "transparent", + getTxResponse: false, + })); + log(`new implementation contract deployed at: ${newImplementationAddress}`); + const proxyAdminAddress = await hre.upgrades.erc1967.getAdminAddress(proxyDeployment.address); + let proxyAdmin; + let upgradeTxData; + const proxyInterfaceVersion = await (0, upgrades_core_1.getUpgradeInterfaceVersion)(hre.network.provider, proxyAdminAddress); + switch (proxyInterfaceVersion) { + case "5.0.0": { +- proxyAdmin = await (0, utils_1.attachProxyAdminV5)(hre, proxyAdminAddress, signer); ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV5.abi, proxyAdminAddress, signer); + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgradeAndCall", [ + proxyDeployment.address, + newImplementationAddress, + opts?.callData ?? "0x", + ]); + break; + } + default: { +- proxyAdmin = await (0, utils_1.attachProxyAdminV4)(hre, proxyAdminAddress, signer); ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV4.abi, proxyAdminAddress, signer); + if (opts?.callData) { + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgradeAndCall", [proxyDeployment.address, newImplementationAddress, opts?.callData]); + } + else { + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgrade", [ + proxyDeployment.address, + newImplementationAddress, + ]); + } + } + } + const preparedTransaction = { + from: (await proxyAdmin.owner()), + to: proxyAdminAddress, + data: upgradeTxData, +diff --git a/src/contracts.ts b/src/contracts.ts +index dc82311..b8f4d3a 100644 +--- a/src/contracts.ts ++++ b/src/contracts.ts +@@ -1,23 +1,23 @@ +-import type { Contract } from "ethers" ++import type { BaseContract, Contract } from "ethers" + import type { HardhatRuntimeEnvironment } from "hardhat/types" + + export interface HardhatContractsHelpers { +- getContract(deploymentName: string): Promise ++ getContract(deploymentName: string): Promise + } + +-async function getContract( ++async function getContract( + hre: HardhatRuntimeEnvironment, + deploymentName: string + ): Promise { + const deployment = await hre.deployments.get(deploymentName) + + return (await hre.ethers.getContractAt( + deployment.abi, + deployment.address + )) as T + } + + export default function ( + hre: HardhatRuntimeEnvironment + ): HardhatContractsHelpers { + return { +diff --git a/src/upgrades.ts b/src/upgrades.ts +index 22edb53..c7abdf3 100644 +--- a/src/upgrades.ts ++++ b/src/upgrades.ts +@@ -1,47 +1,77 @@ + import "@openzeppelin/hardhat-upgrades" + + import type { ++ BaseContract, + Contract, + ContractFactory, + ContractTransaction, + ContractTransactionResponse, ++ TransactionReceipt, + } from "ethers" + import type { + Artifact, + FactoryOptions, + HardhatRuntimeEnvironment, + } from "hardhat/types" +-import type { Deployment } from "hardhat-deploy/dist/types" ++import type { Deployment, Receipt } from "hardhat-deploy/dist/types" + import type { + DeployProxyOptions, + UpgradeProxyOptions, + } from "@openzeppelin/hardhat-upgrades/src/utils/options" + import { Libraries } from "hardhat-deploy/types" +-import { +- attachProxyAdminV4, +- attachProxyAdminV5, +-} from "@openzeppelin/hardhat-upgrades/dist/utils" ++import ProxyAdminV4 from "@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json" ++import ProxyAdminV5 from "@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts-v5/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json" + + import { getUpgradeInterfaceVersion } from "@openzeppelin/upgrades-core" + ++// Preserve the receipt metadata published by hardhat-helpers 0.6. ++function toDeploymentReceipt(receipt: TransactionReceipt): Receipt { ++ return { ++ to: receipt.to, ++ from: receipt.from, ++ contractAddress: receipt.contractAddress, ++ transactionIndex: receipt.index, ++ gasUsed: receipt.gasUsed.toString(), ++ logsBloom: receipt.logsBloom, ++ blockHash: receipt.blockHash, ++ transactionHash: receipt.hash, ++ logs: receipt.logs.map((log) => ({ ++ transactionIndex: log.transactionIndex, ++ blockNumber: log.blockNumber, ++ transactionHash: log.transactionHash, ++ address: log.address, ++ topics: [...log.topics], ++ data: log.data, ++ logIndex: log.index, ++ blockHash: log.blockHash, ++ // Mined receipt logs omit the removed field in the existing export format. ++ removed: undefined, ++ })), ++ blockNumber: receipt.blockNumber, ++ cumulativeGasUsed: receipt.cumulativeGasUsed.toString(), ++ status: receipt.status, ++ byzantium: receipt.status !== null, ++ } ++} ++ + export interface HardhatUpgradesHelpers { +- deployProxy( ++ deployProxy( + name: string, + opts?: UpgradesDeployOptions + ): Promise<[T, Deployment]> +- upgradeProxy( ++ upgradeProxy( + currentContractName: string, + newContractName: string, + opts?: UpgradesUpgradeOptions + ): Promise<[T, Deployment]> + prepareProxyUpgrade( + proxyDeploymentName: string, + newContractName: string, + opts?: UpgradesPrepareProxyUpgradeOptions + ): Promise<{ + newImplementationAddress: string + preparedTransaction: ContractTransaction + }> + } + + type CustomFactoryOptions = FactoryOptions & { +@@ -63,31 +93,31 @@ export interface UpgradesUpgradeOptions { + } + + export interface UpgradesPrepareProxyUpgradeOptions { + contractName?: string + factoryOpts?: CustomFactoryOptions + callData?: string + } + + /** + * Deploys contract as a TransparentProxy. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} name Contract Name + * @param {UpgradesDeployOptions} opts + */ +-export async function deployProxy( ++export async function deployProxy( + hre: HardhatRuntimeEnvironment, + name: string, + opts?: UpgradesDeployOptions + ): Promise<[T, Deployment]> { + const { ethers, upgrades, deployments, artifacts } = hre + const { log } = deployments + + const existingDeployment = await deployments.getOrNull(name) + if (existingDeployment) { + throw new Error( + `${name} was already deployed at ${existingDeployment.address}` + ) + } + + const contractFactory: ContractFactory = await ethers.getContractFactory( +@@ -121,50 +151,51 @@ export async function deployProxy( + const implementation = await upgrades.erc1967.getImplementationAddress( + contractAddress + ) + + if (!transactionReceipt || !transactionHash) { + throw new Error( + `Could not find transaction receipt for transaction hash: ${transactionHash}` + ) + } + + const deployment: Deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + } + + await deployments.save(name, deployment) + + return [contractInstance, deployment] + } + + /** + * Upgrades previously deployed contract. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} proxyDeploymentName Name of the proxy deployment that will be + * upgraded. + * @param {string} newContractName Name of the new implementation contract. + * @param {UpgradesDeployOptions} opts + */ +-async function upgradeProxy( ++async function upgradeProxy( + hre: HardhatRuntimeEnvironment, + proxyDeploymentName: string, + newContractName: string, + opts?: UpgradesUpgradeOptions + ): Promise<[T, Deployment]> { + const { ethers, upgrades, deployments, artifacts } = hre + const { log } = deployments + + const proxyDeployment: Deployment = await deployments.get(proxyDeploymentName) + + const newContract: ContractFactory = await ethers.getContractFactory( + opts?.contractName || newContractName, + opts?.factoryOpts + ) + +@@ -205,30 +236,31 @@ async function upgradeProxy( + log( + `New ${proxyDeploymentName} proxy contract implementation address is: ${implementation}` + ) + + if (!transactionReceipt || !transactionHash) { + throw new Error( + `Could not find transaction receipt for transaction hash: ${transactionHash}` + ) + } + + const deployment: Deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + } + + await deployments.save(proxyDeploymentName, deployment) + + return [newContractInstance, deployment] + } + + /** + * Prepare upgrade of deployed contract. + * It deploys new implementation contract and prepares transaction to upgrade + * the proxy contract to the new implementation thorough a Proxy Admin instance. + * The transaction has to be executed by the owner of the Proxy Admin. +@@ -273,44 +305,44 @@ async function prepareProxyUpgrade( + + const proxyAdminAddress = await hre.upgrades.erc1967.getAdminAddress( + proxyDeployment.address + ) + + let proxyAdmin: Contract + let upgradeTxData: string + + const proxyInterfaceVersion = await getUpgradeInterfaceVersion( + hre.network.provider, + proxyAdminAddress + ) + + switch (proxyInterfaceVersion) { + case "5.0.0": { +- proxyAdmin = await attachProxyAdminV5(hre, proxyAdminAddress, signer) ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV5.abi, proxyAdminAddress, signer) + + upgradeTxData = proxyAdmin.interface.encodeFunctionData( + "upgradeAndCall", + [ + proxyDeployment.address, + newImplementationAddress, + opts?.callData ?? "0x", + ] + ) + break + } + default: { +- proxyAdmin = await attachProxyAdminV4(hre, proxyAdminAddress, signer) ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV4.abi, proxyAdminAddress, signer) + + if (opts?.callData) { + upgradeTxData = proxyAdmin.interface.encodeFunctionData( + "upgradeAndCall", + [proxyDeployment.address, newImplementationAddress, opts?.callData] + ) + } else { + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgrade", [ + proxyDeployment.address, + newImplementationAddress, + ]) + } + } + } + diff --git a/solidity/ecdsa/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch b/solidity/ecdsa/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch new file mode 100644 index 0000000000..06d2c0a560 --- /dev/null +++ b/solidity/ecdsa/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch @@ -0,0 +1,85 @@ +diff --git a/src/utils/etherscan-api.ts b/src/utils/etherscan-api.ts +--- a/src/utils/etherscan-api.ts ++++ b/src/utils/etherscan-api.ts +@@ -2,36 +2,39 @@ + import { HardhatRuntimeEnvironment } from 'hardhat/types'; + + import { request } from 'undici'; + + import debug from './debug'; + import { Etherscan } from '@nomicfoundation/hardhat-verify/etherscan'; + + /** + * Call the configured Etherscan API with the given parameters. + * + * @param etherscan Etherscan instance + * @param params The API parameters to call with + * @returns The Etherscan API response + */ + export async function callEtherscanApi(etherscan: Etherscan, params: any): Promise { + const parameters = new URLSearchParams({ ...params, apikey: etherscan.apiKey }); ++ if (etherscan.chainId !== undefined) { ++ parameters.set('chainid', etherscan.chainId); ++ } + + const response = await request(etherscan.apiUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: parameters.toString(), + }); + + if (!(response.statusCode >= 200 && response.statusCode <= 299)) { + const responseBodyText = await response.body.text(); + throw new UpgradesError( + `Etherscan API call failed with status ${response.statusCode}, response: ${responseBodyText}`, + ); + } + + const responseBodyJson = await response.body.json(); + debug('Etherscan response', JSON.stringify(responseBodyJson)); + + return responseBodyJson; + } + +diff --git a/dist/utils/etherscan-api.js b/dist/utils/etherscan-api.js +--- a/dist/utils/etherscan-api.js ++++ b/dist/utils/etherscan-api.js +@@ -4,35 +4,38 @@ + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.verifyAndGetStatus = exports.RESPONSE_OK = exports.getEtherscanInstance = exports.callEtherscanApi = void 0; + const upgrades_core_1 = require("@openzeppelin/upgrades-core"); + const undici_1 = require("undici"); + const debug_1 = __importDefault(require("./debug")); + const etherscan_1 = require("@nomicfoundation/hardhat-verify/etherscan"); + /** + * Call the configured Etherscan API with the given parameters. + * + * @param etherscan Etherscan instance + * @param params The API parameters to call with + * @returns The Etherscan API response + */ + async function callEtherscanApi(etherscan, params) { + const parameters = new URLSearchParams({ ...params, apikey: etherscan.apiKey }); ++ if (etherscan.chainId !== undefined) { ++ parameters.set('chainid', etherscan.chainId); ++ } + const response = await (0, undici_1.request)(etherscan.apiUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: parameters.toString(), + }); + if (!(response.statusCode >= 200 && response.statusCode <= 299)) { + const responseBodyText = await response.body.text(); + throw new upgrades_core_1.UpgradesError(`Etherscan API call failed with status ${response.statusCode}, response: ${responseBodyText}`); + } + const responseBodyJson = await response.body.json(); + (0, debug_1.default)('Etherscan response', JSON.stringify(responseBodyJson)); + return responseBodyJson; + } + exports.callEtherscanApi = callEtherscanApi; + /** + * Gets an Etherscan instance based on Hardhat config. + * Throws an error if Etherscan API key is not present in config. + */ + async function getEtherscanInstance(hre) { diff --git a/solidity/ecdsa/.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch b/solidity/ecdsa/.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch new file mode 100644 index 0000000000..3e3b7c21ed --- /dev/null +++ b/solidity/ecdsa/.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch @@ -0,0 +1,28 @@ +diff --git a/export/deploy/07_deploy_token_staking.js b/export/deploy/07_deploy_token_staking.js +--- a/export/deploy/07_deploy_token_staking.js ++++ b/export/deploy/07_deploy_token_staking.js +@@ -62,10 +62,10 @@ + })]; + case 4: + tokenStaking = _a.sent(); +- tokenStakingAddress = tokenStaking.address; ++ tokenStakingAddress = tokenStaking.target; + log("Deployed TokenStaking with TransparentProxy at ".concat(tokenStakingAddress)); + implementationInterface = tokenStaking.interface; +- jsonAbi = implementationInterface.format(hardhat_1.ethers.utils.FormatTypes.json); ++ jsonAbi = implementationInterface.formatJson(); + tokenStakingDeployment = { + address: tokenStakingAddress, + abi: JSON.parse(jsonAbi), +diff --git a/export/deploy/30_deploy_tokenholder_timelock.js b/export/deploy/30_deploy_tokenholder_timelock.js +--- a/export/deploy/30_deploy_tokenholder_timelock.js ++++ b/export/deploy/30_deploy_tokenholder_timelock.js +@@ -51,7 +51,7 @@ + case 1: + deployer = (_a.sent()).deployer; + proposers = []; +- executors = [ethers_1.ethers.constants.AddressZero]; ++ executors = [ethers_1.ethers.ZeroAddress]; + minDelay = 172800 // 2 days in seconds (2 * 24 * 60 * 60) + ; + return [4 /*yield*/, deployments.deploy("TokenholderTimelock", { diff --git a/solidity/ecdsa/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch b/solidity/ecdsa/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch new file mode 100644 index 0000000000..85cccd3381 --- /dev/null +++ b/solidity/ecdsa/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch @@ -0,0 +1,13 @@ +diff --git a/dist/codegen/reserved-keywords.js b/dist/codegen/reserved-keywords.js +index f5a47b105a31e5ae3a6e40da476a37f748d962d9..f05f5ec9582c56a264fe6a61f7a098e2008047a3 100644 +--- a/dist/codegen/reserved-keywords.js ++++ b/dist/codegen/reserved-keywords.js +@@ -1,7 +1,7 @@ + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.reservedKeywordsLabels = exports.reservedKeywords = void 0; +-exports.reservedKeywords = new Set(['signer', 'provider', 'deployTransaction', 'deployed', 'fallback', 'connect']); ++exports.reservedKeywords = new Set(['signer', 'provider', 'deployTransaction', 'deployed', 'fallback', 'connect', 'target']); + exports.reservedKeywordsLabels = new Set([ + 'class', + 'function', diff --git a/solidity/ecdsa/Dockerfile b/solidity/ecdsa/Dockerfile index 93f6faae1b..2e55e8d2ca 100644 --- a/solidity/ecdsa/Dockerfile +++ b/solidity/ecdsa/Dockerfile @@ -16,7 +16,10 @@ ENV COREPACK_DEFAULT_TO_LATEST=0 # node: it writes Corepack's per-user cache under $HOME. `chown` targets only # $WORK_DIR here because `yarn install` creates node_modules inside it; # dependency/source ownership is set later via `COPY --chown`. -RUN corepack enable && mkdir -p $WORK_DIR && chown node:node $WORK_DIR +# Native dependencies need a compiler while Yarn packs Git dependencies; the +# build tools are installed/removed as root since `apk` requires root. +RUN apk add --no-cache --virtual .build-deps python3 make g++ && \ + corepack enable && mkdir -p $WORK_DIR && chown node:node $WORK_DIR WORKDIR $WORK_DIR USER node @@ -24,8 +27,13 @@ USER node RUN git config --global url."https://".insteadOf git:// COPY --chown=node:node package*.json yarn.lock .yarnrc.yml ./ +COPY --chown=node:node .yarn/patches/ ./.yarn/patches/ RUN corepack prepare yarn@4.12.0 --activate && yarn install --immutable +USER root +RUN apk del .build-deps +USER node + COPY --chown=node:node . ./ ENTRYPOINT ["npx", "hardhat"] diff --git a/solidity/ecdsa/README.adoc b/solidity/ecdsa/README.adoc index 1e185f1a01..f97da3e695 100644 --- a/solidity/ecdsa/README.adoc +++ b/solidity/ecdsa/README.adoc @@ -423,7 +423,7 @@ presented below. Please make sure you have the following prerequisites installed on your machine: - https://nodejs.org[Node.js] >=24.0.0 -- https://yarnpkg.com[Yarn] >=1.22 +- https://yarnpkg.com[Yarn] >=4.12.0 (via Corepack) === Build contracts diff --git a/solidity/ecdsa/deploy/03_deploy_wallet_registry.ts b/solidity/ecdsa/deploy/03_deploy_wallet_registry.ts index e11fbb58e7..ab479db2b9 100644 --- a/solidity/ecdsa/deploy/03_deploy_wallet_registry.ts +++ b/solidity/ecdsa/deploy/03_deploy_wallet_registry.ts @@ -57,7 +57,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { await helpers.ownable.transferOwnership( "EcdsaSortitionPool", - walletRegistry.address, + await walletRegistry.getAddress(), deployer, ) @@ -79,10 +79,10 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { } if (hre.network.tags.tenderly) { - await verifyOnTenderlyOrContinue(hre, () => + await verifyOnTenderlyOrContinue(hre, async () => hre.tenderly.verify({ name: "WalletRegistry", - address: walletRegistry.address, + address: await walletRegistry.getAddress(), }), ) } diff --git a/solidity/ecdsa/deploy/07_approve_wallet_registry.ts b/solidity/ecdsa/deploy/07_approve_wallet_registry.ts index a438b37817..618da0ba67 100644 --- a/solidity/ecdsa/deploy/07_approve_wallet_registry.ts +++ b/solidity/ecdsa/deploy/07_approve_wallet_registry.ts @@ -1,11 +1,10 @@ import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction } from "hardhat-deploy/types" -import type { utils } from "ethers" +import type { Interface } from "ethers" -function ifaceHasFunction(iface: utils.Interface, name: string): boolean { +function ifaceHasFunction(iface: Interface, name: string): boolean { try { - iface.getFunction(name) - return true + return iface.getFunction(name) !== null } catch { return false } @@ -19,7 +18,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const WalletRegistry = await deployments.get("WalletRegistry") const TokenStaking = await get("TokenStaking") - const iface = new ethers.utils.Interface(TokenStaking.abi) + const iface = new ethers.Interface(TokenStaking.abi) if (!ifaceHasFunction(iface, "approveApplication")) { hre.deployments.log( "TokenStaking does not have approveApplication (Threshold TokenStaking); skipping WalletRegistry approval", diff --git a/solidity/ecdsa/deploy/11_transfer_proxy_admin_ownership.ts b/solidity/ecdsa/deploy/11_transfer_proxy_admin_ownership.ts index 9b022cc8f1..d6270f17bf 100644 --- a/solidity/ecdsa/deploy/11_transfer_proxy_admin_ownership.ts +++ b/solidity/ecdsa/deploy/11_transfer_proxy_admin_ownership.ts @@ -21,7 +21,9 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { if (!helpers.address.equal(currentOwner, newProxyAdminOwner)) { log(`transferring ownership of ProxyAdmin to ${newProxyAdminOwner}`) await ( - await proxyAdmin.connect(deployer).transferOwnership(newProxyAdminOwner) + await proxyAdmin.connect(deployer).getFunction("transferOwnership")( + newProxyAdminOwner, + ) ).wait() } } diff --git a/solidity/ecdsa/deploy/12_deploy_proxy_admin_with_deputy.ts b/solidity/ecdsa/deploy/12_deploy_proxy_admin_with_deputy.ts index 7c03e597ed..02ff72cb68 100644 --- a/solidity/ecdsa/deploy/12_deploy_proxy_admin_with_deputy.ts +++ b/solidity/ecdsa/deploy/12_deploy_proxy_admin_with_deputy.ts @@ -23,10 +23,10 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { await ( await proxyAdmin .connect(await ethers.getSigner(esdm)) - .changeProxyAdmin( - WalletRegistry.address, - WalletRegistryProxyAdminWithDeputy.address, - ) + .getFunction("changeProxyAdmin")( + WalletRegistry.address, + WalletRegistryProxyAdminWithDeputy.address, + ) ).wait() } diff --git a/solidity/ecdsa/deploy/15_deploy_allowlist.ts b/solidity/ecdsa/deploy/15_deploy_allowlist.ts index f05a8d0600..1e187f6f87 100644 --- a/solidity/ecdsa/deploy/15_deploy_allowlist.ts +++ b/solidity/ecdsa/deploy/15_deploy_allowlist.ts @@ -11,15 +11,18 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const WalletRegistry = await deployments.get("WalletRegistry") // Deploy the Allowlist contract using upgradeable proxy pattern - const [allowlist] = await helpers.upgrades.deployProxy("Allowlist", { - initializerArgs: [WalletRegistry.address], - factoryOpts: { - signer: await ethers.getSigner(deployer), + const [allowlist, proxyDeployment] = await helpers.upgrades.deployProxy( + "Allowlist", + { + initializerArgs: [WalletRegistry.address], + factoryOpts: { + signer: await ethers.getSigner(deployer), + }, + proxyOpts: { + kind: "transparent", + }, }, - proxyOpts: { - kind: "transparent", - }, - }) + ) // IMPORTANT: Do NOT transfer ownership here! // Allowlist uses Ownable2StepUpgradeable which requires two steps: @@ -34,12 +37,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // Ownership transfer is handled at the END of script 16 after weights are set. // Log deployment information - console.log(`Allowlist deployed at: ${allowlist.address}`) - console.log( - `Allowlist proxy admin: ${await hre.upgrades.erc1967.getAdminAddress( - allowlist.address, - )}`, - ) + console.log(`Allowlist deployed at: ${await allowlist.getAddress()}`) + console.log(`Allowlist proxy deployed at: ${proxyDeployment.address}`) console.log(`Allowlist owner: ${await allowlist.owner()} (deployer)`) if (governance && governance !== deployer) { console.log( diff --git a/solidity/ecdsa/deploy/16_initialize_allowlist_weights.ts b/solidity/ecdsa/deploy/16_initialize_allowlist_weights.ts index 2a4fed2c91..485eddac23 100644 --- a/solidity/ecdsa/deploy/16_initialize_allowlist_weights.ts +++ b/solidity/ecdsa/deploy/16_initialize_allowlist_weights.ts @@ -97,8 +97,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const currentOwner = await allowlist.owner() const ownerSigner = await ethers.getSigner(currentOwner) - console.log(`Allowlist address: ${allowlist.address}`) - console.log(`WalletRegistry address: ${walletRegistry.address}`) + console.log(`Allowlist address: ${await allowlist.getAddress()}`) + console.log(`WalletRegistry address: ${await walletRegistry.getAddress()}`) console.log(`Allowlist owner: ${currentOwner}`) console.log(`Owner signer: ${await ownerSigner.getAddress()}`) console.log() @@ -136,10 +136,10 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // eslint-disable-next-line no-await-in-loop const existingWeight = await allowlist.authorizedStake( op.stakingProvider, - ethers.constants.AddressZero, + ethers.ZeroAddress, ) - if (existingWeight.gt(0)) { + if (existingWeight > 0n) { console.log( `Skipping ${op.identification} (${op.stakingProvider.slice( 0, @@ -168,7 +168,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // eslint-disable-next-line no-await-in-loop const tx = await allowlist .connect(ownerSigner) - .addStakingProvider(op.stakingProvider, op.weight) + .getFunction("addStakingProvider")(op.stakingProvider, op.weight) // eslint-disable-next-line no-await-in-loop const receipt = await tx.wait() @@ -204,7 +204,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const currentAllowlist = await walletRegistry.allowlist() - if (currentAllowlist === ethers.constants.AddressZero) { + if (currentAllowlist === ethers.ZeroAddress) { console.error("ERROR: WalletRegistry V2 is not initialized!") console.error() console.error("Please run the upgrade script first:") @@ -218,12 +218,15 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { return false } - if (currentAllowlist.toLowerCase() !== allowlist.address.toLowerCase()) { + if ( + currentAllowlist.toLowerCase() !== + (await allowlist.getAddress()).toLowerCase() + ) { console.error( "ERROR: WalletRegistry is initialized with a different Allowlist!", ) console.error(` Current: ${currentAllowlist}`) - console.error(` Expected: ${allowlist.address}`) + console.error(` Expected: ${await allowlist.getAddress()}`) return false } @@ -266,8 +269,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { { timestamp: new Date().toISOString(), network: hre.network.name, - allowlistAddress: allowlist.address, - walletRegistryAddress: walletRegistry.address, + allowlistAddress: await allowlist.getAddress(), + walletRegistryAddress: await walletRegistry.getAddress(), weightsSource: weightsData.metadata.source, weightsGeneratedAt: weightsData.metadata.generatedAt, summary: { @@ -318,7 +321,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const tx = await allowlist .connect(ownerSigner) - .transferOwnership(governance) + .getFunction("transferOwnership")(governance) await tx.wait() diff --git a/solidity/ecdsa/deploy/17_upgrade_wallet_registry_v2.ts b/solidity/ecdsa/deploy/17_upgrade_wallet_registry_v2.ts index c1624be0ca..af353f1569 100644 --- a/solidity/ecdsa/deploy/17_upgrade_wallet_registry_v2.ts +++ b/solidity/ecdsa/deploy/17_upgrade_wallet_registry_v2.ts @@ -56,10 +56,10 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // Check if already upgraded (allowlist is set) // Note: V1 doesn't have allowlist() function, so we need to handle that case - let currentAllowlist = ethers.constants.AddressZero + let currentAllowlist = ethers.ZeroAddress try { currentAllowlist = await walletRegistryBefore.allowlist() - if (currentAllowlist !== ethers.constants.AddressZero) { + if (currentAllowlist !== ethers.ZeroAddress) { console.log(` Allowlist: ${currentAllowlist}`) console.log() console.log("WalletRegistry is already upgraded to V2!") @@ -81,23 +81,21 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // Get ProxyAdmin address from EIP-1967 slot const ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - const proxyAdminSlot = await ethers.provider.getStorageAt( + const proxyAdminSlot = await ethers.provider.getStorage( walletRegistryDeployment.address, ADMIN_SLOT, ) - const proxyAdminAddress = ethers.utils.getAddress( - `0x${proxyAdminSlot.slice(-40)}`, - ) + const proxyAdminAddress = ethers.getAddress(`0x${proxyAdminSlot.slice(-40)}`) console.log(` ProxyAdmin: ${proxyAdminAddress}`) // Get current implementation const IMPL_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - const implSlot = await ethers.provider.getStorageAt( + const implSlot = await ethers.provider.getStorage( walletRegistryDeployment.address, IMPL_SLOT, ) - const currentImpl = ethers.utils.getAddress(`0x${implSlot.slice(-40)}`) + const currentImpl = ethers.getAddress(`0x${implSlot.slice(-40)}`) console.log(` Current Implementation: ${currentImpl}`) // Verify governance state is preserved @@ -124,17 +122,26 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { EcdsaSortitionPool.address, TokenStaking.address, ) - await newImplementation.deployed() + await newImplementation.waitForDeployment() - console.log(`New implementation deployed: ${newImplementation.address}`) - console.log(` TX: ${newImplementation.deployTransaction.hash}`) + const deploymentTransaction = newImplementation.deploymentTransaction() + if (!deploymentTransaction) { + throw new Error( + "WalletRegistry implementation deployment has no transaction", + ) + } + + console.log( + `New implementation deployed: ${await newImplementation.getAddress()}`, + ) + console.log(` TX: ${deploymentTransaction.hash}`) console.log() // Save deployment artifact await deployments.save("WalletRegistryV2Implementation", { - address: newImplementation.address, - abi: WalletRegistryFactory.interface.format("json") as any, - transactionHash: newImplementation.deployTransaction.hash, + address: await newImplementation.getAddress(), + abi: JSON.parse(WalletRegistryFactory.interface.formatJson()), + transactionHash: deploymentTransaction.hash, }) // Encode initializeV2 call @@ -144,7 +151,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { ) // Encode upgradeAndCall for ProxyAdmin - const proxyAdminInterface = new ethers.utils.Interface([ + const proxyAdminInterface = new ethers.Interface([ "function upgradeAndCall(address proxy, address implementation, bytes calldata data) external payable", "function owner() external view returns (address)", ]) @@ -153,7 +160,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { "upgradeAndCall", [ walletRegistryDeployment.address, - newImplementation.address, + await newImplementation.getAddress(), initializeV2Data, ], ) @@ -189,7 +196,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // prettier-ignore console.log(" \"upgradeAndCall(address,address,bytes)\" \\") console.log(` ${walletRegistryDeployment.address} \\`) - console.log(` ${newImplementation.address} \\`) + console.log(` ${await newImplementation.getAddress()} \\`) console.log(` ${initializeV2Data} \\`) console.log(" --rpc-url $CHAIN_API_URL \\") console.log(" --private-key ") @@ -210,7 +217,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { network: network.name, timestamp: new Date().toISOString(), description: "Upgrade WalletRegistry to V2 with Allowlist integration", - newImplementation: newImplementation.address, + newImplementation: await newImplementation.getAddress(), proxy: walletRegistryDeployment.address, proxyAdmin: proxyAdminAddress, proxyAdminOwner, @@ -256,7 +263,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // prettier-ignore console.log(" \"upgradeAndCall(address,address,bytes)\" \\") console.log(` ${walletRegistryDeployment.address} \\`) - console.log(` ${newImplementation.address} \\`) + console.log(` ${await newImplementation.getAddress()} \\`) console.log(` "${initializeV2Data}" \\`) console.log(" --rpc-url $CHAIN_API_URL \\") console.log(" --private-key ") @@ -276,7 +283,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { console.log("Calling ProxyAdmin.upgradeAndCall()...") const tx = await proxyAdminContract.upgradeAndCall( walletRegistryDeployment.address, - newImplementation.address, + await newImplementation.getAddress(), initializeV2Data, ) @@ -317,7 +324,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { // prettier-ignore console.log(" \"upgradeAndCall(address,address,bytes)\" \\") console.log(` ${walletRegistryDeployment.address} \\`) - console.log(` ${newImplementation.address} \\`) + console.log(` ${await newImplementation.getAddress()} \\`) console.log(` "${initializeV2Data}" \\`) console.log(" --rpc-url $CHAIN_API_URL \\") console.log(" --private-key ") diff --git a/solidity/ecdsa/export-baseline.sha256 b/solidity/ecdsa/export-baseline.sha256 index 7e8e95cb34..7ed63e1025 100644 --- a/solidity/ecdsa/export-baseline.sha256 +++ b/solidity/ecdsa/export-baseline.sha256 @@ -30,7 +30,7 @@ fdb43c6720acb1f11042134acf834c73531a7a2bedc83ed7744226322e83a3c2 export/artifac 6660b80de891a9bbe770e97ed1e99966cfea6f5f79687ec2dbe314216c1aa1b5 export/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.json cbd12916d02282b4e416b7e8bf40f114dd26b865870d5f5e3f481668141e63b9 export/artifacts/@thesis/solidity-contracts/contracts/token/ERC20WithPermit.sol/ERC20WithPermit.json 7f573910d33bc5537880d9860f1c1846140fd6c624f10b3cf508315ad7735418 export/artifacts/@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol/MisfundRecovery.json -6105e76f2fb5c72178243e69ee9309b66f02800d77ab6bf76249657f971a2fc4 export/artifacts/@threshold-network/solidity-contracts/contracts/staking/TokenStaking.sol/TokenStaking.json +3ec236d2878e8b35e3fb7cbb7ed938f51c135043cac0932a65edb2d2944ca0a1 export/artifacts/@threshold-network/solidity-contracts/contracts/staking/TokenStaking.sol/TokenStaking.json bdcc156776934335faeadd1235fb919367bc1e5a30daa1d024cd48e393c78168 export/artifacts/@threshold-network/solidity-contracts/contracts/token/T.sol/T.json efe500ffe2b983e9be848227c15de8e50ca98e9192f6f971d6dee8b43592f757 export/artifacts/@threshold-network/solidity-contracts/contracts/utils/PercentUtils.sol/PercentUtils.json 5d5793b0e335a8729eb9aa7809fa32ca7cb88e1af01a1e52c1220eb4de040611 export/artifacts/@threshold-network/solidity-contracts/contracts/utils/SafeTUpgradeable.sol/SafeTUpgradeable.json @@ -58,24 +58,26 @@ b0f64c4f26d2a22c75d0f715bc34d128d40cdb8fdfac9db8cd80a1aead05827d export/deploy/ 544a4d1e45c697304f355ec42fdd3d03c8668415e3165b9796406d835be6d80c export/deploy/00_resolve_token_staking.js 8cd73af459dcea2a0c81d453e56d190f82006535d3bb730350c06393e397d97d export/deploy/01_deploy_ecdsa_sortition_pool.js 0981bb7c24be09b39b7d5f39ecc933667adfc2991cce261018ad558bc2b13740 export/deploy/02_deploy_dkg_validator.js -06cca708497003adfcb3646f1236d7c796a1738f8f66af036d934020d5bceade export/deploy/03_deploy_wallet_registry.js +7823892dca4a29a90a6a9c440a737b7cd66e354d6c8835ecbd511b432f5e43d4 export/deploy/03_deploy_wallet_registry.js dc00fb7433b97f19a13c2d32e9c66daa03592ccbfae2ed74e0cbc57f837a920c export/deploy/04_upgrade_random_beacon_chaosnet.js 39fe289554f1630cb5100bce012c1be3f0230f0bebce80547553d6a23da4aae2 export/deploy/05_authorize_in_random_beacon_chaosnet.js 3e9c8ad80dde936aee0c95705bdbb544559993d4587839a65fc7b427f6f26885 export/deploy/06_transfer_ownership_random_beacon_chaosnet.js -d403ea4fde8b47d3a9c7e82ce9f4aa6ed6eeeb1c9a8e0b6abb6e1a7eaedc1056 export/deploy/07_approve_wallet_registry.js +0909d0cdf9ebb013f16ad6a38ababb74513545e089ebd0da60321526ea8240d0 export/deploy/07_approve_wallet_registry.js 1873bde07dae765880b9608aa2e6d115dfb903e1ac112131fcfa4fffdd98c15a export/deploy/08_authorize_wallet_registry.js 861f37f05e2d1e88d07dad2a858409798161dd9b4762bb8e133d0b99aaba0da2 export/deploy/09_deploy_wallet_registry_governance.js 6706e1c643ca7dc85a772d89b7b5df1dad214adee070783ddccdcb8bfaa433e7 export/deploy/10_transfer_governance.js -a197b078c06392d146590941403d27f6d2c4151d8cf5237b4c7af09e1886fd2d export/deploy/11_transfer_proxy_admin_ownership.js -28cba18cbac1abcd515460bee3df10ef74a9cf893c47e718e8e03f7ad2909418 export/deploy/12_deploy_proxy_admin_with_deputy.js +a346901a794f8438815b8c5d9790fba24d28f6d72c13bcba5bdec21949e52871 export/deploy/11_transfer_proxy_admin_ownership.js +1372ae784f9aaa6819e7aa6d661ea2fa038682cb2597f5bcbed6c3bd462224b1 export/deploy/12_deploy_proxy_admin_with_deputy.js 15ac5da9a177d9c64db0f61111b5a25dc3f191abcea521775d8d30bec32cc47a export/deploy/13_authorize_in_random_beacon.js 8550c65be55299dfd72538021e27b86f39e1f98f31aa0ee878b521dc47b3489e export/deploy/14_transfer_reimbursement_pool_ownerhsip.js -832fc3a97c8050e7b7bbf97f6eb7618196c4a408d93ce9e13b8c74fe92365454 export/deploy/15_deploy_allowlist.js -83c4493954d6b5dfdbee159b20db8480f754d947decf3a3076d977ad005b810e export/deploy/16_initialize_allowlist_weights.js -7eec0b723905ade74a26e9fa47d64c5efcbdd9c91c1d3e30850bcb381b6cbb0c export/deploy/17_upgrade_wallet_registry_v2.js +97b667f5e6fe8fa0ddcccb3be3561a746bb749630a01cc6fe28bbdf0f39bcca8 export/deploy/15_deploy_allowlist.js +39dca7317dafdea5a73e2651ddfea978062a45cd746acd0c081c3af3f6e1283d export/deploy/16_initialize_allowlist_weights.js +a9be64e4aa3a3c4c5a00753ca743b0d548c3d7d286a036f89ec3b8c5b1435338 export/deploy/17_upgrade_wallet_registry_v2.js 6ca5200a0e847f77214fe81b2be9262db012ef342d3abe8973c8b8193cf1eb69 export/deploy/etherscanVerification.js e5e4354e40f830b4e57362802a857dca9370e225a08b3737bdcc4bc0b0f71960 export/deploy/tenderlyVerification.js -b2119d066a4378248eec3e836c078616994fc47ed7a62d7c3b978e95b1a84ade export/hardhat.config.js -499e398ba8dfebb69cc094ff9928847a98045a7b66eff874c9c00a8033699a7b export/tasks/index.js -d845cf4f5a38446df70c2aa2f91211eb24b5ecc7d18dd278a4d443798aeb448e export/tasks/initialize-wallet-owner.js -172739af94a39790d78d74437d5d221c4dce5f4fab5ab3e9201654085b8eb9f9 export/tasks/initialize.js +ad564044c9853bf06233080d5dfd908337fe4f8f1dab1573b93fbfa03f1827b4 export/hardhat.config.js +eb6c89a466ed63b60ba79a273d285aed811b1d58c3cf794079553fc544c922e3 export/tasks/index.js +8877b2c460f39736efb87f2bb83aae40553f0d5a1b44a101de10e174fd3f9125 export/tasks/initialize-wallet-owner.js +519b80b9e5494bc0bfbe14416fb285bdb3f98273943cc814e84acd2a52eb9b28 export/tasks/initialize.js +2693ed0b67840cb2a6ea036d9d8911b015e8b1b41f653bda8826d80f269779a7 export/tasks/random-beacon.js +465d6a61b1c91d83d29288976a211b93342849be775dbe34a585ee52aa64e7bd export/utils/random-beacon-export.js diff --git a/solidity/ecdsa/external/random-beacon-export/README.md b/solidity/ecdsa/external/random-beacon-export/README.md index ad15116c7f..5a157e9f1f 100644 --- a/solidity/ecdsa/external/random-beacon-export/README.md +++ b/solidity/ecdsa/external/random-beacon-export/README.md @@ -1,101 +1,41 @@ -# Bundled random-beacon deploy scripts +# Bundled Random Beacon executable exports -This directory contains a committed copy of the `export/deploy/*.js` scripts that -the `@keep-network/random-beacon` package publishes to npm. The ecdsa package -needs these so its hardhat-deploy run can resolve random-beacon's deploy phase -when the local `../random-beacon/export/` directory is unavailable (it is -gitignored) and falling back to `node_modules/@keep-network/random-beacon/export` -would pull a stale published version. +ECDSA uses these compiled exports when the sibling Beacon build is absent. The +normal resolution order for deployment scripts and tasks is sibling `export/`, +this bundle, then the pinned npm package. Artifacts use the sibling build or npm. +`RANDOM_BEACON_EXPORT_PATH` explicitly selects a producer export root and fails +if a requested `deploy/`, `artifacts/` or `tasks/` directory is missing; package +compatibility checks use it to prevent fallback from hiding omissions. -The resolution order is defined in `solidity/ecdsa/hardhat.config.ts` -(`resolveRandomBeaconExport`): local sibling export first, this bundled copy -second, npm fallback last. +ECDSA's initialization, authorization, registration and account-unlock tasks use +the same resolver. This bundle includes the v6 Beacon initialization and unlock +tasks plus their utilities, so the pinned v5 package supplies no executable task +code. Packed ECDSA exports include this bundle and prefer it over the installed +Beacon dependency until that dependency is migrated. -This README lives one level above `deploy/` because hardhat-deploy walks that -directory and tries to `require()` every file; a Markdown sibling there would -crash deployment. +All nine deployment scripts come from `solidity/random-beacon/deploy/*.ts`, compiled as +ES2020/CommonJS with ethers v6. The approval script's missing-function and +already-approved guards live in the TypeScript source, so it is regenerated with +the other scripts. `utils/wait-for-confirmations.js` is also required by the +explorer-tagged deployment paths. Do not hand-edit generated JavaScript. -## Source - -The scripts are the TypeScript-compiled output of `solidity/random-beacon/deploy/*.ts`, -produced by `yarn prepack` (i.e. `tsc -p tsconfig.export.json`) in the -`@keep-network/random-beacon` package. - -## Format - -The bundled scripts intentionally mix two formats: - -- **`01..04, 06..09_*.js`**: `tsc`-compiled ES5 output from the upstream - package's TypeScript sources (`__awaiter` / `__generator` runtime helpers, - `var` declarations). Treat as build artifacts; do not hand-edit. -- **`05_approve_random_beacon_in_token_staking.js`**: hand-written modern - async/await. Adds an `ifaceHasFunction("approveApplication")` precheck (so it - skips cleanly on the Threshold `TokenStaking` ABI, which does not expose - `approveApplication`) plus an idempotency guard that swallows errors only - while reading `applicationInfo(...)`. The `approveApplication(...)` call - itself is intentionally left unwrapped so a genuine revert propagates. - **Do not regenerate from upstream without preserving this precheck** — - blind regeneration will reintroduce a hard failure on networks running the - Threshold staking contract. - -## Known limitation: verification is not wrapped - -Unlike the hand-maintained ECDSA deploy scripts (which route Etherscan/Tenderly -verification through `verifyOnEtherscanOrContinue` / `verifyOnTenderlyOrContinue` -so explorer outages never abort a deploy), the `tsc`-compiled vendored scripts -call `helpers.etherscan.verify(...)` / `hre.tenderly.verify(...)` directly. A -verification failure (rate limit, bytecode mismatch, missing key) in one of -these scripts can therefore halt the deploy. - -This is accepted rather than patched: these are build artifacts and must not be -hand-edited (see Format above). If it becomes a recurring operational problem, -fix it upstream in `@keep-network/random-beacon`'s `export/deploy` sources and -re-vendor, or set `DISABLE_HARDHAT_VERIFY` / the network's verify tags off for -the run. - -## Regenerate - -From the repo root: +From `solidity/random-beacon`, regenerate with: ```sh -cd solidity/random-beacon -yarn install yarn prepack -# Copy every script EXCEPT 05_* — that one is hand-maintained (see below). -cp export/deploy/0[1-4]_*.js ../ecdsa/external/random-beacon-export/deploy/ -cp export/deploy/0[6-9]_*.js ../ecdsa/external/random-beacon-export/deploy/ +cp export/deploy/*.js ../ecdsa/external/random-beacon-export/deploy/ +mkdir -p ../ecdsa/external/random-beacon-export/utils +cp export/utils/wait-for-confirmations.js ../ecdsa/external/random-beacon-export/utils/ +mkdir -p ../ecdsa/external/random-beacon-export/tasks/utils +cp export/tasks/initialize.js export/tasks/unlock-eth-accounts.js ../ecdsa/external/random-beacon-export/tasks/ +cp export/tasks/utils/*.js ../ecdsa/external/random-beacon-export/tasks/utils/ ``` -Then verify `git diff` matches the intended deploy-script change in the -sibling `solidity/random-beacon/deploy/*.ts` source — divergence between -the `.ts` source and the bundled `.js` is the failure mode this directory -guards against. - -### Regeneration policy - -When syncing from upstream: - -1. Regenerate `01..04, 06..09_*.js` from `@keep-network/random-beacon`'s - `export/deploy` source via its `tsc` build (the `yarn prepack` step above). -2. **Skip `05_*.js`** during bulk regeneration — it is maintained deliberately. - If you do regenerate it, ensure it matches - `solidity/random-beacon/deploy/05_approve_random_beacon_in_token_staking.ts` - and preserves the `ifaceHasFunction("approveApplication")` gating and the - `applicationInfo(...)` idempotency check. -3. Verify by running deploys against both a network that exposes - `approveApplication` (legacy Keep TokenStaking) and one that does not - (Threshold TokenStaking). -4. **Also re-check `../types/random-beacon.d.ts`** against - `solidity/random-beacon/tasks/{initialize.ts,utils/*.ts}` — that file is a - second, hand-maintained mirror of this same upstream package's task-export - surface (declarations the published package doesn't yet ship), and nothing - automatically detects drift between it and the upstream sources it tracks. - -## Why we don't just `ts-node` the upstream +Compare the generated files with their sources, then exercise ECDSA with the +sibling export unavailable. Separately test actual npm tarballs with +`RANDOM_BEACON_EXPORT_PATH`; a passing bundled fallback does not validate a +published producer. See [the compatibility checks](../../../docs/ethers-v6-compatibility.md). -`hardhat-deploy` reads deploy scripts from the configured external paths as -plain CommonJS modules. The `external/*/deploy` directories are listed in -`hardhat.config.ts` and loaded via `require`, so they must be runnable JS. -The bundled `.js` here matches what `@keep-network/random-beacon` ships to -npm consumers, keeping the in-monorepo and published-consumer code paths -identical. +The Beacon scripts still call explorer verification directly when the network +tags enable it. Verification failure can halt a deploy. The local compatibility +checks do not test explorer services or enable public-network tags. diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/01_deploy_reimbursement_pool.js b/solidity/ecdsa/external/random-beacon-export/deploy/01_deploy_reimbursement_pool.js index 96a555e026..a62f0c1198 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/01_deploy_reimbursement_pool.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/01_deploy_reimbursement_pool.js @@ -1,84 +1,32 @@ "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, helpers, deployer, staticGas, maxGasPrice, ReimbursementPool; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments, helpers = hre.helpers; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - deployer = (_a.sent()).deployer; - staticGas = 40800 // gas amount consumed by the refund() + tx cost - ; - maxGasPrice = 500000000000 // 500 Gwei - ; - return [4 /*yield*/, deployments.deploy("ReimbursementPool", { - from: deployer, - args: [staticGas, maxGasPrice], - log: true, - waitConfirmations: 1, - })]; - case 2: - ReimbursementPool = _a.sent(); - if (!hre.network.tags.etherscan) return [3 /*break*/, 6]; - if (!ReimbursementPool.transactionHash) return [3 /*break*/, 4]; - return [4 /*yield*/, hre.ethers.provider.waitForTransaction(ReimbursementPool.transactionHash, 2, 300000)]; - case 3: - _a.sent(); - _a.label = 4; - case 4: return [4 /*yield*/, helpers.etherscan.verify(ReimbursementPool)]; - case 5: - _a.sent(); - _a.label = 6; - case 6: - if (!hre.network.tags.tenderly) return [3 /*break*/, 8]; - return [4 /*yield*/, hre.tenderly.verify({ - name: "ReimbursementPool", - address: ReimbursementPool.address, - })]; - case 7: - _a.sent(); - _a.label = 8; - case 8: return [2 /*return*/]; - } +const wait_for_confirmations_1 = __importDefault(require("../utils/wait-for-confirmations")); +const func = async (hre) => { + const { getNamedAccounts, deployments, helpers } = hre; + const { deployer } = await getNamedAccounts(); + const staticGas = 40800; // gas amount consumed by the refund() + tx cost + const maxGasPrice = 500000000000; // 500 Gwei + const ReimbursementPool = await deployments.deploy("ReimbursementPool", { + from: deployer, + args: [staticGas, maxGasPrice], + log: true, + waitConfirmations: 1, }); -}); }; + if (hre.network.tags.etherscan) { + if (ReimbursementPool.transactionHash) { + await (0, wait_for_confirmations_1.default)(hre.ethers.provider, ReimbursementPool.transactionHash, 2, 300000); + } + await helpers.etherscan.verify(ReimbursementPool); + } + if (hre.network.tags.tenderly) { + await hre.tenderly.verify({ + name: "ReimbursementPool", + address: ReimbursementPool.address, + }); + } +}; exports.default = func; func.tags = ["ReimbursementPool"]; diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/02_deploy_beacon_sortition_pool.js b/solidity/ecdsa/external/random-beacon-export/deploy/02_deploy_beacon_sortition_pool.js index f5cda5a629..c43b4f0630 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/02_deploy_beacon_sortition_pool.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/02_deploy_beacon_sortition_pool.js @@ -1,91 +1,37 @@ "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, helpers, _a, deployer, chaosnetOwner, execute, to1e18, POOL_WEIGHT_DIVISOR, T, BeaconSortitionPool; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments, helpers = hre.helpers; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - _a = _b.sent(), deployer = _a.deployer, chaosnetOwner = _a.chaosnetOwner; - execute = deployments.execute; - to1e18 = helpers.number.to1e18; - POOL_WEIGHT_DIVISOR = to1e18(1); - return [4 /*yield*/, deployments.get("T")]; - case 2: - T = _b.sent(); - return [4 /*yield*/, deployments.deploy("BeaconSortitionPool", { - contract: "SortitionPool", - from: deployer, - args: [T.address, POOL_WEIGHT_DIVISOR], - log: true, - waitConfirmations: 1, - })]; - case 3: - BeaconSortitionPool = _b.sent(); - return [4 /*yield*/, execute("BeaconSortitionPool", { from: deployer, log: true, waitConfirmations: 1 }, "transferChaosnetOwnerRole", chaosnetOwner)]; - case 4: - _b.sent(); - if (!hre.network.tags.etherscan) return [3 /*break*/, 8]; - if (!BeaconSortitionPool.transactionHash) return [3 /*break*/, 6]; - return [4 /*yield*/, hre.ethers.provider.waitForTransaction(BeaconSortitionPool.transactionHash, 2, 300000)]; - case 5: - _b.sent(); - _b.label = 6; - case 6: return [4 /*yield*/, helpers.etherscan.verify(BeaconSortitionPool)]; - case 7: - _b.sent(); - _b.label = 8; - case 8: - if (!hre.network.tags.tenderly) return [3 /*break*/, 10]; - return [4 /*yield*/, hre.tenderly.verify({ - name: "BeaconSortitionPool", - address: BeaconSortitionPool.address, - })]; - case 9: - _b.sent(); - _b.label = 10; - case 10: return [2 /*return*/]; - } +const wait_for_confirmations_1 = __importDefault(require("../utils/wait-for-confirmations")); +const func = async (hre) => { + const { getNamedAccounts, deployments, helpers } = hre; + const { deployer, chaosnetOwner } = await getNamedAccounts(); + const { execute } = deployments; + const { to1e18 } = helpers.number; + const POOL_WEIGHT_DIVISOR = to1e18(1); + const T = await deployments.get("T"); + const BeaconSortitionPool = await deployments.deploy("BeaconSortitionPool", { + contract: "SortitionPool", + from: deployer, + args: [T.address, POOL_WEIGHT_DIVISOR], + log: true, + waitConfirmations: 1, }); -}); }; + await execute("BeaconSortitionPool", { from: deployer, log: true, waitConfirmations: 1 }, "transferChaosnetOwnerRole", chaosnetOwner); + if (hre.network.tags.etherscan) { + if (BeaconSortitionPool.transactionHash) { + await (0, wait_for_confirmations_1.default)(hre.ethers.provider, BeaconSortitionPool.transactionHash, 2, 300000); + } + await helpers.etherscan.verify(BeaconSortitionPool); + } + if (hre.network.tags.tenderly) { + await hre.tenderly.verify({ + name: "BeaconSortitionPool", + address: BeaconSortitionPool.address, + }); + } +}; exports.default = func; func.tags = ["BeaconSortitionPool"]; // TokenStaking and T deployments are expected to be resolved from diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/03_deploy_beacon_dkg_validator.js b/solidity/ecdsa/external/random-beacon-export/deploy/03_deploy_beacon_dkg_validator.js index 19af14eaec..e6e39eda3d 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/03_deploy_beacon_dkg_validator.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/03_deploy_beacon_dkg_validator.js @@ -1,84 +1,32 @@ "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, helpers, deployer, BeaconSortitionPool, BeaconDkgValidator; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments, helpers = hre.helpers; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - deployer = (_a.sent()).deployer; - return [4 /*yield*/, deployments.get("BeaconSortitionPool")]; - case 2: - BeaconSortitionPool = _a.sent(); - return [4 /*yield*/, deployments.deploy("BeaconDkgValidator", { - from: deployer, - args: [BeaconSortitionPool.address], - log: true, - waitConfirmations: 1, - })]; - case 3: - BeaconDkgValidator = _a.sent(); - if (!hre.network.tags.etherscan) return [3 /*break*/, 7]; - if (!BeaconDkgValidator.transactionHash) return [3 /*break*/, 5]; - return [4 /*yield*/, hre.ethers.provider.waitForTransaction(BeaconDkgValidator.transactionHash, 2, 300000)]; - case 4: - _a.sent(); - _a.label = 5; - case 5: return [4 /*yield*/, helpers.etherscan.verify(BeaconDkgValidator)]; - case 6: - _a.sent(); - _a.label = 7; - case 7: - if (!hre.network.tags.tenderly) return [3 /*break*/, 9]; - return [4 /*yield*/, hre.tenderly.verify({ - name: "BeaconDkgValidator", - address: BeaconDkgValidator.address, - })]; - case 8: - _a.sent(); - _a.label = 9; - case 9: return [2 /*return*/]; - } +const wait_for_confirmations_1 = __importDefault(require("../utils/wait-for-confirmations")); +const func = async (hre) => { + const { getNamedAccounts, deployments, helpers } = hre; + const { deployer } = await getNamedAccounts(); + const BeaconSortitionPool = await deployments.get("BeaconSortitionPool"); + const BeaconDkgValidator = await deployments.deploy("BeaconDkgValidator", { + from: deployer, + args: [BeaconSortitionPool.address], + log: true, + waitConfirmations: 1, }); -}); }; + if (hre.network.tags.etherscan) { + if (BeaconDkgValidator.transactionHash) { + await (0, wait_for_confirmations_1.default)(hre.ethers.provider, BeaconDkgValidator.transactionHash, 2, 300000); + } + await helpers.etherscan.verify(BeaconDkgValidator); + } + if (hre.network.tags.tenderly) { + await hre.tenderly.verify({ + name: "BeaconDkgValidator", + address: BeaconDkgValidator.address, + }); + } +}; exports.default = func; func.tags = ["BeaconDkgValidator"]; func.dependencies = ["BeaconSortitionPool"]; diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/04_deploy_random_beacon.js b/solidity/ecdsa/external/random-beacon-export/deploy/04_deploy_random_beacon.js index a67c73387c..d30fc5ea13 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/04_deploy_random_beacon.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/04_deploy_random_beacon.js @@ -1,147 +1,63 @@ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); +Object.defineProperty(exports, "__esModule", { value: true }); +const wait_for_confirmations_1 = __importDefault(require("../utils/wait-for-confirmations")); +const func = async (hre) => { + const { getNamedAccounts, deployments, helpers } = hre; + const { deployer } = await getNamedAccounts(); + const T = await deployments.get("T"); + const TokenStaking = await deployments.get("TokenStaking"); + const ReimbursementPool = await deployments.get("ReimbursementPool"); + const BeaconSortitionPool = await deployments.get("BeaconSortitionPool"); + const BeaconDkgValidator = await deployments.get("BeaconDkgValidator"); + const deployOptions = { + from: deployer, + log: true, + waitConfirmations: 1, + }; + const BLS = await deployments.deploy("BLS", deployOptions); + const BeaconAuthorization = await deployments.deploy("BeaconAuthorization", deployOptions); + const BeaconDkg = await deployments.deploy("BeaconDkg", deployOptions); + const BeaconInactivity = await deployments.deploy("BeaconInactivity", deployOptions); + const RandomBeacon = await deployments.deploy("RandomBeacon", { + contract: process.env.TEST_USE_STUBS_BEACON === "true" + ? "RandomBeaconStub" + : undefined, + args: [ + BeaconSortitionPool.address, + T.address, + TokenStaking.address, + BeaconDkgValidator.address, + ReimbursementPool.address, + ], + libraries: { + BLS: BLS.address, + BeaconAuthorization: BeaconAuthorization.address, + BeaconDkg: BeaconDkg.address, + BeaconInactivity: BeaconInactivity.address, + }, + ...deployOptions, }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + await helpers.ownable.transferOwnership("BeaconSortitionPool", RandomBeacon.address, deployer); + if (hre.network.tags.etherscan) { + if (RandomBeacon.transactionHash) { + await (0, wait_for_confirmations_1.default)(hre.ethers.provider, RandomBeacon.transactionHash, 2, 300000); + } + await helpers.etherscan.verify(BLS); + await helpers.etherscan.verify(BeaconAuthorization); + await helpers.etherscan.verify(BeaconDkg); + await helpers.etherscan.verify(BeaconInactivity); + await helpers.etherscan.verify(RandomBeacon); + } + if (hre.network.tags.tenderly) { + await hre.tenderly.verify({ + name: "RandomBeacon", + address: RandomBeacon.address, + }); } }; -Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, helpers, deployer, T, TokenStaking, ReimbursementPool, BeaconSortitionPool, BeaconDkgValidator, deployOptions, BLS, BeaconAuthorization, BeaconDkg, BeaconInactivity, RandomBeacon; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments, helpers = hre.helpers; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - deployer = (_a.sent()).deployer; - return [4 /*yield*/, deployments.get("T")]; - case 2: - T = _a.sent(); - return [4 /*yield*/, deployments.get("TokenStaking")]; - case 3: - TokenStaking = _a.sent(); - return [4 /*yield*/, deployments.get("ReimbursementPool")]; - case 4: - ReimbursementPool = _a.sent(); - return [4 /*yield*/, deployments.get("BeaconSortitionPool")]; - case 5: - BeaconSortitionPool = _a.sent(); - return [4 /*yield*/, deployments.get("BeaconDkgValidator")]; - case 6: - BeaconDkgValidator = _a.sent(); - deployOptions = { - from: deployer, - log: true, - waitConfirmations: 1, - }; - return [4 /*yield*/, deployments.deploy("BLS", deployOptions)]; - case 7: - BLS = _a.sent(); - return [4 /*yield*/, deployments.deploy("BeaconAuthorization", deployOptions)]; - case 8: - BeaconAuthorization = _a.sent(); - return [4 /*yield*/, deployments.deploy("BeaconDkg", deployOptions)]; - case 9: - BeaconDkg = _a.sent(); - return [4 /*yield*/, deployments.deploy("BeaconInactivity", deployOptions)]; - case 10: - BeaconInactivity = _a.sent(); - return [4 /*yield*/, deployments.deploy("RandomBeacon", __assign({ contract: process.env.TEST_USE_STUBS_BEACON === "true" - ? "RandomBeaconStub" - : undefined, args: [ - BeaconSortitionPool.address, - T.address, - TokenStaking.address, - BeaconDkgValidator.address, - ReimbursementPool.address, - ], libraries: { - BLS: BLS.address, - BeaconAuthorization: BeaconAuthorization.address, - BeaconDkg: BeaconDkg.address, - BeaconInactivity: BeaconInactivity.address, - } }, deployOptions))]; - case 11: - RandomBeacon = _a.sent(); - return [4 /*yield*/, helpers.ownable.transferOwnership("BeaconSortitionPool", RandomBeacon.address, deployer)]; - case 12: - _a.sent(); - if (!hre.network.tags.etherscan) return [3 /*break*/, 20]; - if (!RandomBeacon.transactionHash) return [3 /*break*/, 14]; - return [4 /*yield*/, hre.ethers.provider.waitForTransaction(RandomBeacon.transactionHash, 2, 300000)]; - case 13: - _a.sent(); - _a.label = 14; - case 14: return [4 /*yield*/, helpers.etherscan.verify(BLS)]; - case 15: - _a.sent(); - return [4 /*yield*/, helpers.etherscan.verify(BeaconAuthorization)]; - case 16: - _a.sent(); - return [4 /*yield*/, helpers.etherscan.verify(BeaconDkg)]; - case 17: - _a.sent(); - return [4 /*yield*/, helpers.etherscan.verify(BeaconInactivity)]; - case 18: - _a.sent(); - return [4 /*yield*/, helpers.etherscan.verify(RandomBeacon)]; - case 19: - _a.sent(); - _a.label = 20; - case 20: - if (!hre.network.tags.tenderly) return [3 /*break*/, 22]; - return [4 /*yield*/, hre.tenderly.verify({ - name: "RandomBeacon", - address: RandomBeacon.address, - })]; - case 21: - _a.sent(); - _a.label = 22; - case 22: return [2 /*return*/]; - } - }); -}); }; exports.default = func; func.tags = ["RandomBeacon"]; func.dependencies = [ diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/05_approve_random_beacon_in_token_staking.js b/solidity/ecdsa/external/random-beacon-export/deploy/05_approve_random_beacon_in_token_staking.js index 738d85e62c..30ec7b136b 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/05_approve_random_beacon_in_token_staking.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/05_approve_random_beacon_in_token_staking.js @@ -1,31 +1,31 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // ApplicationStatus enum: NOT_APPROVED=0, APPROVED=1, PAUSED=2, DISABLED=3 -var APPLICATION_STATUS_APPROVED = 1; +const APPLICATION_STATUS_APPROVED = 1n; function ifaceHasFunction(iface, name) { try { - iface.getFunction(name); - return true; + return iface.getFunction(name) !== null; } - catch (_a) { + catch { return false; } } -async function func(hre) { - var deployer = (await hre.getNamedAccounts()).deployer; - var execute = hre.deployments.execute, get = hre.deployments.get; - var ethers = hre.ethers; - var RandomBeacon = await hre.deployments.get("RandomBeacon"); - var TokenStaking = await get("TokenStaking"); - var iface = new ethers.utils.Interface(TokenStaking.abi); +const func = async (hre) => { + const { getNamedAccounts, deployments, ethers } = hre; + const { deployer } = await getNamedAccounts(); + const { execute, get } = deployments; + const RandomBeacon = await deployments.get("RandomBeacon"); + const TokenStaking = await get("TokenStaking"); + const iface = new ethers.Interface(TokenStaking.abi); if (!ifaceHasFunction(iface, "approveApplication")) { hre.deployments.log("TokenStaking does not have approveApplication (Threshold TokenStaking); skipping"); return; } + // Skip if RandomBeacon is already approved (idempotent for re-runs) try { - var tokenStakingContract = await ethers.getContractAt(TokenStaking.abi, TokenStaking.address); + const tokenStakingContract = await ethers.getContractAt(TokenStaking.abi, TokenStaking.address); if (ifaceHasFunction(iface, "applicationInfo")) { - var appInfo = await tokenStakingContract.applicationInfo(RandomBeacon.address); + const appInfo = await tokenStakingContract.applicationInfo(RandomBeacon.address); if (appInfo.status === APPLICATION_STATUS_APPROVED) { hre.deployments.log("RandomBeacon already approved in TokenStaking; skipping"); return; @@ -33,12 +33,12 @@ async function func(hre) { } } catch (e) { - hre.deployments.log("Could not read TokenStaking application status (continuing): ".concat(e)); + hre.deployments.log(`Could not read TokenStaking application status (continuing): ${e}`); } await execute("TokenStaking", { from: deployer, log: true, waitConfirmations: 1 }, "approveApplication", RandomBeacon.address); -} +}; exports.default = func; func.tags = ["RandomBeaconApprove"]; func.dependencies = ["TokenStaking", "RandomBeacon"]; // Skip for mainnet (already approved). -func.skip = async function (hre) { return hre.network.name === "mainnet"; }; +func.skip = async (hre) => hre.network.name === "mainnet"; diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/06_authorize_random_beacon_in_reimbursement_pool.js b/solidity/ecdsa/external/random-beacon-export/deploy/06_authorize_random_beacon_in_reimbursement_pool.js index 2a179fe3a2..c7386d4cc3 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/06_authorize_random_beacon_in_reimbursement_pool.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/06_authorize_random_beacon_in_reimbursement_pool.js @@ -1,61 +1,12 @@ "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, deployer, execute, RandomBeacon; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - deployer = (_a.sent()).deployer; - execute = deployments.execute; - return [4 /*yield*/, deployments.get("RandomBeacon")]; - case 2: - RandomBeacon = _a.sent(); - return [4 /*yield*/, execute("ReimbursementPool", { from: deployer, log: true, waitConfirmations: 1 }, "authorize", RandomBeacon.address)]; - case 3: - _a.sent(); - return [2 /*return*/]; - } - }); -}); }; +const func = async (hre) => { + const { getNamedAccounts, deployments } = hre; + const { deployer } = await getNamedAccounts(); + const { execute } = deployments; + const RandomBeacon = await deployments.get("RandomBeacon"); + await execute("ReimbursementPool", { from: deployer, log: true, waitConfirmations: 1 }, "authorize", RandomBeacon.address); +}; exports.default = func; func.tags = ["RandomBeaconAuthorize"]; func.dependencies = ["ReimbursementPool", "RandomBeacon"]; diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/07_deploy_random_beacon_governance.js b/solidity/ecdsa/external/random-beacon-export/deploy/07_deploy_random_beacon_governance.js index c248ec08b8..9eae4c02fb 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/07_deploy_random_beacon_governance.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/07_deploy_random_beacon_governance.js @@ -1,86 +1,33 @@ "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, helpers, deployer, RandomBeacon, GOVERNANCE_DELAY, RandomBeaconGovernance; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments, helpers = hre.helpers; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - deployer = (_a.sent()).deployer; - return [4 /*yield*/, deployments.get("RandomBeacon")]; - case 2: - RandomBeacon = _a.sent(); - GOVERNANCE_DELAY = 604800 // 1 week - ; - return [4 /*yield*/, deployments.deploy("RandomBeaconGovernance", { - from: deployer, - args: [RandomBeacon.address, GOVERNANCE_DELAY], - log: true, - waitConfirmations: 1, - })]; - case 3: - RandomBeaconGovernance = _a.sent(); - if (!hre.network.tags.etherscan) return [3 /*break*/, 7]; - if (!RandomBeaconGovernance.transactionHash) return [3 /*break*/, 5]; - return [4 /*yield*/, hre.ethers.provider.waitForTransaction(RandomBeaconGovernance.transactionHash, 2, 300000)]; - case 4: - _a.sent(); - _a.label = 5; - case 5: return [4 /*yield*/, helpers.etherscan.verify(RandomBeaconGovernance)]; - case 6: - _a.sent(); - _a.label = 7; - case 7: - if (!hre.network.tags.tenderly) return [3 /*break*/, 9]; - return [4 /*yield*/, hre.tenderly.verify({ - name: "RandomBeaconGovernance", - address: RandomBeaconGovernance.address, - })]; - case 8: - _a.sent(); - _a.label = 9; - case 9: return [2 /*return*/]; - } +const wait_for_confirmations_1 = __importDefault(require("../utils/wait-for-confirmations")); +const func = async (hre) => { + const { getNamedAccounts, deployments, helpers } = hre; + const { deployer } = await getNamedAccounts(); + const RandomBeacon = await deployments.get("RandomBeacon"); + const GOVERNANCE_DELAY = 604800; // 1 week + const RandomBeaconGovernance = await deployments.deploy("RandomBeaconGovernance", { + from: deployer, + args: [RandomBeacon.address, GOVERNANCE_DELAY], + log: true, + waitConfirmations: 1, }); -}); }; + if (hre.network.tags.etherscan) { + if (RandomBeaconGovernance.transactionHash) { + await (0, wait_for_confirmations_1.default)(hre.ethers.provider, RandomBeaconGovernance.transactionHash, 2, 300000); + } + await helpers.etherscan.verify(RandomBeaconGovernance); + } + if (hre.network.tags.tenderly) { + await hre.tenderly.verify({ + name: "RandomBeaconGovernance", + address: RandomBeaconGovernance.address, + }); + } +}; exports.default = func; func.tags = ["RandomBeaconGovernance"]; func.dependencies = ["RandomBeacon"]; diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/08_transfer_governance.js b/solidity/ecdsa/external/random-beacon-export/deploy/08_transfer_governance.js index 9538cdad39..13494d1cbb 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/08_transfer_governance.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/08_transfer_governance.js @@ -1,63 +1,12 @@ "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, helpers, _a, deployer, governance, RandomBeaconGovernance; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments, helpers = hre.helpers; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - _a = _b.sent(), deployer = _a.deployer, governance = _a.governance; - return [4 /*yield*/, deployments.get("RandomBeaconGovernance")]; - case 2: - RandomBeaconGovernance = _b.sent(); - return [4 /*yield*/, helpers.ownable.transferOwnership("RandomBeaconGovernance", governance, deployer)]; - case 3: - _b.sent(); - return [4 /*yield*/, deployments.execute("RandomBeacon", { from: deployer, log: true, waitConfirmations: 1 }, "transferGovernance", RandomBeaconGovernance.address)]; - case 4: - _b.sent(); - return [2 /*return*/]; - } - }); -}); }; +const func = async (hre) => { + const { getNamedAccounts, deployments, helpers } = hre; + const { deployer, governance } = await getNamedAccounts(); + const RandomBeaconGovernance = await deployments.get("RandomBeaconGovernance"); + await helpers.ownable.transferOwnership("RandomBeaconGovernance", governance, deployer); + await deployments.execute("RandomBeacon", { from: deployer, log: true, waitConfirmations: 1 }, "transferGovernance", RandomBeaconGovernance.address); +}; exports.default = func; func.tags = ["RandomBeaconTransferGovernance"]; func.dependencies = ["RandomBeaconGovernance"]; diff --git a/solidity/ecdsa/external/random-beacon-export/deploy/09_deploy_random_beacon_chaosnet.js b/solidity/ecdsa/external/random-beacon-export/deploy/09_deploy_random_beacon_chaosnet.js index 29a1b5f6a7..3ee769357d 100644 --- a/solidity/ecdsa/external/random-beacon-export/deploy/09_deploy_random_beacon_chaosnet.js +++ b/solidity/ecdsa/external/random-beacon-export/deploy/09_deploy_random_beacon_chaosnet.js @@ -1,91 +1,32 @@ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); +Object.defineProperty(exports, "__esModule", { value: true }); +const wait_for_confirmations_1 = __importDefault(require("../utils/wait-for-confirmations")); +const func = async (hre) => { + const { getNamedAccounts, deployments, helpers } = hre; + const { deployer } = await getNamedAccounts(); + const deployOptions = { + from: deployer, + log: true, + waitConfirmations: 1, + }; + const RandomBeaconChaosnet = await deployments.deploy("RandomBeaconChaosnet", { + ...deployOptions, }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + if (hre.network.tags.etherscan) { + if (RandomBeaconChaosnet.transactionHash) { + await (0, wait_for_confirmations_1.default)(hre.ethers.provider, RandomBeaconChaosnet.transactionHash, 2, 300000); + } + await helpers.etherscan.verify(RandomBeaconChaosnet); + } + if (hre.network.tags.tenderly) { + await hre.tenderly.verify({ + name: "RandomBeaconChaosnet", + address: RandomBeaconChaosnet.address, + }); } }; -Object.defineProperty(exports, "__esModule", { value: true }); -var func = function (hre) { return __awaiter(void 0, void 0, void 0, function () { - var getNamedAccounts, deployments, helpers, deployer, deployOptions, RandomBeaconChaosnet; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - getNamedAccounts = hre.getNamedAccounts, deployments = hre.deployments, helpers = hre.helpers; - return [4 /*yield*/, getNamedAccounts()]; - case 1: - deployer = (_a.sent()).deployer; - deployOptions = { - from: deployer, - log: true, - waitConfirmations: 1, - }; - return [4 /*yield*/, deployments.deploy("RandomBeaconChaosnet", __assign({}, deployOptions))]; - case 2: - RandomBeaconChaosnet = _a.sent(); - if (!hre.network.tags.etherscan) return [3 /*break*/, 6]; - if (!RandomBeaconChaosnet.transactionHash) return [3 /*break*/, 4]; - return [4 /*yield*/, hre.ethers.provider.waitForTransaction(RandomBeaconChaosnet.transactionHash, 2, 300000)]; - case 3: - _a.sent(); - _a.label = 4; - case 4: return [4 /*yield*/, helpers.etherscan.verify(RandomBeaconChaosnet)]; - case 5: - _a.sent(); - _a.label = 6; - case 6: - if (!hre.network.tags.tenderly) return [3 /*break*/, 8]; - return [4 /*yield*/, hre.tenderly.verify({ - name: "RandomBeaconChaosnet", - address: RandomBeaconChaosnet.address, - })]; - case 7: - _a.sent(); - _a.label = 8; - case 8: return [2 /*return*/]; - } - }); -}); }; exports.default = func; func.tags = ["RandomBeaconChaosnet"]; diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/initialize.js b/solidity/ecdsa/external/random-beacon-export/tasks/initialize.js new file mode 100644 index 0000000000..2d0ded1b58 --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/initialize.js @@ -0,0 +1,89 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TASK_ADD_BETA_OPERATOR = exports.TASK_REGISTER = exports.TASK_AUTHORIZE = exports.TASK_STAKE = exports.TASK_MINT = exports.TASK_INITIALIZE_STAKING = exports.TASK_INITIALIZE = void 0; +const ethers_1 = require("ethers"); +const config_1 = require("hardhat/config"); +const utils_1 = require("./utils"); +// Main task executing all child tasks. +exports.TASK_INITIALIZE = "initialize"; +// Subtask for staking. +exports.TASK_INITIALIZE_STAKING = `${exports.TASK_INITIALIZE}:staking`; +// Staking tasks. +exports.TASK_MINT = "mint"; +exports.TASK_STAKE = "stake"; +// Name prefix that should be used in tasks implementation for specific application. +exports.TASK_AUTHORIZE = "authorize"; +exports.TASK_REGISTER = "register"; +exports.TASK_ADD_BETA_OPERATOR = "add_beta_operator"; +// Subtask for the Random Beacon application. +const TASK_INITIALIZE_BEACON = `${exports.TASK_INITIALIZE}:beacon`; +const TASK_AUTHORIZE_BEACON = `${exports.TASK_AUTHORIZE}:beacon`; +const TASK_REGISTER_BEACON = `${exports.TASK_REGISTER}:beacon`; +const TASK_ADD_BETA_OPERATOR_BEACON = `${exports.TASK_ADD_BETA_OPERATOR}:beacon`; +(0, config_1.task)(exports.TASK_INITIALIZE, "Initializes staking and the Random Beacon application for a staking provider and an operator") + .addParam("owner", "Stake Owner address", undefined, config_1.types.string) + .addParam("provider", "Staking Provider", undefined, config_1.types.string) + .addParam("operator", "Staking Operator", undefined, config_1.types.string) + .addOptionalParam("beneficiary", "Stake Beneficiary", undefined, config_1.types.string) + .addOptionalParam("authorizer", "Stake Authorizer", undefined, config_1.types.string) + .addOptionalParam("amount", "Stake amount", 1000000, config_1.types.int) + .addOptionalParam("authorization", "Authorization amount (default: minimumAuthorization)", undefined, config_1.types.int) + .setAction(async (args, hre) => { + // Initialize staking + await hre.run(exports.TASK_INITIALIZE_STAKING, args); + // Initialize Beacon + await hre.run(TASK_INITIALIZE_BEACON, args); + // Set the operator as a beta operator + await hre.run(TASK_ADD_BETA_OPERATOR_BEACON, args); +}); +(0, config_1.task)(exports.TASK_INITIALIZE_STAKING, "Initializes staking for a service provider") + .addParam("owner", "Stake Owner address", undefined, config_1.types.string) + .addParam("provider", "Staking Provider", undefined, config_1.types.string) + .addOptionalParam("beneficiary", "Stake Beneficiary", undefined, config_1.types.string) + .addOptionalParam("authorizer", "Stake Authorizer", undefined, config_1.types.string) + .addOptionalParam("amount", "Stake amount", 1000000, config_1.types.int) + .setAction(async (args, hre) => { + const tokensToMint = await (0, utils_1.calculateTokensNeededForStake)(hre, args.provider, args.amount); + if (tokensToMint !== 0n) { + await hre.run(exports.TASK_MINT, { ...args, amount: (0, ethers_1.getNumber)(tokensToMint) }); + } + await hre.run(exports.TASK_STAKE, args); +}); +(0, config_1.task)(exports.TASK_MINT, "Mints T tokens") + .addParam("owner", "Stake Owner address", undefined, config_1.types.string) + .addOptionalParam("amount", "Stake amount", 1000000, config_1.types.int) + .setAction(async (args, hre) => { + await (0, utils_1.mint)(hre, args.owner, args.amount); +}); +(0, config_1.task)(exports.TASK_STAKE, "Stakes T tokens") + .addParam("owner", "Stake Owner address", undefined, config_1.types.string) + .addParam("provider", "Staking Provider", undefined, config_1.types.string) + .addOptionalParam("beneficiary", "Stake Beneficiary", undefined, config_1.types.string) + .addOptionalParam("authorizer", "Stake Authorizer", undefined, config_1.types.string) + .addOptionalParam("amount", "Stake amount", 1000000, config_1.types.int) + .setAction(async (args, hre) => { + await (0, utils_1.stake)(hre, args.owner, args.provider, args.amount, args.beneficiary, args.authorizer); +}); +(0, config_1.task)(TASK_INITIALIZE_BEACON, "Initializes operator for Beacon").setAction(async (args, hre) => { + await hre.run(TASK_AUTHORIZE_BEACON, args); + await hre.run(TASK_REGISTER_BEACON, args); +}); +(0, config_1.task)(TASK_AUTHORIZE_BEACON, "Sets authorization for Beacon") + .addParam("owner", "Stake Owner address", undefined, config_1.types.string) + .addParam("provider", "Staking Provider", undefined, config_1.types.string) + .addOptionalParam("authorizer", "Stake Authorizer", undefined, config_1.types.string) + .addOptionalParam("authorization", "Authorization amount (default: minimumAuthorization)", undefined, config_1.types.int) + .setAction(async (args, hre) => { + await (0, utils_1.authorize)(hre, "RandomBeacon", args.owner, args.provider, args.authorizer, args.authorization); +}); +(0, config_1.task)(TASK_REGISTER_BEACON, "Registers an operator for a staking provider in Beacon") + .addParam("provider", "Staking Provider", undefined, config_1.types.string) + .addParam("operator", "Operator Address", undefined, config_1.types.string) + .setAction(async (args, hre) => { + await (0, utils_1.register)(hre, "RandomBeacon", args.provider, args.operator); +}); +(0, config_1.task)(TASK_ADD_BETA_OPERATOR_BEACON, "Adds an operator to the set of beta operators in Beacon") + .addParam("operator", "Operator Address", undefined, config_1.types.string) + .setAction(async (args, hre) => { + await (0, utils_1.addBetaOperator)(hre, "BeaconSortitionPool", args.operator); +}); diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/unlock-eth-accounts.js b/solidity/ecdsa/external/random-beacon-export/tasks/unlock-eth-accounts.js new file mode 100644 index 0000000000..28197bcd10 --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/unlock-eth-accounts.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_1 = require("hardhat/config"); +(0, config_1.task)("unlock-accounts", "Unlock ethereum accounts").setAction(async (args, hre) => { + const { ethers } = hre; + if (hre.network.name === "development") { + const password = process.env.KEEP_ETHEREUM_PASSWORD || "password"; + const provider = new ethers.JsonRpcProvider(hre.network.config.url); + const accounts = await provider.listAccounts(); + console.log(`Total accounts: ${accounts.length}`); + console.log("---------------------------------"); + for (let i = 0; i < accounts.length; i++) { + const account = await accounts[i].getAddress(); + try { + console.log(`\nUnlocking account: ${account}`); + // An explicit duration of zero seconds unlocks the key until geth exits. + await provider.send("personal_unlockAccount", [ + account.toLowerCase(), + password, + 0, + ]); + console.log("Account unlocked!"); + } + catch (error) { + console.log(`\nAccount: ${account} not unlocked!`); + console.error(error); + } + console.log("\n---------------------------------"); + } + } +}); diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/utils/add_beta_operator.js b/solidity/ecdsa/external/random-beacon-export/tasks/utils/add_beta_operator.js new file mode 100644 index 0000000000..fd27d63265 --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/utils/add_beta_operator.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.addBetaOperator = addBetaOperator; +// eslint-disable-next-line import/prefer-default-export +async function addBetaOperator(hre, sortitionPoolDeploymentName, operator) { + const { ethers, helpers } = hre; + const sortitionPool = await helpers.contracts.getContract(sortitionPoolDeploymentName); + const chaosnetOwner = await sortitionPool.chaosnetOwner(); + if (await sortitionPool.isBetaOperator(operator)) { + console.log(`Operator ${operator} is already a beta operator`); + return; + } + console.log(`Adding ${operator} to the set of beta operators...`); + await (await sortitionPool + .connect(await ethers.getSigner(chaosnetOwner)) + .getFunction("addBetaOperators")([operator])).wait(); +} diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/utils/authorize.js b/solidity/ecdsa/external/random-beacon-export/tasks/utils/authorize.js new file mode 100644 index 0000000000..2d5d78e9d4 --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/utils/authorize.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.authorize = authorize; +// eslint-disable-next-line import/prefer-default-export +async function authorize(hre, deploymentName, // TODO: Change to IApplication +owner, provider, authorizer, authorization) { + const { ethers, helpers } = hre; + const ownerAddress = ethers.getAddress(owner); + const providerAddress = ethers.getAddress(provider); + const application = await helpers.contracts.getContract(deploymentName); + console.log(`Authorizing provider's ${providerAddress} stake in ${deploymentName} application (${await application.getAddress()})`); + // Authorizer can equal to the owner if not set otherwise. This simplification + // is used for development purposes. + const authorizerAddress = authorizer + ? ethers.getAddress(authorizer) + : ownerAddress; + const { to1e18, from1e18 } = helpers.number; + const staking = await helpers.contracts.getContract("TokenStaking"); + const authorizationBN = authorization + ? to1e18(authorization) + : await application.minimumAuthorization(); + const currentAuthorization = await staking.authorizedStake(providerAddress, await application.getAddress()); + if (currentAuthorization >= authorizationBN) { + console.log(`Authorized stake is already ${from1e18(currentAuthorization)} T`); + return; + } + const increaseAmount = authorizationBN - currentAuthorization; + console.log(`Increasing authorization by ${from1e18(increaseAmount)} T to ${from1e18(authorizationBN)} T...`); + await (await staking + .connect(await ethers.getSigner(authorizerAddress)) + .getFunction("increaseAuthorization")(providerAddress, await application.getAddress(), increaseAmount)).wait(); +} diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/utils/ether.js b/solidity/ecdsa/external/random-beacon-export/tasks/utils/ether.js new file mode 100644 index 0000000000..32ef8f4aef --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/utils/ether.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseValue = parseValue; +// eslint-disable-next-line import/prefer-default-export +function parseValue(value, hre) { + const parsed = String(value).trim().split(" "); + if (parsed.length === 0 || parsed.length > 2) { + throw new Error(`invalid value: ${value}`); + } + return hre.ethers.parseUnits(parsed[0], parsed[1] || "wei"); +} diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/utils/index.js b/solidity/ecdsa/external/random-beacon-export/tasks/utils/index.js new file mode 100644 index 0000000000..0c2f16611d --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/utils/index.js @@ -0,0 +1,22 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./authorize"), exports); +__exportStar(require("./ether"), exports); +__exportStar(require("./mint"), exports); +__exportStar(require("./register"), exports); +__exportStar(require("./stake"), exports); +__exportStar(require("./add_beta_operator"), exports); diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/utils/mint.js b/solidity/ecdsa/external/random-beacon-export/tasks/utils/mint.js new file mode 100644 index 0000000000..043b7d751b --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/utils/mint.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.mint = mint; +// eslint-disable-next-line import/prefer-default-export +async function mint(hre, owner, amount) { + const { ethers, helpers } = hre; + const { to1e18, from1e18 } = helpers.number; + const ownerAddress = ethers.getAddress(owner); + const stakeAmount = to1e18(amount); + const t = await helpers.contracts.getContract("T"); + const staking = await helpers.contracts.getContract("TokenStaking"); + const tokenContractOwner = await t.owner(); + const currentBalance = await t.balanceOf(ownerAddress); + console.log(`Account ${ownerAddress} balance is ${from1e18(currentBalance)} T`); + if (currentBalance < stakeAmount) { + const mintAmount = stakeAmount - currentBalance; + console.log(`Minting ${from1e18(mintAmount)} T for ${ownerAddress}...`); + await (await t + .connect(await ethers.getSigner(tokenContractOwner)) + .getFunction("mint")(ownerAddress, mintAmount)).wait(); + } + const currentAllowance = await t.allowance(ownerAddress, await staking.getAddress()); + console.log(`Account ${ownerAddress} allowance for ${await staking.getAddress()} is ${from1e18(currentAllowance)} T`); + if (currentAllowance < stakeAmount) { + console.log(`Approving ${from1e18(stakeAmount)} T for ${await staking.getAddress()}...`); + await (await t + .connect(await ethers.getSigner(ownerAddress)) + .getFunction("approve")(await staking.getAddress(), stakeAmount)).wait(); + } +} diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/utils/register.js b/solidity/ecdsa/external/random-beacon-export/tasks/utils/register.js new file mode 100644 index 0000000000..9415824ba9 --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/utils/register.js @@ -0,0 +1,28 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.register = register; +// eslint-disable-next-line import/prefer-default-export +async function register(hre, deploymentName, provider, operator) { + const { ethers, helpers } = hre; + const providerAddress = ethers.getAddress(provider); + const operatorAddress = ethers.getAddress(operator); + const application = await helpers.contracts.getContract(deploymentName); + console.log(`Registering operator ${operatorAddress} in ${deploymentName} application (${await application.getAddress()})`); + const currentProvider = ethers.getAddress(await application.operatorToStakingProvider.staticCall(operatorAddress)); + switch (currentProvider) { + case providerAddress: { + console.log(`Current staking provider for operator ${operatorAddress} is ${currentProvider}`); + return; + } + case ethers.ZeroAddress: { + console.log(`Registering operator ${operatorAddress} for a staking provider ${providerAddress}...`); + await (await application + .connect(await ethers.getSigner(providerAddress)) + .getFunction("registerOperator")(operatorAddress)).wait(); + break; + } + default: { + throw new Error(`Operator [${operatorAddress}] has already been registered for another staking provider [${currentProvider}]`); + } + } +} diff --git a/solidity/ecdsa/external/random-beacon-export/tasks/utils/stake.js b/solidity/ecdsa/external/random-beacon-export/tasks/utils/stake.js new file mode 100644 index 0000000000..0098dbac75 --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/tasks/utils/stake.js @@ -0,0 +1,48 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.stake = stake; +exports.calculateTokensNeededForStake = calculateTokensNeededForStake; +async function stake(hre, owner, provider, amount, beneficiary, authorizer) { + const { ethers, helpers } = hre; + const { to1e18, from1e18 } = helpers.number; + const ownerAddress = ethers.getAddress(owner); + const providerAddress = ethers.getAddress(provider); + const stakeAmount = to1e18(amount); + // Beneficiary can equal to the owner if not set otherwise. This simplification + // is used for development purposes. + const beneficiaryAddress = beneficiary + ? ethers.getAddress(beneficiary) + : ownerAddress; + // Authorizer can equal to the owner if not set otherwise. This simplification + // is used for development purposes. + const authorizerAddress = authorizer + ? ethers.getAddress(authorizer) + : ownerAddress; + const staking = await helpers.contracts.getContract("TokenStaking"); + const { tStake: currentStake } = await staking.stakes.staticCall(providerAddress); + console.log(`Current stake for ${providerAddress} is ${from1e18(currentStake)} T`); + if (currentStake === 0n) { + console.log(`Staking ${from1e18(stakeAmount)} T to the staking provider ${providerAddress}...`); + await (await staking + .connect(await ethers.getSigner(ownerAddress)) + .getFunction("stake")(providerAddress, beneficiaryAddress, authorizerAddress, stakeAmount)).wait(); + } + else if (currentStake < stakeAmount) { + const topUpAmount = stakeAmount - currentStake; + console.log(`Topping up ${from1e18(topUpAmount)} T to the staking provider ${providerAddress}...`); + await (await staking + .connect(await ethers.getSigner(ownerAddress)) + .getFunction("topUp")(providerAddress, topUpAmount)).wait(); + } +} +async function calculateTokensNeededForStake(hre, provider, amount) { + const { ethers, helpers } = hre; + const { to1e18, from1e18 } = helpers.number; + const stakeAmount = to1e18(amount); + const staking = await helpers.contracts.getContract("TokenStaking"); + const { tStake: currentStake } = await staking.stakes.staticCall(provider); + if (currentStake < stakeAmount) { + return BigInt(from1e18(stakeAmount - currentStake)); + } + return 0n; +} diff --git a/solidity/ecdsa/external/random-beacon-export/utils/wait-for-confirmations.js b/solidity/ecdsa/external/random-beacon-export/utils/wait-for-confirmations.js new file mode 100644 index 0000000000..df31cc60d3 --- /dev/null +++ b/solidity/ecdsa/external/random-beacon-export/utils/wait-for-confirmations.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = waitForConfirmations; +/** Wait through the transaction response; Hardhat's ethers v6 provider does not implement waitForTransaction. */ +async function waitForConfirmations(provider, transactionHash, confirmations = 2, timeout = 300000) { + const pollInterval = 2000; + const deadline = Date.now() + timeout; + // ethers v5 waitForTransaction polled, so a load-balanced endpoint that does + // not see the just-mined transaction yet must not fail the deployment. + let transaction = await provider.getTransaction(transactionHash); + while (!transaction) { + const remaining = deadline - Date.now(); + if (remaining <= 0) { + throw new Error(`Deployment transaction ${transactionHash} was not found`); + } + await new Promise((resolve) => { + setTimeout(resolve, Math.min(pollInterval, remaining)); + }); + transaction = await provider.getTransaction(transactionHash); + } + const receipt = await transaction.wait(confirmations, Math.max(deadline - Date.now(), 1)); + if (!receipt) { + throw new Error(`Deployment transaction ${transactionHash} is not confirmed`); + } + return receipt; +} diff --git a/solidity/ecdsa/hardhat.config.ts b/solidity/ecdsa/hardhat.config.ts index 7a1026bb7b..0db596df18 100644 --- a/solidity/ecdsa/hardhat.config.ts +++ b/solidity/ecdsa/hardhat.config.ts @@ -5,6 +5,7 @@ import fs from "fs" import path from "path" +import "@nomicfoundation/hardhat-ethers" import "@nomicfoundation/hardhat-chai-matchers" import "@nomicfoundation/hardhat-verify" import "@keep-network/hardhat-helpers" @@ -12,7 +13,7 @@ import "@keep-network/hardhat-local-networks-config" import "@openzeppelin/hardhat-upgrades" import "@typechain/hardhat" import "hardhat-deploy" -import "@tenderly/hardhat-tenderly" +import { setup as setupTenderly } from "@tenderly/hardhat-tenderly" import "hardhat-contract-sizer" import "hardhat-dependency-compiler" import "hardhat-gas-reporter" @@ -22,37 +23,15 @@ import "./tasks" import { task } from "hardhat/config" import { TASK_TEST } from "hardhat/builtin-tasks/task-names" +import resolveRandomBeaconExport from "./utils/random-beacon-export" + import type { HardhatUserConfig } from "hardhat/config" const TASK_CHECK_ACCOUNTS_COUNT = "check-accounts-count" const hardhatVerifyEnabled = process.env.DISABLE_HARDHAT_VERIFY !== "true" -/** - * Random-beacon `export/` is gitignored in the random-beacon package, so CI never - * has ../random-beacon/export. Prefer committed `external/random-beacon-export/deploy` - * (mirrors npm export scripts with a fixed 05_approve_*) before falling back to node_modules. - */ -function resolveRandomBeaconExport(subdir: "deploy" | "artifacts"): string { - const local = path.join(__dirname, "../random-beacon/export", subdir) - if (fs.existsSync(local)) { - return local - } - if (subdir === "deploy") { - const bundledDeploy = path.join( - __dirname, - "external/random-beacon-export/deploy", - ) - if (fs.existsSync(bundledDeploy)) { - return bundledDeploy - } - } - return path.join( - __dirname, - "node_modules/@keep-network/random-beacon/export", - subdir, - ) -} +setupTenderly({ automaticVerifications: false }) const thresholdSolidityCompilerConfig = { version: "0.8.9", @@ -273,7 +252,7 @@ const config: HardhatUserConfig = { timeout: 60000, }, typechain: { - target: "ethers-v5", + target: "ethers-v6", outDir: "typechain", }, docgen: { diff --git a/solidity/ecdsa/package.json b/solidity/ecdsa/package.json index 4946548bf2..8da1f08629 100644 --- a/solidity/ecdsa/package.json +++ b/solidity/ecdsa/package.json @@ -11,7 +11,10 @@ "!**/test/", "deploy/", "export/", + "external/random-beacon-export/", "tasks/", + "types/random-beacon.d.ts", + "utils/", "export.json" ], "scripts": { @@ -34,19 +37,20 @@ "deploy": "hardhat deploy --export export.json", "deploy:test": "USE_EXTERNAL_DEPLOY=true TEST_USE_STUBS_ECDSA=true hardhat deploy", "prepack": "tsc -p tsconfig.export.json && hardhat export-artifacts --including-no-public-functions export/artifacts", - "prepublishOnly": "hardhat prepare-artifacts --network $npm_config_network" + "prepublishOnly": "hardhat export-deployment-artifacts --network \"${npm_config_network:-hardhat}\"" }, "devDependencies": { - "@keep-network/hardhat-helpers": "github:threshold-network/hardhat-helpers#v0.6.0-pre.21", + "@keep-network/hardhat-helpers": "patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch", "@keep-network/hardhat-local-networks-config": "github:threshold-network/hardhat-local-networks-config#6dff5bc8648127ca5d8696c321076bddb6d4142a", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", + "@nomicfoundation/hardhat-chai-matchers": "^2.1.2", + "@nomicfoundation/hardhat-ethers": "^3.1.3", + "@nomicfoundation/hardhat-network-helpers": "^1.1.2", "@nomicfoundation/hardhat-verify": "^2.1.3", - "@nomiclabs/hardhat-ethers": "^2.0.6", - "@openzeppelin/hardhat-upgrades": "^1.20.4", + "@openzeppelin/hardhat-upgrades": "patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch", "@stylistic/eslint-plugin": "^5.10.0", - "@tenderly/hardhat-tenderly": ">=1.0.13 <1.2.0", - "@typechain/ethers-v5": "^11.1.2", - "@typechain/hardhat": "^7.0.0", + "@tenderly/hardhat-tenderly": "2.1.1", + "@typechain/ethers-v6": "patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch", + "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.3.20", "@types/chai-as-promised": "^7.1.5", "@types/mocha": "^10.0.10", @@ -58,7 +62,7 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-import-x": "^4.17.1", "eslint-plugin-no-only-tests": "^3.4.0", - "ethers": "^5.5.3", + "ethers": "^6.17.0", "fs-extra": "^11.2.0", "globals": "^17.12.0", "hardhat": "2.29.0", @@ -77,7 +81,7 @@ "typescript-eslint": "^8.70.0" }, "dependencies": { - "@keep-network/random-beacon": "development", + "@keep-network/random-beacon": "2.1.0-dev.18", "@keep-network/sortition-pools": "^2.0.0-pre.16", "@openzeppelin/contracts": "^4.9.6", "@openzeppelin/contracts-upgradeable": "^4.9.6", @@ -87,8 +91,10 @@ "node": ">=24.0.0" }, "resolutions": { + "axios": "^1.8.4", "ethereumjs-abi": "npm:0.6.8", - "get-func-name": "^2.0.2" + "get-func-name": "^2.0.2", + "@threshold-network/solidity-contracts@npm:1.3.0-dev.14": "patch:@threshold-network/solidity-contracts@npm%3A1.3.0-dev.14#./.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch" }, "packageManager": "yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8" } diff --git a/solidity/ecdsa/scripts/consolidate_beta_stakers.ts b/solidity/ecdsa/scripts/consolidate_beta_stakers.ts index 5b8fb8fbb9..3a6539cfbc 100644 --- a/solidity/ecdsa/scripts/consolidate_beta_stakers.ts +++ b/solidity/ecdsa/scripts/consolidate_beta_stakers.ts @@ -115,12 +115,12 @@ program try { const weight = await allowlist.authorizedStake( operator, - ethers.constants.AddressZero, + ethers.ZeroAddress, ) const entity = ENTITY_MAPPINGS[operator.toLowerCase()] || "UNKNOWN" currentStates[operator] = { - weight: ethers.utils.formatEther(weight), + weight: ethers.formatEther(weight), entity, } @@ -128,9 +128,7 @@ program ? "→ CONSOLIDATE" : "✅ KEEP" console.log( - `${operator} (${entity}): ${ethers.utils.formatEther( - weight, - )} T ${status}`, + `${operator} (${entity}): ${ethers.formatEther(weight)} T ${status}`, ) } catch (error: any) { console.error(`❌ Error checking ${operator}: ${error.message}`) @@ -222,7 +220,7 @@ program const providerInfo = await allowlist.stakingProviders(operator) const pendingWeight = providerInfo.pendingNewWeight - if (pendingWeight.eq(0)) { + if (pendingWeight === 0n) { console.log(`✅ ${operator}: Pending decrease to 0`) } else { console.log(`⚠️ ${operator}: No pending decrease found`) @@ -311,7 +309,7 @@ program const entity = ENTITY_MAPPINGS[operator.toLowerCase()] || "UNKNOWN" const weight = await allowlist.authorizedStake( operator, - ethers.constants.AddressZero, + ethers.ZeroAddress, ) const providerInfo = await allowlist.stakingProviders(operator) const pendingWeight = providerInfo.pendingNewWeight @@ -319,12 +317,13 @@ program const status = OPERATORS_TO_CONSOLIDATE.includes(operator) ? "CONSOLIDATE" : "KEEP" - const pending = pendingWeight.gt(0) - ? ` (pending: ${ethers.utils.formatEther(pendingWeight)})` - : "" + const pending = + pendingWeight > 0n + ? ` (pending: ${ethers.formatEther(pendingWeight)})` + : "" console.log(`${operator} (${entity})`) - console.log(` Weight: ${ethers.utils.formatEther(weight)} T${pending}`) + console.log(` Weight: ${ethers.formatEther(weight)} T${pending}`) console.log(` Plan: ${status}`) } }) diff --git a/solidity/ecdsa/tasks/index.ts b/solidity/ecdsa/tasks/index.ts index ed30fceb50..e827e04de6 100644 --- a/solidity/ecdsa/tasks/index.ts +++ b/solidity/ecdsa/tasks/index.ts @@ -1,3 +1,2 @@ import "./initialize-wallet-owner" import "./initialize" -import "@keep-network/random-beacon/export/tasks/unlock-eth-accounts" diff --git a/solidity/ecdsa/tasks/initialize-wallet-owner.ts b/solidity/ecdsa/tasks/initialize-wallet-owner.ts index c97ab48c6e..152ba8a2a6 100644 --- a/solidity/ecdsa/tasks/initialize-wallet-owner.ts +++ b/solidity/ecdsa/tasks/initialize-wallet-owner.ts @@ -18,9 +18,9 @@ async function initializeWalletOwner( const { getNamedAccounts, ethers, deployments, helpers } = hre const { read, execute } = deployments const { deployer, governance } = await getNamedAccounts() - const ZERO = ethers.constants.AddressZero + const ZERO = ethers.ZeroAddress - if (!ethers.utils.isAddress(walletOwnerAddress)) { + if (!ethers.isAddress(walletOwnerAddress)) { throw Error(`invalid address: ${walletOwnerAddress}`) } diff --git a/solidity/ecdsa/tasks/initialize.ts b/solidity/ecdsa/tasks/initialize.ts index 0d188bac29..014cd63431 100644 --- a/solidity/ecdsa/tasks/initialize.ts +++ b/solidity/ecdsa/tasks/initialize.ts @@ -1,16 +1,15 @@ import { task, types } from "hardhat/config" + import { TASK_INITIALIZE, TASK_AUTHORIZE, TASK_REGISTER, TASK_INITIALIZE_STAKING, TASK_ADD_BETA_OPERATOR, -} from "@keep-network/random-beacon/export/tasks/initialize" -import { authorize, register, addBetaOperator, -} from "@keep-network/random-beacon/export/tasks/utils" +} from "./random-beacon" // Tasks for the ECDSA application. const TASK_INITIALIZE_ECDSA = `${TASK_INITIALIZE}:ecdsa` diff --git a/solidity/ecdsa/tasks/random-beacon.ts b/solidity/ecdsa/tasks/random-beacon.ts new file mode 100644 index 0000000000..7121d2bfd7 --- /dev/null +++ b/solidity/ecdsa/tasks/random-beacon.ts @@ -0,0 +1,23 @@ +import { createRequire } from "module" +import path from "path" + +import resolveRandomBeaconExport from "../utils/random-beacon-export" + +import type { InitializationTasks, TaskUtils } from "../types/random-beacon" + +const requireBeaconTask = createRequire( + path.join(resolveRandomBeaconExport("tasks"), "initialize.js"), +) + +export const { + TASK_INITIALIZE, + TASK_INITIALIZE_STAKING, + TASK_AUTHORIZE, + TASK_REGISTER, + TASK_ADD_BETA_OPERATOR, +}: InitializationTasks = requireBeaconTask("./initialize") + +export const { authorize, register, addBetaOperator }: TaskUtils = + requireBeaconTask("./utils") + +requireBeaconTask("./unlock-eth-accounts") diff --git a/solidity/ecdsa/test/Allowlist.test.ts b/solidity/ecdsa/test/Allowlist.test.ts index 75f4d0505c..56f68f3a82 100644 --- a/solidity/ecdsa/test/Allowlist.test.ts +++ b/solidity/ecdsa/test/Allowlist.test.ts @@ -5,12 +5,12 @@ import { expect } from "chai" import { createMock, expectCalledWith } from "./helpers/mock" import type { Mock } from "./helpers/mock" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { Allowlist, WalletRegistry } from "../typechain" const { createSnapshot, restoreSnapshot } = helpers.snapshot -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress describe("Allowlist", () => { let allowlist: Allowlist @@ -44,7 +44,7 @@ describe("Allowlist", () => { // approveAuthorizationDecrease which checks msg.sender == walletRegistry). await governance.sendTransaction({ to: walletRegistry.address, - value: ethers.utils.parseEther("10"), + value: ethers.parseEther("10"), }) // Deploy Allowlist proxy using ERC1967Proxy directly instead of @@ -58,15 +58,18 @@ describe("Allowlist", () => { // call deployments.fixture(). const AllowlistFactory = await ethers.getContractFactory("Allowlist") const impl = await AllowlistFactory.deploy() - await impl.deployed() + await impl.waitForDeployment() const initData = AllowlistFactory.interface.encodeFunctionData( "initialize", [walletRegistry.address], ) const ERC1967ProxyFactory = await ethers.getContractFactory("ERC1967Proxy") - const proxy = await ERC1967ProxyFactory.deploy(impl.address, initData) - await proxy.deployed() - allowlist = AllowlistFactory.attach(proxy.address) as Allowlist + const proxy = await ERC1967ProxyFactory.deploy( + await impl.getAddress(), + initData, + ) + await proxy.waitForDeployment() + allowlist = AllowlistFactory.attach(await proxy.getAddress()) as Allowlist }) describe("initialization", () => { @@ -87,22 +90,23 @@ describe("Allowlist", () => { it("should revert if initialized with zero address", async () => { const AllowlistFactory = await ethers.getContractFactory("Allowlist") const impl = await AllowlistFactory.deploy() - await impl.deployed() + await impl.waitForDeployment() const initData = AllowlistFactory.interface.encodeFunctionData( "initialize", [ZERO_ADDRESS], ) const ERC1967ProxyFactory = await ethers.getContractFactory("ERC1967Proxy") - await expect(ERC1967ProxyFactory.deploy(impl.address, initData)).to.be - .reverted + await expect( + ERC1967ProxyFactory.deploy(await impl.getAddress(), initData), + ).to.be.reverted }) }) describe("addStakingProvider", () => { context("when called by the owner", () => { it("should add a new staking provider with the specified weight", async () => { - const weight = ethers.utils.parseEther("40000") // 40k T equivalent + const weight = ethers.parseEther("40000") // 40k T equivalent await expect( allowlist @@ -120,7 +124,7 @@ describe("Allowlist", () => { }) it("should call authorizationIncreased on WalletRegistry", async () => { - const weight = ethers.utils.parseEther("50000") + const weight = ethers.parseEther("50000") await allowlist .connect(governance) @@ -134,7 +138,7 @@ describe("Allowlist", () => { }) it("should revert if staking provider already exists", async () => { - const weight = ethers.utils.parseEther("40000") + const weight = ethers.parseEther("40000") await allowlist .connect(governance) @@ -148,7 +152,7 @@ describe("Allowlist", () => { }) it("should revert if staking provider is zero address", async () => { - const weight = ethers.utils.parseEther("40000") + const weight = ethers.parseEther("40000") await expect( allowlist @@ -168,7 +172,7 @@ describe("Allowlist", () => { context("when called by non-owner", () => { it("should revert", async () => { - const weight = ethers.utils.parseEther("40000") + const weight = ethers.parseEther("40000") await expect( allowlist @@ -180,7 +184,7 @@ describe("Allowlist", () => { }) describe("requestWeightDecrease", () => { - const initialWeight = ethers.utils.parseEther("50000") + const initialWeight = ethers.parseEther("50000") beforeEach(async () => { // Add a staking provider first @@ -191,7 +195,7 @@ describe("Allowlist", () => { context("when called by the owner", () => { it("should request weight decrease for existing provider", async () => { - const newWeight = ethers.utils.parseEther("30000") + const newWeight = ethers.parseEther("30000") await expect( allowlist @@ -209,7 +213,7 @@ describe("Allowlist", () => { }) it("should call authorizationDecreaseRequested on WalletRegistry", async () => { - const newWeight = ethers.utils.parseEther("30000") + const newWeight = ethers.parseEther("30000") await allowlist .connect(governance) @@ -240,8 +244,8 @@ describe("Allowlist", () => { }) it("should overwrite pending weight decrease request", async () => { - const firstNewWeight = ethers.utils.parseEther("30000") - const secondNewWeight = ethers.utils.parseEther("20000") + const firstNewWeight = ethers.parseEther("30000") + const secondNewWeight = ethers.parseEther("20000") await allowlist .connect(governance) @@ -257,7 +261,7 @@ describe("Allowlist", () => { }) it("should revert if staking provider is unknown", async () => { - const newWeight = ethers.utils.parseEther("30000") + const newWeight = ethers.parseEther("30000") await expect( allowlist @@ -273,7 +277,7 @@ describe("Allowlist", () => { .requestWeightDecrease(stakingProvider1.address, initialWeight), ).to.be.reverted - const higherWeight = ethers.utils.parseEther("60000") + const higherWeight = ethers.parseEther("60000") await expect( allowlist .connect(governance) @@ -284,7 +288,7 @@ describe("Allowlist", () => { context("when called by non-owner", () => { it("should revert", async () => { - const newWeight = ethers.utils.parseEther("30000") + const newWeight = ethers.parseEther("30000") await expect( allowlist @@ -296,8 +300,8 @@ describe("Allowlist", () => { }) describe("approveAuthorizationDecrease", () => { - const initialWeight = ethers.utils.parseEther("50000") - const newWeight = ethers.utils.parseEther("30000") + const initialWeight = ethers.parseEther("50000") + const newWeight = ethers.parseEther("30000") beforeEach(async () => { // Add a staking provider and request weight decrease @@ -329,7 +333,7 @@ describe("Allowlist", () => { it("should return the new weight", async () => { const result = await allowlist .connect(walletRegistry.wallet) - .callStatic.approveAuthorizationDecrease(stakingProvider1.address) + .approveAuthorizationDecrease.staticCall(stakingProvider1.address) expect(result).to.equal(newWeight) }) @@ -368,7 +372,7 @@ describe("Allowlist", () => { }) describe("authorizedStake", () => { - const weight = ethers.utils.parseEther("40000") + const weight = ethers.parseEther("40000") beforeEach(async () => { await allowlist @@ -414,7 +418,7 @@ describe("Allowlist", () => { await expect( allowlist.seize( - ethers.utils.parseEther("1000"), // amount (ignored) + ethers.parseEther("1000"), // amount (ignored) 100, // rewardMultiplier (ignored) thirdParty.address, // notifier stakingProviders, @@ -431,7 +435,7 @@ describe("Allowlist", () => { allowlist .connect(thirdParty) .seize( - ethers.utils.parseEther("500"), + ethers.parseEther("500"), 50, governance.address, stakingProviders, @@ -466,7 +470,7 @@ describe("Allowlist", () => { it("should support beta staker consolidation workflow", async () => { // Add multiple staking providers (simulating existing beta stakers) const providers = [stakingProvider1.address, stakingProvider2.address] - const initialWeight = ethers.utils.parseEther("40000") + const initialWeight = ethers.parseEther("40000") for (const provider of providers) { await allowlist diff --git a/solidity/ecdsa/test/DKGValidator.test.ts b/solidity/ecdsa/test/DKGValidator.test.ts index d466cee835..843fd7d303 100644 --- a/solidity/ecdsa/test/DKGValidator.test.ts +++ b/solidity/ecdsa/test/DKGValidator.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-await-in-loop */ -import { BigNumber } from "ethers" + import { ethers, helpers } from "hardhat" import { expect } from "chai" @@ -26,13 +26,11 @@ import type { Operator } from "./utils/operators" const { createSnapshot, restoreSnapshot } = helpers.snapshot describe("EcdsaDkgValidator", () => { - const dkgSeed: BigNumber = BigNumber.from( + const dkgSeed = BigInt( "31415926535897932384626433832795028841971693993751058209749445923078164062862", ) const dkgStartBlock = 1337 - const groupPublicKey: string = ethers.utils.hexValue( - ecdsaData.group1.publicKey, - ) + const groupPublicKey: string = ethers.toQuantity(ecdsaData.group1.publicKey) let selectedOperators: Operator[] @@ -702,8 +700,8 @@ describe("EcdsaDkgValidator", () => { context("when signatures contain wrong result hash", () => { const signWithWrongResultHash = async (signingOperators: Operator[]) => { - const wrongResultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const wrongResultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( ["uint256", "bytes", "uint8[]", "uint256"], [ hardhatNetworkId, @@ -717,11 +715,11 @@ describe("EcdsaDkgValidator", () => { for (let i = 0; i < signingOperators.length; i++) { const { signer: ethersSigner } = signingOperators[i] const signature = await ethersSigner.signMessage( - ethers.utils.arrayify(wrongResultHash), + ethers.getBytes(wrongResultHash), ) signatures.push(signature) } - const signaturesBytes = ethers.utils.hexConcat(signatures) + const signaturesBytes = ethers.concat(signatures) return signaturesBytes } diff --git a/solidity/ecdsa/test/WalletRegistry.Authorization.test.ts b/solidity/ecdsa/test/WalletRegistry.Authorization.test.ts index f1810cf962..11a446c580 100644 --- a/solidity/ecdsa/test/WalletRegistry.Authorization.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Authorization.test.ts @@ -22,16 +22,16 @@ import type { IStaking, } from "../typechain" import type { Mock } from "./helpers/mock" -import type { ContractTransaction } from "ethers" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { ContractTransactionResponse } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" const { mineBlocks } = helpers.time const { to1e18 } = helpers.number const { createSnapshot, restoreSnapshot } = helpers.snapshot -const ZERO_ADDRESS = ethers.constants.AddressZero -const MAX_UINT64 = ethers.BigNumber.from("18446744073709551615") // 2^64 - 1 +const ZERO_ADDRESS = ethers.ZeroAddress +const MAX_UINT64 = BigInt("18446744073709551615") // 2^64 - 1 /* * LEGACY TESTS DEPRECATED - TIP-092 Migration @@ -99,7 +99,7 @@ async function setupRealStaking( amount: any, ): Promise { await t.connect(deployer).mint(stakingProvider.address, amount) - await t.connect(stakingProvider).approve(staking.address, amount) + await t.connect(stakingProvider).approve(await staking.getAddress(), amount) await legacyTokenStakingAt(staking, stakingProvider).stake( stakingProvider.address, beneficiary.address, @@ -108,7 +108,7 @@ async function setupRealStaking( ) await legacyTokenStakingAt(staking, stakingProvider).increaseAuthorization( stakingProvider.address, - walletRegistry.address, + await walletRegistry.getAddress(), amount, ) } @@ -288,7 +288,7 @@ describe("WalletRegistry - Authorization", () => { await ethers.getSigners() )[0].sendTransaction({ to: slasher.address, - value: ethers.utils.parseEther("100"), + value: ethers.parseEther("100"), }) }) @@ -364,7 +364,7 @@ describe("WalletRegistry - Authorization", () => { // the staking provider, and the staking provider is registering operator // for ECDSA application. context("when staking provider is registering new operator", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -457,7 +457,7 @@ describe("WalletRegistry - Authorization", () => { // approving that authorization decrease request, staking provider can // register an operator. context("when authorization decrease request was approved", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -549,7 +549,7 @@ describe("WalletRegistry - Authorization", () => { // Minimum possible authorization - the minimum authorized amount for // ECDSA as set in `minimumAuthorization` parameter. context("when increasing to the minimum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -581,7 +581,7 @@ describe("WalletRegistry - Authorization", () => { // Maximum possible authorization - the entire stake delegated to the // staking provider. context("when increasing to the maximum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -627,7 +627,7 @@ describe("WalletRegistry - Authorization", () => { // Minimum possible authorization - the minimum authorized amount for // ECDSA as set in `minimumAuthorization` parameter. context("when increasing to the minimum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -660,7 +660,7 @@ describe("WalletRegistry - Authorization", () => { // Maximum possible authorization - the entire stake delegated to the // staking provider. context("when increasing to the maximum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -748,7 +748,7 @@ describe("WalletRegistry - Authorization", () => { // Decreasing to zero when operator was not set up yet - authorization // decrease request is valid and can be approved context("when decreasing to zero", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse const decreasingTo = 0 let decreasingBy @@ -800,7 +800,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when decreasing to the minimum", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let decreasingTo let decreasingBy @@ -853,7 +853,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when decreasing to a value above the minimum", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let decreasingTo let decreasingBy @@ -1177,7 +1177,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when decreasing to zero", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse const decreasingTo = 0 let decreasingBy @@ -1228,7 +1228,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when decreasing to the minimum", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let decreasingTo let decreasingBy @@ -1280,7 +1280,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when decreasing to a value above the minimum", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let decreasingTo let decreasingBy @@ -1901,7 +1901,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when the pool was updated and the delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1954,7 +1954,7 @@ describe("WalletRegistry - Authorization", () => { context("when the operator is unknown", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2013,7 +2013,7 @@ describe("WalletRegistry - Authorization", () => { context("when the operator is not in the sortition pool", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2055,7 +2055,7 @@ describe("WalletRegistry - Authorization", () => { context("when the sortition pool is locked", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2094,7 +2094,7 @@ describe("WalletRegistry - Authorization", () => { context("when the sortition pool is not locked", () => { context("when the authorization drops to above the minimum", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2226,7 +2226,7 @@ describe("WalletRegistry - Authorization", () => { ) context("when the operator has the minimum stake authorized", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2464,7 +2464,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when the authorization increased", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2499,7 +2499,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when there was an authorization decrease request", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2575,7 +2575,7 @@ describe("WalletRegistry - Authorization", () => { }) context("when the authorization increased", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let expectedWeight before(async () => { @@ -2623,7 +2623,7 @@ describe("WalletRegistry - Authorization", () => { context( "when there was an authorization decrease request to non-zero", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let expectedWeight before(async () => { @@ -2679,7 +2679,7 @@ describe("WalletRegistry - Authorization", () => { context( "when there was an authorization decrease request to zero", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2729,7 +2729,7 @@ describe("WalletRegistry - Authorization", () => { context( "when operator is in the process of deauthorizing but also increased authorization in the meantime", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let expectedWeight before(async () => { @@ -3040,7 +3040,7 @@ describe("WalletRegistry - Authorization", () => { stakingProvider.address ) ).to.be.closeTo( - ethers.BigNumber.from(params.authorizationDecreaseDelay / 2), + BigInt(params.authorizationDecreaseDelay / 2), 5 // +- 5sec ) }) @@ -3977,7 +3977,7 @@ describe("WalletRegistry - Migration Scenario Tests (TIP-092)", () => { walletRegistry, allowlist.address, stakingProvider.address, - ethers.BigNumber.from(0), + 0n, minimumAuthorization, ), ).to.not.be.reverted @@ -4021,7 +4021,7 @@ describe("WalletRegistry - Migration Scenario Tests (TIP-092)", () => { walletRegistry, allowlist.address, stakingProvider.address, - ethers.BigNumber.from(0), + 0n, minimumAuthorization, ) diff --git a/solidity/ecdsa/test/WalletRegistry.CustomErrors.test.ts b/solidity/ecdsa/test/WalletRegistry.CustomErrors.test.ts index 69e0b2c3ba..a63f5954d3 100644 --- a/solidity/ecdsa/test/WalletRegistry.CustomErrors.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.CustomErrors.test.ts @@ -22,12 +22,12 @@ import type { WalletRegistryGovernance, } from "../typechain" import type { Mock } from "./helpers/mock" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" const { to1e18 } = helpers.number const { createSnapshot, restoreSnapshot } = helpers.snapshot -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress describe.skip("TokenStaking Integration (DEPRECATED TIP-092)", () => { /** @@ -172,13 +172,13 @@ describe("WalletRegistry - Custom Errors", () => { }) it("should revert with custom error when unauthorized caller attempts closeWallet", async () => { - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") await expect(walletRegistry.connect(unauthorized).closeWallet(walletID)) .to.be.reverted }) it("should revert with custom error when unauthorized caller attempts seize", async () => { - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const walletMembersIDs = [1, 2, 3] await expect( walletRegistry @@ -233,15 +233,15 @@ describe("WalletRegistry - Custom Errors", () => { "WalletRegistry", { libraries: { - EcdsaInactivity: EcdsaInactivity.address, + EcdsaInactivity: await EcdsaInactivity.getAddress(), }, }, ) const newImplementation = await WalletRegistryFactory.deploy( - sortitionPool.address, - staking.address, + await sortitionPool.getAddress(), + await staking.getAddress(), ) - await newImplementation.deployed() + await newImplementation.waitForDeployment() await expect(newImplementation.initializeV2(ZERO_ADDRESS)).to.be .reverted @@ -276,7 +276,7 @@ describe("WalletRegistry - Custom Errors", () => { it("should revert with custom error when notifyOperatorInactivity called with wrong nonce", async () => { // This test requires a wallet to be created first // For simplicity, we test the nonce check with a mock claim - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const wrongNonce = 999 // Expected nonce is 0 initially const claim = { @@ -311,7 +311,7 @@ describe("WalletRegistry - Custom Errors", () => { it("should revert with custom error when notifyOperatorInactivity called with invalid group members", async () => { // This test requires a wallet with stored members hash // We'll test with a mock scenario where hash doesn't match - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const nonce = 0 const claim = { @@ -335,7 +335,7 @@ describe("WalletRegistry - Custom Errors", () => { describe("InvalidWalletMembersIdentifiers", () => { it("should revert with custom error when seize called with invalid wallet members hash", async () => { - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const invalidWalletMembersIDs = [1, 2, 3] await expect( @@ -352,7 +352,7 @@ describe("WalletRegistry - Custom Errors", () => { }) it("should revert with custom error when isWalletMember called with invalid wallet members hash", async () => { - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const invalidWalletMembersIDs = [1, 2, 3] await expect( @@ -368,7 +368,7 @@ describe("WalletRegistry - Custom Errors", () => { describe("NotSortitionPoolOperator", () => { it("should revert with custom error when isWalletMember called with non-sortition pool operator", async () => { - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const walletMembersIDs = [1, 2, 3] const nonOperator = unauthorized.address @@ -397,7 +397,7 @@ describe("WalletRegistry - Custom Errors", () => { }) it("should revert with custom error when isWalletMember called with index zero", async () => { - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const walletMembersIDs = [1, 2, 3] await expect( @@ -411,7 +411,7 @@ describe("WalletRegistry - Custom Errors", () => { }) it("should revert with custom error when isWalletMember called with index exceeding array length", async () => { - const walletID = ethers.utils.formatBytes32String("test-wallet") + const walletID = ethers.encodeBytes32String("test-wallet") const walletMembersIDs = [1, 2, 3] await expect( @@ -476,15 +476,15 @@ describe("WalletRegistry - Custom Errors", () => { // Creating a mock DKG result for testing const dkgResult = { submitterMemberIndex: 1, - groupPubKey: ethers.utils.hexZeroPad("0x01", 64), + groupPubKey: ethers.zeroPadValue("0x01", 64), misbehavedMembersIndices: [], - signatures: ethers.utils.hexZeroPad("0x", 65 * constants.groupSize), + signatures: ethers.zeroPadValue("0x", 65 * constants.groupSize), signingMembersIndices: Array.from( { length: constants.groupSize }, (_, i) => i + 1, ), members: Array.from({ length: constants.groupSize }, (_, i) => i + 1), - membersHash: ethers.constants.HashZero, + membersHash: ethers.ZeroHash, } // Attempting to challenge with very low gas limit should trigger the error diff --git a/solidity/ecdsa/test/WalletRegistry.Deployment.test.ts b/solidity/ecdsa/test/WalletRegistry.Deployment.test.ts index f6e10ccee0..2c9440fa8d 100644 --- a/solidity/ecdsa/test/WalletRegistry.Deployment.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Deployment.test.ts @@ -3,7 +3,7 @@ import chai, { expect } from "chai" import chaiAsPromised from "chai-as-promised" import type { Contract } from "ethers" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { WalletRegistry, WalletRegistryGovernance, @@ -12,7 +12,7 @@ import type { chai.use(chaiAsPromised) -const { AddressZero } = ethers.constants +const { ZeroAddress: AddressZero } = ethers describe("WalletRegistry - Deployment", async () => { let deployer: SignerWithAddress @@ -45,7 +45,7 @@ describe("WalletRegistry - Deployment", async () => { walletRegistryProxy = await ethers.getContractAt( "TransparentUpgradeableProxy", - walletRegistry.address, + await walletRegistry.getAddress(), ) proxyAdmin = await upgrades.admin.getInstance() @@ -57,9 +57,9 @@ describe("WalletRegistry - Deployment", async () => { it("should set WalletRegistry proxy admin", async () => { expect( - await upgrades.erc1967.getAdminAddress(walletRegistry.address), + await upgrades.erc1967.getAdminAddress(await walletRegistry.getAddress()), "invalid WalletRegistry proxy admin", - ).to.be.equal(proxyAdmin.address) + ).to.be.equal(await proxyAdmin.getAddress()) }) it("should set ProxyAdmin owner", async () => { @@ -70,14 +70,18 @@ describe("WalletRegistry - Deployment", async () => { it("should set WalletRegistry implementation", async () => { expect( - await upgrades.erc1967.getImplementationAddress(walletRegistry.address), + await upgrades.erc1967.getImplementationAddress( + await walletRegistry.getAddress(), + ), "invalid WalletRegistry implementation", ).to.be.equal(walletRegistryImplementationAddress) }) it("should set WalletRegistry implementation in ProxyAdmin", async () => { expect( - await proxyAdmin.getProxyImplementation(walletRegistryProxy.address), + await proxyAdmin.getProxyImplementation( + await walletRegistryProxy.getAddress(), + ), "invalid proxy implementation", ).to.be.equal(walletRegistryImplementationAddress) }) @@ -86,7 +90,7 @@ describe("WalletRegistry - Deployment", async () => { expect( await walletRegistry.governance(), "invalid WalletRegistry governance", - ).equal(walletRegistryGovernance.address) + ).equal(await walletRegistryGovernance.getAddress()) }) it("should set WalletRegistryGovernance owner", async () => { @@ -97,9 +101,10 @@ describe("WalletRegistry - Deployment", async () => { }) it("should set WalletRegistry address in artifact to the proxy address", async () => { - expect(walletRegistry.address, "invalid WalletRegistry address").equal( - walletRegistryProxy.address, - ) + expect( + await walletRegistry.getAddress(), + "invalid WalletRegistry address", + ).equal(await walletRegistryProxy.getAddress()) }) it("should revert when initialize called again", async () => { diff --git a/solidity/ecdsa/test/WalletRegistry.DualMode.test.ts b/solidity/ecdsa/test/WalletRegistry.DualMode.test.ts index 1de59cd4d9..6abbc292af 100644 --- a/solidity/ecdsa/test/WalletRegistry.DualMode.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.DualMode.test.ts @@ -1,15 +1,16 @@ import { ethers, helpers } from "hardhat" import { expect } from "chai" +import requireResult from "./helpers/chain" import { createMock } from "./helpers/mock" import type { Mock } from "./helpers/mock" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { WalletRegistry, Allowlist, IStaking } from "../typechain" const { createSnapshot, restoreSnapshot } = helpers.snapshot -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress describe("WalletRegistry - Dual-Mode Authorization", () => { let walletRegistry: WalletRegistry @@ -38,7 +39,7 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { const EcdsaInactivityFactory = await ethers.getContractFactory("EcdsaInactivity") const ecdsaInactivity = await EcdsaInactivityFactory.deploy() - await ecdsaInactivity.deployed() + await ecdsaInactivity.waitForDeployment() // Create fake contracts first allowlist = await createMock("Allowlist") @@ -64,7 +65,7 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { "WalletRegistry", { libraries: { - EcdsaInactivity: ecdsaInactivity.address, + EcdsaInactivity: await ecdsaInactivity.getAddress(), }, }, ) @@ -73,7 +74,7 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { sortitionPool.address, stakingContract.address, ) - await impl.deployed() + await impl.waitForDeployment() const initData = WalletRegistryFactory.interface.encodeFunctionData( "initialize", @@ -81,11 +82,14 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { ) const ERC1967ProxyFactory = await ethers.getContractFactory("ERC1967Proxy") - const proxy = await ERC1967ProxyFactory.deploy(impl.address, initData) - await proxy.deployed() + const proxy = await ERC1967ProxyFactory.deploy( + await impl.getAddress(), + initData, + ) + await proxy.waitForDeployment() walletRegistry = WalletRegistryFactory.attach( - proxy.address, + await proxy.getAddress(), ) as WalletRegistry }) @@ -122,8 +126,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { }) it("should allow authorization increase from allowlist contract", async () => { - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -152,8 +156,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { }) it("should reject authorization increase from legacy staking contract when allowlist is set", async () => { - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate staking contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -185,8 +189,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { }) it("should reject authorization from unauthorized caller when allowlist is set", async () => { - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") await expect( walletRegistry @@ -203,9 +207,9 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { }) it("should allow authorization decrease request from allowlist contract", async () => { - const initialAmount = ethers.utils.parseEther("0") - const fromAmount = ethers.utils.parseEther("40000") - const toAmount = ethers.utils.parseEther("20000") + const initialAmount = ethers.parseEther("0") + const fromAmount = ethers.parseEther("40000") + const toAmount = ethers.parseEther("20000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -255,8 +259,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { // No initializeV2 call - allowlist remains at address(0) it("should allow authorization increase from legacy staking contract when allowlist not set", async () => { - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate staking contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -285,8 +289,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { }) it("should reject authorization from allowlist when allowlist is zero address", async () => { - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate allowlist contract (but allowlist is not set in WalletRegistry) await ethers.provider.send("hardhat_impersonateAccount", [ @@ -318,8 +322,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { }) it("should reject authorization from unauthorized caller when allowlist not set", async () => { - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") await expect( walletRegistry @@ -350,8 +354,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { // Since we're using a fake/mock Allowlist in this test, we can't directly test // the two-step pattern, but we verify the dual-mode modifier allows allowlist calls - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -386,8 +390,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { // TD-2 implemented custom errors for gas efficiency // Verify that dual-mode modifier preserves this optimization - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Measure gas for revert with dual-mode modifier const tx = walletRegistry @@ -409,8 +413,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { // Initialize with allowlist await walletRegistry.initializeV2(allowlist.address) - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -426,7 +430,7 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { const tx = await walletRegistry .connect(allowlistSigner) .authorizationIncreased(stakingProvider.address, fromAmount, toAmount) - const receipt = await tx.wait() + const receipt = requireResult(await tx.wait()) const dualModeGas = receipt.gasUsed await ethers.provider.send("hardhat_stopImpersonatingAccount", [ @@ -452,8 +456,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { await walletRegistry.initializeV2(allowlist.address) - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -469,7 +473,7 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { const tx1 = await walletRegistry .connect(allowlistSigner) .authorizationIncreased(stakingProvider.address, fromAmount, toAmount) - const receipt1 = await tx1.wait() + const receipt1 = requireResult(await tx1.wait()) // Subsequent call - should have similar gas (caching working) const tx2 = await walletRegistry @@ -479,7 +483,7 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { toAmount, fromAmount, ) - const receipt2 = await tx2.wait() + const receipt2 = requireResult(await tx2.wait()) await ethers.provider.send("hardhat_stopImpersonatingAccount", [ allowlist.address, @@ -512,8 +516,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { await walletRegistry.initializeV2(allowlist.address) - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -573,8 +577,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { // Without calling initializeV2, WalletRegistry should work exactly as before // (allowlist defaults to address(0), so legacy staking path is used) - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") await ethers.provider.send("hardhat_setBalance", [ stakingContract.address, @@ -600,9 +604,9 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { it("should support full authorization lifecycle with allowlist", async () => { await walletRegistry.initializeV2(allowlist.address) - const initialAmount = ethers.utils.parseEther("0") - const increasedAmount = ethers.utils.parseEther("40000") - const decreasedAmount = ethers.utils.parseEther("20000") + const initialAmount = ethers.parseEther("0") + const increasedAmount = ethers.parseEther("40000") + const decreasedAmount = ethers.parseEther("20000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ @@ -654,8 +658,8 @@ describe("WalletRegistry - Dual-Mode Authorization", () => { it("should reject mixed authorization attempts (allowlist and staking)", async () => { await walletRegistry.initializeV2(allowlist.address) - const fromAmount = ethers.utils.parseEther("0") - const toAmount = ethers.utils.parseEther("40000") + const fromAmount = ethers.parseEther("0") + const toAmount = ethers.parseEther("40000") // Impersonate allowlist contract await ethers.provider.send("hardhat_impersonateAccount", [ diff --git a/solidity/ecdsa/test/WalletRegistry.Inactivity.test.ts b/solidity/ecdsa/test/WalletRegistry.Inactivity.test.ts index f798a1694c..ff011f2077 100644 --- a/solidity/ecdsa/test/WalletRegistry.Inactivity.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Inactivity.test.ts @@ -9,9 +9,9 @@ import { createNewWallet } from "./utils/wallets" import { signOperatorInactivityClaim } from "./utils/inactivity" import { assertGasUsed } from "./helpers/gas" -import type { BigNumber, ContractTransaction } from "ethers" +import type { ContractTransactionResponse } from "ethers" import type { Mock } from "./helpers/mock" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { SortitionPool, WalletRegistry, @@ -85,9 +85,9 @@ describe("WalletRegistry - Inactivity", () => { ) => number[], expectedGasUsed: number, ) => { - let tx: ContractTransaction - let initialNonce: BigNumber - let initClaimSenderBalance: BigNumber + let tx: ContractTransactionResponse + let initialNonce: bigint + let initClaimSenderBalance: bigint let claimSender: SignerWithAddress before(async () => { @@ -137,13 +137,12 @@ describe("WalletRegistry - Inactivity", () => { it("should refund ETH", async () => { const postNotifyThirdPartyBalance = await provider.getBalance(claimSender.address) - const diff = postNotifyThirdPartyBalance.sub( - initClaimSenderBalance, - ) + const diff = + postNotifyThirdPartyBalance - initClaimSenderBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("2000000", "gwei"), // 0,002 ETH + ethers.parseUnits("2000000", "gwei"), // 0,002 ETH ) }) @@ -151,17 +150,14 @@ describe("WalletRegistry - Inactivity", () => { await assertGasUsed( tx, expectedGasUsed, - ethers.BigNumber.from(expectedGasUsed) - .mul(5) // 5% delta - .div(100) - .toNumber(), + Number((BigInt(expectedGasUsed) * 5n) / 100n), ) }) it("should increment inactivity claim nonce for the group", async () => { expect( await walletRegistry.inactivityClaimNonce(walletID), - ).to.be.equal(initialNonce.add(1)) + ).to.be.equal(initialNonce + 1n) }) it("should emit InactivityClaimed event", async () => { @@ -169,7 +165,7 @@ describe("WalletRegistry - Inactivity", () => { .to.emit(walletRegistry, "InactivityClaimed") .withArgs( walletID, - initialNonce.toNumber(), + Number(initialNonce), claimSender.address, ) }) @@ -945,7 +941,7 @@ describe("WalletRegistry - Inactivity", () => { context("when wallet ID is unknown", async () => { it("should revert", async () => { - const unknownWalletID: string = ethers.utils.keccak256(walletID) + const unknownWalletID: string = ethers.keccak256(walletID) const { signatures, signingMembersIndices } = await signOperatorInactivityClaim( diff --git a/solidity/ecdsa/test/WalletRegistry.Parameters.test.ts b/solidity/ecdsa/test/WalletRegistry.Parameters.test.ts index 645315c17d..5b23059e42 100644 --- a/solidity/ecdsa/test/WalletRegistry.Parameters.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Parameters.test.ts @@ -11,7 +11,7 @@ import type { WalletRegistryGovernance, } from "../typechain" import type { Mock } from "./helpers/mock" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" const { createSnapshot, restoreSnapshot } = helpers.snapshot diff --git a/solidity/ecdsa/test/WalletRegistry.RandomBeacon.test.ts b/solidity/ecdsa/test/WalletRegistry.RandomBeacon.test.ts index 0969417bf4..4831e39545 100644 --- a/solidity/ecdsa/test/WalletRegistry.RandomBeacon.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.RandomBeacon.test.ts @@ -1,7 +1,9 @@ +import { toBigInt } from "ethers" /* eslint-disable no-underscore-dangle */ import { ethers, helpers } from "hardhat" import { expect } from "chai" +import requireResult from "./helpers/chain" import { expectCalledWith } from "./helpers/mock" import { dkgState, walletRegistryFixture } from "./fixtures" import { upgradeRandomBeacon } from "./utils/governance" @@ -15,8 +17,8 @@ import type { WalletRegistryStub, } from "../typechain" import type { Mock } from "./helpers/mock" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { ContractTransaction } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { ContractTransactionResponse } from "ethers" const { createSnapshot, restoreSnapshot } = helpers.snapshot @@ -37,7 +39,7 @@ describe("WalletRegistry - Random Beacon", async () => { describe("requestNewWallet", async () => { context("when requestRelayEntry reverts", async () => { - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -61,7 +63,7 @@ describe("WalletRegistry - Random Beacon", async () => { }) context("when requestRelayEntry succeeds", async () => { - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -79,7 +81,7 @@ describe("WalletRegistry - Random Beacon", async () => { it("should call random beacon", async () => { await expectCalledWith(randomBeaconFake.requestRelayEntry, [ - walletRegistry.address, + await walletRegistry.getAddress(), ]) }) }) @@ -114,8 +116,8 @@ describe("WalletRegistry - Random Beacon", async () => { }) context("when new wallet was requested", async () => { - const relayEntry = ethers.BigNumber.from(ethers.utils.randomBytes(32)) - let tx: ContractTransaction + const relayEntry = toBigInt(ethers.randomBytes(32)) + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -124,7 +126,7 @@ describe("WalletRegistry - Random Beacon", async () => { tx = await walletRegistry .connect(randomBeaconFake.wallet) - .__beaconCallback(relayEntry, 0) + .__beaconCallback(ethers.toBigInt(relayEntry), 0) }) after(async () => { @@ -146,7 +148,7 @@ describe("WalletRegistry - Random Beacon", async () => { it("should set start block for wallet creation", async () => { await expect( (await walletRegistry.getDkgData()).startBlock, - ).to.be.equal((await tx.wait()).blockNumber) + ).to.be.equal(requireResult(await tx.wait()).blockNumber) }) it("should not emit DkgStateLocked event", async () => { @@ -176,10 +178,7 @@ describe("WalletRegistry - Random Beacon", async () => { const gasEstimate = await walletRegistry .connect(randomBeaconFake.wallet) - .estimateGas.__beaconCallback( - ethers.BigNumber.from(ethers.utils.randomBytes(32)), - 0, - ) + .__beaconCallback.estimateGas(toBigInt(ethers.randomBytes(32)), 0) await expect(gasEstimate).to.be.lte(expectedGasEstimate) }) @@ -213,7 +212,7 @@ describe("WalletRegistry - Random Beacon", async () => { // BigNumber first was not just redundant: ethers renders one via // `toHexString()`, which drops leading zero bytes, so roughly one run // in 256 submitted a short entry. - const entry = ethers.utils.randomBytes(32) + const entry = ethers.randomBytes(32) const tx = await randomBeaconMock.submitRelayEntry(entry) @@ -237,7 +236,7 @@ async function mockRandomBeacon( await ethers.getContractFactory("RandomBeaconStub") ).deploy() - await upgradeRandomBeacon(walletRegistry, randomBeacon.address) + await upgradeRandomBeacon(walletRegistry, await randomBeacon.getAddress()) return randomBeacon as RandomBeaconStub } diff --git a/solidity/ecdsa/test/WalletRegistry.Rewards.test.ts b/solidity/ecdsa/test/WalletRegistry.Rewards.test.ts index 114d7de084..704024091a 100644 --- a/solidity/ecdsa/test/WalletRegistry.Rewards.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Rewards.test.ts @@ -6,7 +6,7 @@ import ecdsaData from "./data/ecdsa" import { createNewWallet } from "./utils/wallets" import { signOperatorInactivityClaim } from "./utils/inactivity" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { Mock } from "./helpers/mock" import type { Operator, OperatorID } from "./utils/operators" import type { @@ -30,7 +30,7 @@ async function rewardsBeneficiaryAddress( stakingProvider: string, ): Promise { const allowlistAddr = await walletRegistry.allowlist() - if (allowlistAddr !== ethers.constants.AddressZero) { + if (allowlistAddr !== ethers.ZeroAddress) { const al = (await ethers.getContractAt( "Allowlist", allowlistAddr, @@ -116,7 +116,7 @@ describe("WalletRegistry - Rewards", () => { await tToken.connect(deployer).mint(deployer.address, rewardAmount) await tToken .connect(deployer) - .approveAndCall(sortitionPool.address, rewardAmount, []) + .approveAndCall(await sortitionPool.getAddress(), rewardAmount, "0x") }) after(async () => { @@ -133,7 +133,7 @@ describe("WalletRegistry - Rewards", () => { const balanceBefore = await tToken.balanceOf(beneficiary) const tx = await walletRegistry.withdrawRewards(stakingProvider) const balanceAfter = await tToken.balanceOf(beneficiary) - const received = balanceAfter.sub(balanceBefore) + const received = balanceAfter - balanceBefore await expect(tx) .to.emit(walletRegistry, "RewardsWithdrawn") @@ -172,7 +172,7 @@ describe("WalletRegistry - Rewards", () => { await tToken.connect(deployer).mint(deployer.address, rewardAmount) await tToken .connect(deployer) - .approveAndCall(sortitionPool.address, rewardAmount, []) + .approveAndCall(await sortitionPool.getAddress(), rewardAmount, "0x") }) after(async () => { @@ -187,7 +187,7 @@ describe("WalletRegistry - Rewards", () => { await walletRegistry.withdrawRewards(stakingProvider) const balanceAfter = await tToken.balanceOf(beneficiary) - expect(availableAmount).to.equal(balanceAfter.sub(balanceBefore)) + expect(availableAmount).to.equal(balanceAfter - balanceBefore) availableAmount = await walletRegistry.availableRewards(stakingProvider) expect(availableAmount).to.equal(0) @@ -243,7 +243,7 @@ describe("WalletRegistry - Rewards", () => { await tToken.connect(deployer).mint(deployer.address, rewardAmount) await tToken .connect(deployer) - .approveAndCall(sortitionPool.address, rewardAmount, []) + .approveAndCall(await sortitionPool.getAddress(), rewardAmount, "0x") }) it("should withdraw ineligible rewards", async () => { diff --git a/solidity/ecdsa/test/WalletRegistry.Slashing.test.ts b/solidity/ecdsa/test/WalletRegistry.Slashing.test.ts index 67514d15f6..ee44793794 100644 --- a/solidity/ecdsa/test/WalletRegistry.Slashing.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Slashing.test.ts @@ -13,9 +13,8 @@ import type { T, IRandomBeacon, } from "../typechain" -import type { BigNumber } from "ethers" import type { Mock } from "./helpers/mock" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { Operator, OperatorID } from "./utils/operators" const { createSnapshot, restoreSnapshot } = helpers.snapshot @@ -128,8 +127,8 @@ describe("WalletRegistry - Slashing", () => { context.skip( "when the passed wallet members identifiers are valid (skipped: TokenStaking slashing queue API differs from legacy tests)", () => { - let notifierBalanceBefore: BigNumber - let notifierBalanceAfter: BigNumber + let notifierBalanceBefore: bigint + let notifierBalanceAfter: bigint before(async () => { await createSnapshot() @@ -180,9 +179,7 @@ describe("WalletRegistry - Slashing", () => { // Notification rewards are no longer configured in TokenStaking // (pushNotificationReward/setNotificationReward methods removed). // The notifier receives 0 reward. - const receivedReward = notifierBalanceAfter.sub( - notifierBalanceBefore, - ) + const receivedReward = notifierBalanceAfter - notifierBalanceBefore expect(receivedReward).to.equal(0) }) diff --git a/solidity/ecdsa/test/WalletRegistry.Upgrade.test.ts b/solidity/ecdsa/test/WalletRegistry.Upgrade.test.ts index 05eb520c2b..934d58ed55 100644 --- a/solidity/ecdsa/test/WalletRegistry.Upgrade.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Upgrade.test.ts @@ -1,21 +1,22 @@ import { deployments, ethers, upgrades, helpers } from "hardhat" import chai, { expect } from "chai" import chaiAsPromised from "chai-as-promised" -import { keccak256 } from "ethers/lib/utils" +import { keccak256 } from "ethers" +import requireResult from "./helpers/chain" import { params, walletRegistryFixture } from "./fixtures" import { noMisbehaved, signAndSubmitCorrectDkgResult } from "./utils/dkg" import ecdsaData from "./data/ecdsa" import { createNewWallet } from "./utils/wallets" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { WalletRegistry, WalletRegistryV2 } from "../typechain" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { Allowlist, WalletRegistry, WalletRegistryV2 } from "../typechain" import type { FactoryOptions } from "hardhat/types" -import type { Contract } from "ethers" +import type { BaseContract, Contract } from "ethers" import type { UpgradeProxyOptions } from "@openzeppelin/hardhat-upgrades/src/utils/options" const { mineBlocksTo } = helpers.time -const { AddressZero } = ethers.constants +const { ZeroAddress: AddressZero } = ethers chai.use(chaiAsPromised) @@ -37,7 +38,9 @@ describe("WalletRegistry - Upgrade", async () => { await expect( upgradeProxy("WalletRegistry", "WalletRegistry", { factoryOpts: { - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { + EcdsaInactivity: await EcdsaInactivity.getAddress(), + }, signer: proxyAdminOwner, }, proxyOpts: { @@ -49,12 +52,15 @@ describe("WalletRegistry - Upgrade", async () => { unsafeAllow: ["external-library-linking"], }, }), - ).to.be.rejectedWith(Error, "AllowlistAddressZero") + ).to.be.revertedWithCustomError( + await helpers.contracts.getContract("WalletRegistry"), + "AllowlistAddressZero", + ) }) }) describe("T-005: Atomic upgrade without governance modifier (ISSUE #2)", () => { - let allowlist: Contract + let allowlist: Allowlist beforeEach(async () => { await deployments.fixture() @@ -62,7 +68,7 @@ describe("WalletRegistry - Upgrade", async () => { // Deploy a minimal Allowlist contract for testing const AllowlistFactory = await ethers.getContractFactory("Allowlist") allowlist = await AllowlistFactory.deploy() - await allowlist.deployed() + await allowlist.waitForDeployment() }) it("should allow initializeV2 via upgradeToAndCall without governance restriction", async () => { @@ -78,14 +84,16 @@ describe("WalletRegistry - Upgrade", async () => { "WalletRegistry", { factoryOpts: { - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { + EcdsaInactivity: await EcdsaInactivity.getAddress(), + }, signer: proxyAdminOwner, // Proxy admin owner, NOT governance }, proxyOpts: { constructorArgs: [AddressZero, AddressZero], call: { fn: "initializeV2", - args: [allowlist.address], // Valid allowlist address + args: [await allowlist.getAddress()], }, unsafeAllow: ["external-library-linking"], }, @@ -93,22 +101,26 @@ describe("WalletRegistry - Upgrade", async () => { ) // Verify upgrade succeeded - expect(newWalletRegistry.address).to.equal(walletRegistry.address) - expect(await newWalletRegistry.allowlist()).to.equal(allowlist.address) + expect(await newWalletRegistry.getAddress()).to.equal( + await walletRegistry.getAddress(), + ) + expect(await newWalletRegistry.getFunction("allowlist")()).to.equal( + await allowlist.getAddress(), + ) }) it("should prevent re-initialization with reinitializer(2) modifier", async () => { // First upgrade with initializeV2 await upgradeProxy("WalletRegistry", "WalletRegistry", { factoryOpts: { - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { EcdsaInactivity: await EcdsaInactivity.getAddress() }, signer: proxyAdminOwner, }, proxyOpts: { constructorArgs: [AddressZero, AddressZero], call: { fn: "initializeV2", - args: [allowlist.address], + args: [await allowlist.getAddress()], }, unsafeAllow: ["external-library-linking"], }, @@ -120,11 +132,11 @@ describe("WalletRegistry - Upgrade", async () => { // Deploy another allowlist for re-initialization attempt const AllowlistFactory = await ethers.getContractFactory("Allowlist") const newAllowlist = await AllowlistFactory.deploy() - await newAllowlist.deployed() + await newAllowlist.waitForDeployment() // Attempt to call initializeV2 again should fail await expect( - walletRegistry.initializeV2(newAllowlist.address), + walletRegistry.initializeV2(await newAllowlist.getAddress()), ).to.be.revertedWith("Initializable: contract is already initialized") }) @@ -135,7 +147,9 @@ describe("WalletRegistry - Upgrade", async () => { await expect( upgradeProxy("WalletRegistry", "WalletRegistry", { factoryOpts: { - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { + EcdsaInactivity: await EcdsaInactivity.getAddress(), + }, signer: proxyAdminOwner, }, proxyOpts: { @@ -147,7 +161,10 @@ describe("WalletRegistry - Upgrade", async () => { unsafeAllow: ["external-library-linking"], }, }), - ).to.be.rejectedWith(Error, "AllowlistAddressZero") + ).to.be.revertedWithCustomError( + await helpers.contracts.getContract("WalletRegistry"), + "AllowlistAddressZero", + ) }) }) }) @@ -161,7 +178,9 @@ describe("WalletRegistry - Upgrade", async () => { await expect( upgradeProxy("WalletRegistry", "WalletRegistryV2MisplacedNewSlot", { factoryOpts: { - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { + EcdsaInactivity: await EcdsaInactivity.getAddress(), + }, signer: proxyAdminOwner, }, proxyOpts: { @@ -180,7 +199,9 @@ describe("WalletRegistry - Upgrade", async () => { await expect( upgradeProxy("WalletRegistry", "WalletRegistryV2MissingSlot", { factoryOpts: { - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { + EcdsaInactivity: await EcdsaInactivity.getAddress(), + }, signer: proxyAdminOwner, }, proxyOpts: { @@ -223,7 +244,7 @@ describe("WalletRegistry - Upgrade", async () => { )) as WalletRegistry & WalletRegistryV2 expect(await walletRegistry.governance()).equal( - walletRegistryGovernance.address, + await walletRegistryGovernance.getAddress(), ) newWalletRegistry = (await upgradeProxy( @@ -232,10 +253,15 @@ describe("WalletRegistry - Upgrade", async () => { { factoryOpts: { signer: proxyAdminOwner, - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { + EcdsaInactivity: await EcdsaInactivity.getAddress(), + }, }, proxyOpts: { - constructorArgs: [newSortitionPoolAddress, tokenStaking.address], + constructorArgs: [ + newSortitionPoolAddress, + await tokenStaking.getAddress(), + ], call: { fn: "initializeV2", args: [newRandomBeaconAddress, newVarValue], @@ -247,12 +273,14 @@ describe("WalletRegistry - Upgrade", async () => { }) it("new instance should have the same address as the old one", async () => { - expect(newWalletRegistry.address).equal(walletRegistry.address) + expect(await newWalletRegistry.getAddress()).equal( + await walletRegistry.getAddress(), + ) }) it("should not update governance", async () => { expect(await walletRegistry.governance()).equal( - walletRegistryGovernance.address, + await walletRegistryGovernance.getAddress(), ) }) @@ -274,7 +302,7 @@ describe("WalletRegistry - Upgrade", async () => { it("should not update already set variable", async () => { expect(await walletRegistry.reimbursementPool()).to.be.equal( - reimbursementPool.address, + await reimbursementPool.getAddress(), ) }) @@ -295,10 +323,9 @@ describe("WalletRegistry - Upgrade", async () => { }) it("should revert for removed function", async () => { - await expect(walletRegistry.notifySeedTimeout()).to.be.rejectedWith( - Error, - "Transaction reverted: function selector was not recognized and there's no fallback function", - ) + await expect( + walletRegistry.notifySeedTimeout(), + ).to.be.revertedWithoutReason() }) it("should execute updated function logic", async () => { @@ -349,13 +376,13 @@ describe("WalletRegistry - Upgrade", async () => { .connect(walletOwner.wallet) .requestNewWallet() - const relayEntry = ethers.utils.randomBytes(32) - const dkgSeed = ethers.BigNumber.from(keccak256(relayEntry)) + const relayEntry = ethers.randomBytes(32) + const dkgSeed = BigInt(keccak256(relayEntry)) // eslint-disable-next-line no-underscore-dangle await walletRegistryV1 .connect(randomBeacon.wallet) - .__beaconCallback(relayEntry, 0) + .__beaconCallback(ethers.toBigInt(relayEntry), 0) // Submit DKG result on Wallet Registry V1 const { @@ -366,7 +393,7 @@ describe("WalletRegistry - Upgrade", async () => { walletRegistryV1, expectedNewWalletData.publicKey, dkgSeed, - (await requestNewWalletTx.wait()).blockNumber, + requireResult(await requestNewWalletTx.wait()).blockNumber, noMisbehaved, ) @@ -379,10 +406,15 @@ describe("WalletRegistry - Upgrade", async () => { { factoryOpts: { signer: proxyAdminOwner, - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { + EcdsaInactivity: await EcdsaInactivity.getAddress(), + }, }, proxyOpts: { - constructorArgs: [sortitionPool.address, staking.address], + constructorArgs: [ + await sortitionPool.getAddress(), + await staking.getAddress(), + ], call: { fn: "initializeV2", args: [AddressZero, "new variable set for new contract"], @@ -394,7 +426,7 @@ describe("WalletRegistry - Upgrade", async () => { // Approve DKG result on Wallet Registry V2 await mineBlocksTo( - (await submitDkgResultTx.wait()).blockNumber + + requireResult(await submitDkgResultTx.wait()).blockNumber + params.dkgResultChallengePeriodLength, ) @@ -430,7 +462,7 @@ describe("WalletRegistry - Upgrade", async () => { upgradeProxy("WalletRegistry", "WalletRegistryV2", { factoryOpts: { signer: (await helpers.signers.getNamedSigners()).deployer, - libraries: { EcdsaInactivity: EcdsaInactivity.address }, + libraries: { EcdsaInactivity: await EcdsaInactivity.getAddress() }, }, proxyOpts: { constructorArgs: [AddressZero, AddressZero], @@ -455,7 +487,7 @@ async function upgradeProxy( currentContractName: string, newContractName: string, opts?: UpgradesUpgradeOptions, -): Promise { +): Promise { const currentContract = await deployments.get(currentContractName) const newContract = await ethers.getContractFactory( diff --git a/solidity/ecdsa/test/WalletRegistry.UpgradeV2Deploy.test.ts b/solidity/ecdsa/test/WalletRegistry.UpgradeV2Deploy.test.ts new file mode 100644 index 0000000000..619fb48164 --- /dev/null +++ b/solidity/ecdsa/test/WalletRegistry.UpgradeV2Deploy.test.ts @@ -0,0 +1,114 @@ +import { deployments, ethers, helpers } from "hardhat" +import chai, { expect } from "chai" +import chaiAsPromised from "chai-as-promised" + +import type { Allowlist, WalletRegistry } from "../typechain" + +chai.use(chaiAsPromised) + +// EIP-1967 implementation slot: bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1) +const IMPL_SLOT = + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + +// Covers deploy/17_upgrade_wallet_registry_v2.ts. The script is gated behind +// UPGRADE_WALLET_REGISTRY_V2 and is skipped by default, so it is otherwise +// never exercised by `yarn test` (WalletRegistry.Upgrade.test.ts drives its +// upgrade scenario directly via `upgrades.upgradeProxy`, not via this deploy +// script). This test actually runs the script's body on the hardhat network. +describe("deploy script - UpgradeWalletRegistryV2", () => { + let walletRegistry: WalletRegistry + let allowlist: Allowlist + let governanceBeforeUpgrade: string + + before(async () => { + // Ensure the shared base deployment exists (ReimbursementPool, RandomBeacon, + // TokenStaking, WalletRegistry, Allowlist, ...). This reuses the `::global` + // deployments.fixture() snapshot most other test files already populate; if + // this file happens to run first in the suite it deploys everything fresh. + await deployments.fixture() + + // Governance is not a named EOA here: deploy/10_transfer_governance.ts + // points WalletRegistry.governance() at the deployed + // WalletRegistryGovernance contract, not at the "governance" named + // account. The invariant under test is that the upgrade preserves + // whatever it already was, so capture it before running the upgrade + // fixture below. + const preUpgradeDeployment = await deployments.get("WalletRegistry") + const preUpgradeWalletRegistry = await ethers.getContractAt( + "WalletRegistry", + preUpgradeDeployment.address, + ) + governanceBeforeUpgrade = await preUpgradeWalletRegistry.governance() + + // The upgrade script is gated behind this env var and is skipped by default, + // so it is otherwise never run by `yarn test` (WalletRegistry.Upgrade.test.ts + // drives its upgrade scenario directly via `upgrades.upgradeProxy`, not via + // this deploy script). + process.env.UPGRADE_WALLET_REGISTRY_V2 = "true" + + // Run only the two additional scripts needed on top of the base deployment: + // - "TransferProxyAdminOwnership" (deploy 11): the upgrade script's testnet + // path requires `esdm` to already own the ProxyAdmin, and that transfer is + // not one of its declared `dependencies`. + // - "UpgradeWalletRegistryV2" (deploy 17): the script under test. + // `keepExistingDeployments: true` reuses the deployments from the base + // fixture above instead of wiping and trying to redeploy everything under + // this narrow tag set (which would fail: ReimbursementPool/RandomBeacon/ + // TokenStaking come from an external deploy step that is filtered by this + // same narrow `tags` argument and would be skipped). `fallbackToGlobal: + // false` ensures this specific tag combination actually executes instead of + // silently reverting to the (env-var-unaware) `::global` snapshot cached + // above. + await deployments.fixture( + ["UpgradeWalletRegistryV2", "TransferProxyAdminOwnership"], + { keepExistingDeployments: true, fallbackToGlobal: false }, + ) + + // The deployments.json record for "WalletRegistry" still carries the + // pre-upgrade ABI (the deploy script never re-saves it), so attach with + // the compiled V2 interface directly, exactly as the deploy script does + // for its own post-upgrade verification. + const walletRegistryDeployment = await deployments.get("WalletRegistry") + walletRegistry = await ethers.getContractAt( + "WalletRegistry", + walletRegistryDeployment.address, + ) + + allowlist = await helpers.contracts.getContract("Allowlist") + }) + + after(() => { + delete process.env.UPGRADE_WALLET_REGISTRY_V2 + }) + + it("should save the new implementation deployment artifact", async () => { + const implementationDeployment = await deployments.get( + "WalletRegistryV2Implementation", + ) + expect(implementationDeployment.address).to.not.equal(ethers.ZeroAddress) + }) + + it("should point the WalletRegistry proxy at the new implementation", async () => { + const implementationDeployment = await deployments.get( + "WalletRegistryV2Implementation", + ) + + const implSlot = await ethers.provider.getStorage( + await walletRegistry.getAddress(), + IMPL_SLOT, + ) + const currentImplementation = ethers.getAddress(`0x${implSlot.slice(-40)}`) + + expect(currentImplementation).to.equal(implementationDeployment.address) + }) + + it("should initialize the upgraded WalletRegistry with the deployed Allowlist address", async () => { + expect(await walletRegistry.allowlist()).to.equal( + await allowlist.getAddress(), + ) + }) + + it("should preserve WalletRegistry governance across the upgrade", async () => { + expect(await walletRegistry.governance()).to.equal(governanceBeforeUpgrade) + }) +}) diff --git a/solidity/ecdsa/test/WalletRegistry.WalletCreation.test.ts b/solidity/ecdsa/test/WalletRegistry.WalletCreation.test.ts index 2857810e5f..03effb641d 100644 --- a/solidity/ecdsa/test/WalletRegistry.WalletCreation.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.WalletCreation.test.ts @@ -1,6 +1,8 @@ +import { toBeHex } from "ethers" import { ethers, helpers } from "hardhat" import { expect } from "chai" +import requireResult from "./helpers/chain" import { constants, dkgState, params, walletRegistryFixture } from "./fixtures" import ecdsaData from "./data/ecdsa" import { @@ -19,7 +21,7 @@ import { assertGasUsed } from "./helpers/gas" import { legacyTokenStakingAt } from "./utils/operators" import type { Operator } from "./utils/operators" -import type { BigNumber, ContractTransaction, Signer } from "ethers" +import type { ContractTransactionResponse, Signer } from "ethers" import type { IWalletOwner, SortitionPool, @@ -29,7 +31,7 @@ import type { IRandomBeacon, DkgChallenger, } from "../typechain" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { DkgResult, DkgResultSubmittedEventArgs } from "./utils/dkg" import type { Mock } from "./helpers/mock" @@ -37,7 +39,7 @@ const { to1e18 } = helpers.number const { mineBlocks, mineBlocksTo } = helpers.time const { createSnapshot, restoreSnapshot } = helpers.snapshot -const { keccak256 } = ethers.utils +const { keccak256 } = ethers const { provider } = ethers describe.skip("TokenStaking Integration (DEPRECATED TIP-092)", () => { @@ -71,13 +73,9 @@ describe.skip("TokenStaking Integration (DEPRECATED TIP-092)", () => { describe("WalletRegistry - Wallet Creation", async () => { const dkgTimeout: number = params.dkgResultSubmissionTimeout - const groupPublicKey: string = ethers.utils.hexValue( - ecdsaData.group1.publicKey, - ) - const groupPublicKey2: string = ethers.utils.hexValue( - ecdsaData.group2.publicKey, - ) - const walletID: string = ethers.utils.keccak256(groupPublicKey) + const groupPublicKey: string = ethers.toQuantity(ecdsaData.group1.publicKey) + const groupPublicKey2: string = ethers.toQuantity(ecdsaData.group2.publicKey) + const walletID: string = ethers.keccak256(groupPublicKey) const stubDkgResult: DkgResult = { submitterMemberIndex: 1, @@ -139,7 +137,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("when called by the wallet owner", async () => { context("with initial contract state", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before("start wallet creation", async () => { await createSnapshot() @@ -201,7 +199,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with relay entry submitted", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before("submit relay entry", async () => { await createSnapshot() @@ -371,7 +369,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with relay entry submitted", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before(async () => { await createSnapshot() @@ -536,7 +534,7 @@ describe("WalletRegistry - Wallet Creation", async () => { .connect(walletOwner.wallet) .requestNewWallet() - requestNewWalletStartBlock = (await tx.wait()).blockNumber + requestNewWalletStartBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -582,7 +580,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with relay entry submitted", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before(async () => { await createSnapshot() @@ -638,7 +636,7 @@ describe("WalletRegistry - Wallet Creation", async () => { before("submit dkg result", async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -651,7 +649,9 @@ describe("WalletRegistry - Wallet Creation", async () => { noMisbehaved, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult( + await tx.wait(), + ).blockNumber }) after(async () => { @@ -786,7 +786,9 @@ describe("WalletRegistry - Wallet Creation", async () => { await createSnapshot() const tx = await walletRegistry.challengeDkgResult(dkgResult) - challengeBlockNumber = (await tx.wait()).blockNumber + challengeBlockNumber = requireResult( + await tx.wait(), + ).blockNumber }) after(async () => { @@ -884,7 +886,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with relay entry submitted", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before(async () => { await createSnapshot() @@ -986,7 +988,7 @@ describe("WalletRegistry - Wallet Creation", async () => { }) context("with enough signatures on the result", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DkgResult let dkgResultHash: string @@ -1144,7 +1146,7 @@ describe("WalletRegistry - Wallet Creation", async () => { before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -1157,7 +1159,9 @@ describe("WalletRegistry - Wallet Creation", async () => { noMisbehaved, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult( + await tx.wait(), + ).blockNumber }) after(async () => { @@ -1240,7 +1244,9 @@ describe("WalletRegistry - Wallet Creation", async () => { const tx = await walletRegistry.challengeDkgResult(dkgResult) - challengeBlockNumber = (await tx.wait()).blockNumber + challengeBlockNumber = requireResult( + await tx.wait(), + ).blockNumber }) after(async () => { @@ -1271,7 +1277,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with a fresh dkg result", async () => { context("", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let expectedEventArgs: DkgResultSubmittedEventArgs before(async () => { @@ -1410,7 +1416,7 @@ describe("WalletRegistry - Wallet Creation", async () => { ) context("with misbehaved members", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DkgResult let dkgResultHash: string @@ -1556,7 +1562,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with relay entry submitted", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before("submit relay entry", async () => { await createSnapshot() @@ -1586,14 +1592,14 @@ describe("WalletRegistry - Wallet Creation", async () => { let dkgResultHash: string let dkgResult: DkgResult let submitter: SignerWithAddress - let submitterInitialBalance: BigNumber + let submitterInitialBalance: bigint const submitterIndex = 1 before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -1609,7 +1615,7 @@ describe("WalletRegistry - Wallet Creation", async () => { submitterIndex, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -1652,7 +1658,7 @@ describe("WalletRegistry - Wallet Creation", async () => { }) context("when called by a DKG result submitter", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1697,13 +1703,13 @@ describe("WalletRegistry - Wallet Creation", async () => { it("should refund ETH to a submitter", async () => { const postDkgResultApprovalSubmitterInitialBalance = await provider.getBalance(await submitter.getAddress()) - const diff = postDkgResultApprovalSubmitterInitialBalance.sub( - submitterInitialBalance, - ) + const diff = + postDkgResultApprovalSubmitterInitialBalance - + submitterInitialBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1200000", "gwei"), // 0.0012 ETH + ethers.parseUnits("1200000", "gwei"), // 0.0012 ETH ) }) @@ -1755,8 +1761,8 @@ describe("WalletRegistry - Wallet Creation", async () => { ) context("when the third party is eligible", async () => { - let tx: ContractTransaction - let thirdPartyInitialBalance: BigNumber + let tx: ContractTransactionResponse + let thirdPartyInitialBalance: bigint before(async () => { await createSnapshot() @@ -1787,18 +1793,17 @@ describe("WalletRegistry - Wallet Creation", async () => { await provider.getBalance(await thirdParty.getAddress()) const { dkgResultSubmissionGas } = await walletRegistry.gasParameters() - const feeForDkgSubmission = dkgResultSubmissionGas.mul( - (await tx.wait()).effectiveGasPrice, - ) + const feeForDkgSubmission = + dkgResultSubmissionGas * + requireResult(await tx.wait()).gasPrice // submission part was done by someone else and this is why // we add submission dkg fee to the initial balance const diff = - postDkgResultApprovalThirdPartyInitialBalance.sub( - thirdPartyInitialBalance.add(feeForDkgSubmission), - ) + postDkgResultApprovalThirdPartyInitialBalance - + (thirdPartyInitialBalance + feeForDkgSubmission) expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1000000", "gwei"), // 0,001 ETH + ethers.parseUnits("1000000", "gwei"), // 0,001 ETH ) }) }) @@ -1834,7 +1839,7 @@ describe("WalletRegistry - Wallet Creation", async () => { await walletRegistry.challengeDkgResult(maliciousDkgResult) - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -1849,7 +1854,7 @@ describe("WalletRegistry - Wallet Creation", async () => { anotherSubmitterIndex, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -1881,8 +1886,8 @@ describe("WalletRegistry - Wallet Creation", async () => { }) context("with challenge period passed", async () => { - let tx: ContractTransaction - let initalAnotherSubmitterBalance: BigNumber + let tx: ContractTransactionResponse + let initalAnotherSubmitterBalance: bigint before(async () => { await createSnapshot() @@ -1933,26 +1938,25 @@ describe("WalletRegistry - Wallet Creation", async () => { await provider.getBalance(await anotherSubmitter.getAddress()) const { dkgResultSubmissionGas } = await walletRegistry.gasParameters() - const feeForDkgSubmission = dkgResultSubmissionGas.mul( - (await tx.wait()).effectiveGasPrice, - ) + const feeForDkgSubmission = + dkgResultSubmissionGas * + requireResult(await tx.wait()).gasPrice // submission part was done by someone else and this is why // we add submission dkg fee to the initial balance const diff = - postDkgResultApprovalAnotherSubmitterInitialBalance.sub( - initalAnotherSubmitterBalance.add(feeForDkgSubmission), - ) + postDkgResultApprovalAnotherSubmitterInitialBalance - + (initalAnotherSubmitterBalance + feeForDkgSubmission) expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("2000000", "gwei"), // 0,002 ETH + ethers.parseUnits("2000000", "gwei"), // 0,002 ETH ) }) }) }) context("with max periods duration", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResultHash: string let submitter: SignerWithAddress @@ -1998,10 +2002,10 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with misbehaved operators", async () => { const misbehavedIndices = [2, 9, 11, 30, 60, 64] let misbehavedIds: number[] - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DkgResult let submitter: SignerWithAddress - let submitterInitialBalance: BigNumber + let submitterInitialBalance: bigint before(async () => { await createSnapshot() @@ -2061,18 +2065,18 @@ describe("WalletRegistry - Wallet Creation", async () => { it("should refund ETH to a submitter", async () => { const postDkgResultApprovalSubmitterInitialBalance = await provider.getBalance(await submitter.getAddress()) - const diff = postDkgResultApprovalSubmitterInitialBalance.sub( - submitterInitialBalance, - ) + const diff = + postDkgResultApprovalSubmitterInitialBalance - + submitterInitialBalance - expect(diff).to.be.gt(ethers.utils.parseUnits("-1000000", "gwei")) // -0,001 ETH + expect(diff).to.be.gt(ethers.parseUnits("-1000000", "gwei")) // -0,001 ETH expect(diff).to.be.lt( - ethers.utils.parseUnits("1000000", "gwei"), // 0,001 ETH + ethers.parseUnits("1000000", "gwei"), // 0,001 ETH ) }) it("should use close to 330 000 gas", async () => { - await assertGasUsed(tx, 330_000, 15_000) + await assertGasUsed(tx, 330_000, 20_000) }) }) @@ -2085,7 +2089,7 @@ describe("WalletRegistry - Wallet Creation", async () => { let dkgResult: DkgResult let submitter: SignerWithAddress - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -2114,7 +2118,7 @@ describe("WalletRegistry - Wallet Creation", async () => { }) it("should use close to 330 000 gas", async () => { - await assertGasUsed(await tx, 330_000, 15_000) + await assertGasUsed(await tx, 330_000, 20_000) }) }, ) @@ -2177,7 +2181,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with new wallet creation started", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before( "request new wallet creation and submit relay entry", @@ -2204,7 +2208,7 @@ describe("WalletRegistry - Wallet Creation", async () => { let dkgResultHash: string let dkgResult: DkgResult let submitter: SignerWithAddress - let submitterInitialBalance: BigNumber + let submitterInitialBalance: bigint const newResultPublicKey = ecdsaData.group2.publicKey const newWalletID = keccak256(newResultPublicKey) @@ -2230,7 +2234,7 @@ describe("WalletRegistry - Wallet Creation", async () => { }) context("when called by a DKG result submitter", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2275,13 +2279,13 @@ describe("WalletRegistry - Wallet Creation", async () => { it("should refund ETH to a submitter", async () => { const postDkgResultApprovalSubmitterInitialBalance = await provider.getBalance(await submitter.getAddress()) - const diff = postDkgResultApprovalSubmitterInitialBalance.sub( - submitterInitialBalance, - ) + const diff = + postDkgResultApprovalSubmitterInitialBalance - + submitterInitialBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1200000", "gwei"), // 0.0012 ETH + ethers.parseUnits("1200000", "gwei"), // 0.0012 ETH ) }) }) @@ -2296,14 +2300,16 @@ describe("WalletRegistry - Wallet Creation", async () => { let dkgResult: DkgResult let dkgResultHash: string let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before("setup malicious DKG result", async () => { await createSnapshot() // Deploy challenger contract const DkgChallenger = await ethers.getContractFactory("DkgChallenger") - dkgChallenger = await DkgChallenger.deploy(walletRegistry.address) + dkgChallenger = await DkgChallenger.deploy( + await walletRegistry.getAddress(), + ) // Request new wallet await walletRegistry.connect(walletOwner.wallet).requestNewWallet() @@ -2333,7 +2339,7 @@ describe("WalletRegistry - Wallet Creation", async () => { .to.emit(walletRegistry, "DkgResultChallenged") .withArgs( dkgResultHash, - dkgChallenger.address, + await dkgChallenger.getAddress(), "Invalid group members", ) }) @@ -2365,7 +2371,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with relay entry submitted", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before("submit relay entry", async () => { await createSnapshot() @@ -2394,7 +2400,7 @@ describe("WalletRegistry - Wallet Creation", async () => { before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -2409,7 +2415,9 @@ describe("WalletRegistry - Wallet Creation", async () => { noMisbehaved, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult( + await tx.wait(), + ).blockNumber }) after(async () => { @@ -2420,8 +2428,8 @@ describe("WalletRegistry - Wallet Creation", async () => { context.skip( "called by a third party (skipped: no processSlashing on dev TokenStaking)", async () => { - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2501,8 +2509,8 @@ describe("WalletRegistry - Wallet Creation", async () => { context.skip( "called by a third party (skipped: no processSlashing on dev TokenStaking)", async () => { - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2608,8 +2616,8 @@ describe("WalletRegistry - Wallet Creation", async () => { let dkgResult: DkgResult let submitter: SignerWithAddress - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2683,7 +2691,7 @@ describe("WalletRegistry - Wallet Creation", async () => { async () => { const misbehavedIndices = [2, 9, 30, 11, 60, 64] - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DkgResult let dkgResultHash: string @@ -2730,7 +2738,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("when misbehaved members contains duplicates", async () => { const misbehavedIndices = [2, 9, 30, 30, 60, 64] - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DkgResult let dkgResultHash: string @@ -2808,7 +2816,7 @@ describe("WalletRegistry - Wallet Creation", async () => { before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -2830,7 +2838,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context( "when staking.seize() succeeds (normal operation)", async () => { - let challengeTx: ContractTransaction + let challengeTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2867,8 +2875,8 @@ describe("WalletRegistry - Wallet Creation", async () => { }) it("should use less gas than current implementation (bytecode optimization)", async () => { - const receipt = await challengeTx.wait() - const gasUsed = receipt.gasUsed.toNumber() + const receipt = requireResult(await challengeTx.wait()) + const gasUsed = Number(receipt.gasUsed) expect(gasUsed).to.be.lessThan(1_850_000) }) }, @@ -2899,7 +2907,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with new wallet creation started", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before( "request new wallet creation and submit relay entry", @@ -2937,7 +2945,7 @@ describe("WalletRegistry - Wallet Creation", async () => { before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -2952,7 +2960,7 @@ describe("WalletRegistry - Wallet Creation", async () => { noMisbehaved, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -2963,8 +2971,8 @@ describe("WalletRegistry - Wallet Creation", async () => { context.skip( "called by a third party (skipped: no processSlashing on dev TokenStaking)", async () => { - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3050,8 +3058,8 @@ describe("WalletRegistry - Wallet Creation", async () => { context.skip( "called by a third party (skipped: no processSlashing on dev TokenStaking)", async () => { - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3148,8 +3156,8 @@ describe("WalletRegistry - Wallet Creation", async () => { let dkgResult: DkgResult let submitter: SignerWithAddress - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3331,7 +3339,7 @@ describe("WalletRegistry - Wallet Creation", async () => { expectedSubmissionOffset += blocksToMine await expect( - walletRegistry.callStatic.notifyDkgTimeout(), + walletRegistry.notifyDkgTimeout.staticCall(), ).to.be.revertedWith("DKG has not timed out") await walletRegistry.challengeDkgResult(dkgResult) @@ -3371,7 +3379,7 @@ describe("WalletRegistry - Wallet Creation", async () => { context("with new wallet creation in progress", async () => { let startBlock: number - let dkgSeed: BigNumber + let dkgSeed: bigint before("request new wallet creation and submit relay entry", async () => { await createSnapshot() @@ -3443,7 +3451,7 @@ describe("WalletRegistry - Wallet Creation", async () => { .connect(walletOwner.wallet) .requestNewWallet() - requestNewWalletStartBlock = (await tx.wait()).blockNumber + requestNewWalletStartBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -3538,7 +3546,7 @@ describe("WalletRegistry - Wallet Creation", async () => { .connect(walletOwner.wallet) .requestNewWallet() - requestNewWalletStartBlock = (await tx.wait()).blockNumber + requestNewWalletStartBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -3597,8 +3605,8 @@ describe("WalletRegistry - Wallet Creation", async () => { }) context("called by a third party", async () => { - let tx: ContractTransaction - let initThirdPartyBalance: BigNumber + let tx: ContractTransactionResponse + let initThirdPartyBalance: bigint before(async () => { await createSnapshot() @@ -3636,12 +3644,10 @@ describe("WalletRegistry - Wallet Creation", async () => { const postNotifyThirdPartyBalance = await provider.getBalance( thirdParty.address, ) - const diff = postNotifyThirdPartyBalance.sub( - initThirdPartyBalance, - ) + const diff = postNotifyThirdPartyBalance - initThirdPartyBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("100000", "gwei"), // 0,0001 ETH + ethers.parseUnits("100000", "gwei"), // 0,0001 ETH ) }) @@ -3689,7 +3695,7 @@ describe("WalletRegistry - Wallet Creation", async () => { .connect(walletOwner.wallet) .requestNewWallet() - requestNewWalletStartBlock = (await tx.wait()).blockNumber + requestNewWalletStartBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -3759,8 +3765,8 @@ describe("WalletRegistry - Wallet Creation", async () => { }) context("called by a third party", async () => { - let tx: ContractTransaction - let initThirdPartyBalance: BigNumber + let tx: ContractTransactionResponse + let initThirdPartyBalance: bigint before(async () => { await createSnapshot() @@ -3791,12 +3797,10 @@ describe("WalletRegistry - Wallet Creation", async () => { const postNotifyThirdPartyBalance = await provider.getBalance( thirdParty.address, ) - const diff = postNotifyThirdPartyBalance.sub( - initThirdPartyBalance, - ) + const diff = postNotifyThirdPartyBalance - initThirdPartyBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("100000", "gwei"), // 0,0001 ETH + ethers.parseUnits("100000", "gwei"), // 0,0001 ETH ) }) @@ -3828,7 +3832,7 @@ describe("WalletRegistry - Wallet Creation", async () => { }) context("when dkg was triggered", async () => { - let dkgSeed: BigNumber + let dkgSeed: bigint before(async () => { await createSnapshot() @@ -3848,7 +3852,7 @@ describe("WalletRegistry - Wallet Creation", async () => { it("should be the same group as if called the sortition pool directly", async () => { const exectedGroup = await sortitionPool.selectGroup( constants.groupSize, - ethers.utils.hexZeroPad(dkgSeed.toHexString(), 32), + ethers.zeroPadValue(toBeHex(dkgSeed), 32), ) const actualGroup = await walletRegistry.selectGroup() expect(exectedGroup).to.be.deep.equal(actualGroup) @@ -3883,7 +3887,7 @@ async function assertDkgResultCleanData(walletRegistry: WalletRegistryStub) { ).to.eq(0) expect(dkgData.submittedResultHash, "unexpected submittedResultHash").to.eq( - ethers.constants.HashZero, + ethers.ZeroHash, ) expect(dkgData.submittedResultBlock, "unexpected submittedResultBlock").to.eq( diff --git a/solidity/ecdsa/test/WalletRegistry.WalletOwner.test.ts b/solidity/ecdsa/test/WalletRegistry.WalletOwner.test.ts index a393c447ab..a8402a4050 100644 --- a/solidity/ecdsa/test/WalletRegistry.WalletOwner.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.WalletOwner.test.ts @@ -8,7 +8,7 @@ import { submitRelayEntry } from "./utils/randomBeacon" import { signAndSubmitCorrectDkgResult } from "./utils/dkg" import ecdsaData from "./data/ecdsa" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { DkgResult } from "./utils/dkg" import type { Mock } from "./helpers/mock" import type { @@ -16,23 +16,17 @@ import type { WalletRegistry, WalletRegistryStub, } from "../typechain" -import type { ContractTransaction } from "ethers" +import type { ContractTransactionResponse } from "ethers" const { mineBlocks } = helpers.time const { createSnapshot, restoreSnapshot } = helpers.snapshot describe("WalletRegistry - Wallet Owner", async () => { - const groupPublicKey: string = ethers.utils.hexValue( - ecdsaData.group1.publicKey, - ) - const groupPublicKeyX: string = ethers.utils.hexValue( - ecdsaData.group1.publicKeyX, - ) - const groupPublicKeyY: string = ethers.utils.hexValue( - ecdsaData.group1.publicKeyY, - ) - const walletID: string = ethers.utils.keccak256(groupPublicKey) + const groupPublicKey: string = ethers.toQuantity(ecdsaData.group1.publicKey) + const groupPublicKeyX: string = ethers.toQuantity(ecdsaData.group1.publicKeyX) + const groupPublicKeyY: string = ethers.toQuantity(ecdsaData.group1.publicKeyY) + const walletID: string = ethers.keccak256(groupPublicKey) let walletRegistry: WalletRegistryStub & WalletRegistry let walletOwner: Mock @@ -70,7 +64,7 @@ describe("WalletRegistry - Wallet Owner", async () => { }) context("when __ecdsaWalletCreatedCallback reverts", async () => { - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -96,7 +90,7 @@ describe("WalletRegistry - Wallet Owner", async () => { }) context("when __ecdsaWalletCreatedCallback succeeds", async () => { - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() diff --git a/solidity/ecdsa/test/WalletRegistry.Wallets.test.ts b/solidity/ecdsa/test/WalletRegistry.Wallets.test.ts index 40a411b236..974c4d9afc 100644 --- a/solidity/ecdsa/test/WalletRegistry.Wallets.test.ts +++ b/solidity/ecdsa/test/WalletRegistry.Wallets.test.ts @@ -1,6 +1,6 @@ import { helpers, ethers } from "hardhat" import { expect } from "chai" -import { formatBytes32String } from "ethers/lib/utils" +import { encodeBytes32String } from "ethers" import { walletRegistryFixture } from "./fixtures" import { createNewWallet } from "./utils/wallets" @@ -8,8 +8,8 @@ import ecdsaData from "./data/ecdsa" import { hashUint32Array } from "./utils/groups" import type { Operator } from "./utils/operators" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { ContractTransaction } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { ContractTransactionResponse } from "ethers" import type { DkgResult } from "./utils/dkg" import type { IRandomBeacon, @@ -92,10 +92,10 @@ describe("WalletRegistry - Wallets", async () => { ).to.be.equal(hashUint32Array(dkgResult.members)) expect(wallet.publicKeyX, "unexpected public key X").to.be.equal( - ethers.utils.hexDataSlice(test.publicKey, 0, 32), + ethers.dataSlice(test.publicKey, 0, 32), ) expect(wallet.publicKeyY, "unexpected public key Y").to.be.equal( - ethers.utils.hexDataSlice(test.publicKey, 32), + ethers.dataSlice(test.publicKey, 32), ) }) @@ -111,12 +111,12 @@ describe("WalletRegistry - Wallets", async () => { const testData = [ { context: "with too short public key", - publicKey: ethers.utils.randomBytes(63), + publicKey: ethers.randomBytes(63), expectedError: "Invalid length of the public key", }, { context: "with too long public key", - publicKey: ethers.utils.randomBytes(65), + publicKey: ethers.randomBytes(65), expectedError: "Invalid length of the public key", }, ] @@ -215,7 +215,7 @@ describe("WalletRegistry - Wallets", async () => { it("should return false", async () => { await expect( await walletRegistry.isWalletRegistered( - formatBytes32String("NON EXISTING"), + encodeBytes32String("NON EXISTING"), ), ).to.be.false }) @@ -249,7 +249,7 @@ describe("WalletRegistry - Wallets", async () => { it("should revert", async () => { await expect( walletRegistry.getWalletPublicKey( - formatBytes32String("NON EXISTING"), + encodeBytes32String("NON EXISTING"), ), ).to.be.revertedWith("Wallet with the given ID has not been registered") }) @@ -283,7 +283,7 @@ describe("WalletRegistry - Wallets", async () => { ).to.be.equal(walletPublicKey) await expect( - ethers.utils.arrayify(actualPublicKey), + ethers.getBytes(actualPublicKey), "returned public key is not 64-byte long", ).to.have.lengthOf(64) }) @@ -318,7 +318,7 @@ describe("WalletRegistry - Wallets", async () => { context("when caller is the wallet owner", () => { context("when wallet with the given ID is unknown", () => { it("should revert", async () => { - const unknownWalletID: string = ethers.utils.keccak256(walletID) + const unknownWalletID: string = ethers.keccak256(walletID) await expect( walletRegistry .connect(walletOwner.wallet) @@ -330,7 +330,7 @@ describe("WalletRegistry - Wallets", async () => { }) context("when wallet with the given ID is registered", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before("close the wallet", async () => { await createSnapshot() @@ -492,7 +492,9 @@ describe("WalletRegistry - Wallets", async () => { "when the passed wallet members identifiers are invalid", () => { it("should revert", async () => { - const corruptedWalletMembersIDs = walletMembersIDs.reverse() + const corruptedWalletMembersIDs = walletMembersIDs + .slice() + .reverse() await expect( walletRegistry.isWalletMember( @@ -518,7 +520,7 @@ describe("WalletRegistry - Wallets", async () => { // To test this scenario, we need an address that is not a // sortition pool operator for sure. The address of the wallet // registry itself seems to be a good candidate. - const operator = walletRegistry.address + const operator = await walletRegistry.getAddress() await expect( walletRegistry.isWalletMember( diff --git a/solidity/ecdsa/test/WalletRegistryGovernance.test.ts b/solidity/ecdsa/test/WalletRegistryGovernance.test.ts index 3338a61ece..af451b9a80 100644 --- a/solidity/ecdsa/test/WalletRegistryGovernance.test.ts +++ b/solidity/ecdsa/test/WalletRegistryGovernance.test.ts @@ -1,10 +1,11 @@ import { deployments, ethers, helpers } from "hardhat" import { expect } from "chai" +import requireResult from "./helpers/chain" import { constants, params, updateWalletRegistryParams } from "./fixtures" -import type { ContractTransaction } from "ethers" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { ContractTransactionResponse } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { WalletRegistry, WalletRegistryStub, @@ -37,9 +38,6 @@ const fixture = deployments.createFixture(async () => { } }) -const minedBlockTimestamp = async (tx: ContractTransaction): Promise => - (await ethers.provider.getBlock((await tx.wait()).blockNumber)).timestamp - describe("WalletRegistryGovernance", async () => { let governance: SignerWithAddress let walletRegistry: WalletRegistry @@ -75,14 +73,14 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse context("when new address is zero", () => { it("should revert when a new random beacon address is zero", async () => { await expect( walletRegistryGovernance .connect(governance) - .upgradeRandomBeacon(ethers.constants.AddressZero), + .upgradeRandomBeacon(ethers.ZeroAddress), ).to.be.revertedWith("New random beacon address cannot be zero") }) }) @@ -127,14 +125,14 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse context("when new address is zero", () => { it("should revert when a new address is zero", async () => { await expect( walletRegistryGovernance .connect(governance) - .initializeWalletOwner(ethers.constants.AddressZero), + .initializeWalletOwner(ethers.ZeroAddress), ).to.be.revertedWith("Wallet Owner address cannot be zero") }) }) @@ -187,7 +185,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -214,7 +212,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit GovernanceDelayUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(walletRegistryGovernance, "GovernanceDelayUpdateStarted") .withArgs(1337, blockTimestamp) @@ -270,7 +272,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -325,7 +327,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -346,9 +348,7 @@ describe("WalletRegistryGovernance", async () => { await expect( walletRegistryGovernance .connect(governance) - .beginWalletRegistryGovernanceTransfer( - ethers.constants.AddressZero, - ), + .beginWalletRegistryGovernanceTransfer(ethers.ZeroAddress), ).to.be.revertedWith( "New wallet registry governance address cannot be zero", ) @@ -357,7 +357,7 @@ describe("WalletRegistryGovernance", async () => { it("should not transfer the governance", async () => { expect(await walletRegistry.governance()).to.be.equal( - walletRegistryGovernance.address, + await walletRegistryGovernance.getAddress(), ) }) @@ -368,7 +368,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit WalletRegistryGovernanceTransferStarted", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -432,7 +436,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -490,7 +494,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -509,14 +513,14 @@ describe("WalletRegistryGovernance", async () => { await expect( walletRegistryGovernance .connect(governance) - .beginWalletOwnerUpdate(ethers.constants.AddressZero), + .beginWalletOwnerUpdate(ethers.ZeroAddress), ).to.be.revertedWith("New wallet owner address cannot be zero") }) }) it("should not update the wallet owner", async () => { expect(await walletRegistry.walletOwner()).to.be.equal( - ethers.constants.AddressZero, + ethers.ZeroAddress, ) }) @@ -527,7 +531,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the WalletOwnerUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(walletRegistryGovernance, "WalletOwnerUpdateStarted") .withArgs(thirdParty.address, blockTimestamp) @@ -579,7 +587,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -632,7 +640,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -659,7 +667,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the MinimumAuthorizationUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -714,7 +726,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -765,7 +777,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -794,7 +806,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the AuthorizationDecreaseDelayUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -847,7 +863,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -903,7 +919,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -932,7 +948,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the AuthorizationDecreaseChangePeriodUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -985,7 +1005,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1041,7 +1061,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1070,7 +1090,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the MaliciousDkgResultSlashingAmountUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -1125,7 +1149,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1181,7 +1205,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1209,7 +1233,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the DkgResultSubmissionGasUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -1264,7 +1292,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1317,7 +1345,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1346,7 +1374,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the DkgResultApprovalGasOffsetUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -1401,7 +1433,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1467,7 +1499,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner and value is correct", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1496,7 +1528,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the MaliciousDkgResultNotificationRewardMultiplierUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -1551,7 +1587,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1609,7 +1645,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1638,7 +1674,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the SortitionPoolRewardsBanDurationUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -1693,7 +1733,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1786,7 +1826,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner and the value is correct", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1813,7 +1853,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the DkgSeedTimeoutUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(walletRegistryGovernance, "DkgSeedTimeoutUpdateStarted") .withArgs(11, blockTimestamp) @@ -1865,7 +1909,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1948,7 +1992,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner and the value is correct", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1975,7 +2019,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the DkgResultChallengePeriodLengthUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -2030,7 +2078,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2086,7 +2134,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2107,7 +2155,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit DkgResultChallengeExtraGasUpdateStarted", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -2162,7 +2214,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2247,7 +2299,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2274,7 +2326,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the DkgResultSubmissionTimeoutUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -2329,7 +2385,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2416,7 +2472,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner and the value is correct", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2444,7 +2500,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the DkgSubmitterPrecedencePeriodLengthUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -2499,7 +2559,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2556,7 +2616,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let reimbursementPoolAddress: string before(async () => { @@ -2578,7 +2638,7 @@ describe("WalletRegistryGovernance", async () => { await expect( walletRegistryGovernance .connect(governance) - .beginReimbursementPoolUpdate(ethers.constants.AddressZero), + .beginReimbursementPoolUpdate(ethers.ZeroAddress), ).to.be.revertedWith("New reimbursement pool address cannot be zero") }) }) @@ -2596,7 +2656,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the ReimbursementPoolUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(walletRegistryGovernance, "ReimbursementPoolUpdateStarted") .withArgs(thirdParty.address, blockTimestamp) @@ -2648,7 +2712,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2701,7 +2765,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2730,7 +2794,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the NotifyOperatorInactivityGasOffsetUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -2785,7 +2853,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2841,7 +2909,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2870,7 +2938,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the NotifySeedTimeoutGasOffsetUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -2925,7 +2997,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2981,7 +3053,7 @@ describe("WalletRegistryGovernance", async () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3010,7 +3082,11 @@ describe("WalletRegistryGovernance", async () => { }) it("should emit the NotifyDkgTimeoutNegativeGasOffsetUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( walletRegistryGovernance, @@ -3065,7 +3141,7 @@ describe("WalletRegistryGovernance", async () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() diff --git a/solidity/ecdsa/test/fixtures/index.ts b/solidity/ecdsa/test/fixtures/index.ts index cbcfd3cb98..89d9bcf7a6 100644 --- a/solidity/ecdsa/test/fixtures/index.ts +++ b/solidity/ecdsa/test/fixtures/index.ts @@ -62,7 +62,7 @@ import type { IRandomBeacon, Allowlist, } from "../../typechain" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { Operator } from "../utils/operators" import type { Mock } from "../helpers/mock" @@ -252,12 +252,11 @@ async function updateTokenStakingParams( staking: TokenStaking, deployer: SignerWithAddress, ) { - const initialNotifierTreasury = constants.tokenStakingNotificationReward.mul( - constants.groupSize, - ) + const initialNotifierTreasury = + constants.tokenStakingNotificationReward * BigInt(constants.groupSize) await tToken .connect(deployer) - .approve(staking.address, initialNotifierTreasury) + .approve(await staking.getAddress(), initialNotifierTreasury) // NOTE: These methods no longer exist in TokenStaking interface // await staking // .connect(deployer) @@ -357,7 +356,7 @@ export async function initializeWalletOwner( await deployer.sendTransaction({ to: walletOwner.address, - value: ethers.utils.parseEther("1000"), + value: ethers.parseEther("1000"), }) await walletRegistryGovernance @@ -372,8 +371,8 @@ async function fundReimbursementPool( reimbursementPool: ReimbursementPool, ) { await deployer.sendTransaction({ - to: reimbursementPool.address, - value: ethers.utils.parseEther("100.0"), // Send 100.0 ETH + to: await reimbursementPool.getAddress(), + value: ethers.parseEther("100.0"), }) } @@ -408,7 +407,7 @@ export async function setupAllowlist( // This assumes the Allowlist deployment script has already run. const allowlist: Allowlist = await helpers.contracts.getContract("Allowlist") - if (!allowlist.address) { + if (!(await allowlist.getAddress())) { throw new Error( "Allowlist contract not found. Ensure Allowlist deployment script has executed.", ) @@ -421,7 +420,7 @@ export async function setupAllowlist( // Initialize WalletRegistry with Allowlist address to enable dual-mode authorization. // This sets the allowlist address in WalletRegistry storage, which the authorization // routing logic uses to determine whether to accept calls from the Allowlist contract. - await walletRegistry.initializeV2(allowlist.address) + await walletRegistry.initializeV2(await allowlist.getAddress()) return allowlist } diff --git a/solidity/ecdsa/test/helpers/chain.ts b/solidity/ecdsa/test/helpers/chain.ts new file mode 100644 index 0000000000..4c71d8e6e4 --- /dev/null +++ b/solidity/ecdsa/test/helpers/chain.ts @@ -0,0 +1,5 @@ +/** Fail explicitly when a local test's block or mined receipt is unavailable. */ +export default function requireResult(result: T | null): T { + if (result === null) throw new Error("Expected a non-null chain response") + return result +} diff --git a/solidity/ecdsa/test/helpers/gas.ts b/solidity/ecdsa/test/helpers/gas.ts index 458b7020d0..483b0297ce 100644 --- a/solidity/ecdsa/test/helpers/gas.ts +++ b/solidity/ecdsa/test/helpers/gas.ts @@ -1,19 +1,19 @@ import { expect } from "chai" -import { ethers } from "hardhat" -import type { ContractTransaction } from "ethers" +import requireResult from "./chain" -const { BigNumber } = ethers +import type { ContractTransactionResponse } from "ethers" // TODO: Move to @keep-network/hardhat-helpers // eslint-disable-next-line import/prefer-default-export export async function assertGasUsed( - tx: ContractTransaction, + tx: ContractTransactionResponse, expectedGasUsed: number, delta = 1000, ): Promise { - expect((await tx.wait()).gasUsed, "invalid gas used").to.be.closeTo( - BigNumber.from(expectedGasUsed), + const receipt = requireResult(await tx.wait()) + expect(receipt.gasUsed, "invalid gas used").to.be.closeTo( + BigInt(expectedGasUsed), delta, ) } diff --git a/solidity/ecdsa/test/helpers/mock.test.ts b/solidity/ecdsa/test/helpers/mock.test.ts index b56c702583..6255a65ca1 100644 --- a/solidity/ecdsa/test/helpers/mock.test.ts +++ b/solidity/ecdsa/test/helpers/mock.test.ts @@ -1,10 +1,15 @@ import { ethers } from "hardhat" import { expect } from "chai" -import { createMock, expectCalledWith } from "./mock" +import requireResult from "./chain" +import { createMock, expectCalledOnceWith, expectCalledWith } from "./mock" import type { Mock } from "./mock" -import type { IMockTarget, MockTargetConsumer } from "../../typechain" +import type { + IMockTarget, + MockTargetConsumer, + WalletRegistry, +} from "../../typechain" describe("MockContract", () => { let target: Mock @@ -15,7 +20,7 @@ describe("MockContract", () => { const factory = await ethers.getContractFactory("MockTargetConsumer") consumer = (await factory.deploy(target.address)) as MockTargetConsumer - await consumer.deployed() + await consumer.waitForDeployment() }) describe("view functions reached by STATICCALL", () => { @@ -92,9 +97,9 @@ describe("MockContract", () => { it("reverts every call to the function", async () => { await target.doThing.reverts("nope") - await expect( - consumer.doThing(ethers.constants.AddressZero, 1), - ).to.be.revertedWith("nope") + await expect(consumer.doThing(ethers.ZeroAddress, 1)).to.be.revertedWith( + "nope", + ) }) it("reverts only the matching arguments", async () => { @@ -150,24 +155,50 @@ describe("MockContract", () => { it("counts each function separately", async () => { await target.doThing.returns(true) - await consumer.doThing(ethers.constants.AddressZero, 1) + await consumer.doThing(ethers.ZeroAddress, 1) await consumer.noReturn(1) expect(await target.doThing.callCount()).to.equal(1) expect(await target.noReturn.callCount()).to.equal(1) }) + + it("matches a struct argument against plain-number expectations", async () => { + // `normalizeForComparison` walks into arrays and structs, a path + // `IMockTarget`'s flat arguments never reach. ethers decodes every + // integer nested in a DKG result as a bigint, so the plain JS numbers + // spelled out below match only because the walk happens. + const registry = await createMock("WalletRegistry") + const registryCaller: WalletRegistry = await ethers.getContractAt( + "WalletRegistry", + registry.address, + ) + + await registryCaller.submitDkgResult({ + submitterMemberIndex: 1, + groupPubKey: "0xaabb", + misbehavedMembersIndices: [3, 5], + signatures: "0xccdd", + signingMembersIndices: [7, 9], + members: [100, 200], + membersHash: ethers.ZeroHash, + }) + + await expectCalledOnceWith(registry.submitDkgResult, [ + [1, "0xaabb", [3, 5], "0xccdd", [7, 9], [100, 200], ethers.ZeroHash], + ]) + }) }) describe("reset", () => { it("clears recorded calls and configured responses for one function", async () => { await target.doThing.returns(true) - await consumer.doThing(ethers.constants.AddressZero, 1) + await consumer.doThing(ethers.ZeroAddress, 1) await target.doThing.reset() expect(await target.doThing.callCount()).to.equal(0) // The configured `true` is gone, so the call answers with empty data. - await consumer.doThing(ethers.constants.AddressZero, 1) + await consumer.doThing(ethers.ZeroAddress, 1) expect(await consumer.lastResult()).to.equal(false) }) @@ -215,10 +246,10 @@ describe("MockContract", () => { // `msg.sender == someContract`. const factory = await ethers.getContractFactory("MockTargetConsumer") const other = await factory.deploy(target.address) - await other.deployed() + await other.waitForDeployment() const tx = await other.connect(target.wallet).noReturn(1) - const receipt = await tx.wait() + const receipt = requireResult(await tx.wait()) expect(receipt.from).to.equal(target.address) }) @@ -226,9 +257,7 @@ describe("MockContract", () => { describe("address option", () => { it("deploys at a requested address", async () => { - const address = ethers.utils.getAddress( - `0x${"ab".repeat(20)}`.toLowerCase(), - ) + const address = ethers.getAddress(`0x${"ab".repeat(20)}`.toLowerCase()) const pinned = await createMock("IMockTarget", { address }) @@ -237,7 +266,7 @@ describe("MockContract", () => { const factory = await ethers.getContractFactory("MockTargetConsumer") const pinnedConsumer = await factory.deploy(address) - await pinnedConsumer.deployed() + await pinnedConsumer.waitForDeployment() expect(await pinnedConsumer.readValueThroughStaticCall(1)).to.equal(7) }) @@ -250,7 +279,7 @@ describe("MockContract", () => { // real ecdsaWalletRegistry and relay. `hardhat_setCode` replaces the code // and leaves the storage, so a mock keeping its state at slots 0, 1, 2... // would read that leftover as its own. - const address = ethers.utils.getAddress(`0x${"cd".repeat(20)}`) + const address = ethers.getAddress(`0x${"cd".repeat(20)}`) const garbage = "0xdeadbeef00000000000000000000000000000000000000000000000000000001" @@ -258,7 +287,7 @@ describe("MockContract", () => { Array.from({ length: 8 }, (_, slot) => ethers.provider.send("hardhat_setStorageAt", [ address, - ethers.utils.hexValue(slot), + ethers.toQuantity(slot), garbage, ]), ), @@ -272,7 +301,7 @@ describe("MockContract", () => { const factory = await ethers.getContractFactory("MockTargetConsumer") const pinnedConsumer = await factory.deploy(address) - await pinnedConsumer.deployed() + await pinnedConsumer.waitForDeployment() expect(await pinnedConsumer.readValueThroughStaticCall(1)).to.equal(7) }) diff --git a/solidity/ecdsa/test/helpers/mock.ts b/solidity/ecdsa/test/helpers/mock.ts index 22fff97763..5729273e9f 100644 --- a/solidity/ecdsa/test/helpers/mock.ts +++ b/solidity/ecdsa/test/helpers/mock.ts @@ -7,10 +7,18 @@ /* eslint-disable no-underscore-dangle */ import { ethers, artifacts } from "hardhat" import { expect } from "chai" -import { BigNumber } from "ethers" -import type { BigNumberish, Contract, Signer } from "ethers" -import type { FunctionFragment, Interface, ParamType } from "ethers/lib/utils" +import requireResult from "./chain" + +import type { + BaseContract, + BigNumberish, + Signer, + FunctionFragment, + Interface, + ParamType, +} from "ethers" +import type { MockContract } from "../../typechain" /** * Programmable contract mock, replacing `@defi-wonderland/smock`. @@ -57,7 +65,8 @@ import type { FunctionFragment, Interface, ParamType } from "ethers/lib/utils" * the machine happens to be. */ async function withoutAdvancingTime(write: () => Promise): Promise { - const { timestamp } = await ethers.provider.getBlock("latest") + const block = requireResult(await ethers.provider.getBlock("latest")) + const { timestamp } = block await ethers.provider.send("evm_setNextBlockTimestamp", [timestamp]) return write() } @@ -67,7 +76,7 @@ export interface MockCall { /** Decoded arguments, in declaration order. */ args: unknown[] /** `msg.value` the call carried, as smock's `getCall(n).value` did. */ - value: BigNumber + value: bigint } /** Configuration and inspection handle for one function of a mock. */ @@ -95,7 +104,7 @@ export interface MockedFunction { getCalls(): Promise } -export type Mock = { +export type Mock = { [K in keyof T]: T[K] extends (...args: never[]) => unknown ? T[K] & MockedFunction : T[K] @@ -104,14 +113,14 @@ export type Mock = { /** Signer that sends from the mock's own address, as smock's `fake.wallet` did. */ wallet: Signer /** Underlying deployed `MockContract`, for anything this helper does not wrap. */ - mockContract: Contract + mockContract: MockContract /** * The mocked interface bound to `signer`, as smock's `FakeContract.connect` * was. smock's fake extended `ethers.Contract` and inherited this; the proxy * here resolves only the mocked ABI and the keys above, so without it * `mock.connect(someone)` is `undefined`. */ - connect(signer: Signer): Contract + connect(signer: Signer): T /** Drops all configured responses and all recorded calls. */ reset(): Promise /** @@ -125,11 +134,17 @@ export type Mock = { } /** Selectors of `MockContract`'s own administrative entry points. */ +function functionFragments(iface: Interface): FunctionFragment[] { + const fragments: FunctionFragment[] = [] + iface.forEachFunction((fragment) => fragments.push(fragment)) + return fragments +} + function adminSelectors(mockInterface: Interface): Set { return new Set( - Object.keys(mockInterface.functions) - .filter((signature) => signature.startsWith("__mock__")) - .map((signature) => mockInterface.getSighash(signature)), + functionFragments(mockInterface) + .filter((fragment) => fragment.name.startsWith("__mock__")) + .map((fragment) => fragment.selector), ) } @@ -147,8 +162,9 @@ function assertNoSelectorCollision( ): void { const reserved = adminSelectors(mockInterface) - Object.keys(target.functions).forEach((signature) => { - const selector = target.getSighash(signature) + functionFragments(target).forEach((fragment) => { + const signature = fragment.format() + const { selector } = fragment if (reserved.has(selector)) { throw new Error( `${targetName}.${signature} has selector ${selector}, which collides ` + @@ -162,7 +178,7 @@ function assertNoSelectorCollision( function fragmentsByName(target: Interface): Map { const byName = new Map() - Object.values(target.functions).forEach((fragment) => { + functionFragments(target).forEach((fragment) => { const existing = byName.get(fragment.name) if (existing) { existing.push(fragment) @@ -202,7 +218,7 @@ function resolveFragment( * layout. */ function zeroValueFor(type: ParamType): unknown { - if (type.baseType === "array") { + if (type.isArray()) { if (type.arrayLength === -1) { return [] } @@ -211,12 +227,12 @@ function zeroValueFor(type: ParamType): unknown { ) } - if (type.baseType === "tuple") { + if (type.isTuple()) { return type.components.map((component) => zeroValueFor(component)) } if (type.baseType === "address") { - return ethers.constants.AddressZero + return ethers.ZeroAddress } if (type.baseType === "bool") { @@ -249,7 +265,10 @@ function zeroValueFor(type: ParamType): unknown { * those positionally, so they are mapped back by output name. A single-output * function is different: an object there is a struct, and the coder handles it. */ -function toPositional(outputs: ParamType[], value: unknown): unknown[] { +function toPositional( + outputs: readonly ParamType[], + value: unknown, +): unknown[] { if (outputs.length === 1) { return [value] } @@ -273,7 +292,7 @@ function encodeReturn(fragment: FunctionFragment, value: unknown): string { return "0x" } - return ethers.utils.defaultAbiCoder.encode( + return ethers.AbiCoder.defaultAbiCoder().encode( fragment.outputs, toPositional(fragment.outputs, value), ) @@ -285,8 +304,8 @@ function encodeRevert(reason?: string): string { } return ( - ethers.utils.id("Error(string)").slice(0, 10) + - ethers.utils.defaultAbiCoder.encode(["string"], [reason]).slice(2) + ethers.id("Error(string)").slice(0, 10) + + ethers.AbiCoder.defaultAbiCoder().encode(["string"], [reason]).slice(2) ) } @@ -300,18 +319,20 @@ function encodeRevert(reason?: string): string { * @returns A handle exposing each of `target`'s functions with `returns`, * `whenCalledWith`, `reverts`, `reset`, `callCount` and `getCall`. */ -export async function createMock( +export async function createMock( target: string, options: { address?: string } = {}, ): Promise> { const targetArtifact = await artifacts.readArtifact(target) - const targetInterface = new ethers.utils.Interface(targetArtifact.abi) + const targetInterface = new ethers.Interface(targetArtifact.abi) const mockFactory = await ethers.getContractFactory("MockContract") // Deploying is a transaction too, and a mock is routinely created inside a // `before` hook after the test has already captured a baseline timestamp. - let mockContract = await withoutAdvancingTime(() => mockFactory.deploy()) - await mockContract.deployed() + let mockContract: MockContract = await withoutAdvancingTime(() => + mockFactory.deploy(), + ) + await mockContract.waitForDeployment() assertNoSelectorCollision(targetInterface, mockContract.interface, target) @@ -321,21 +342,19 @@ export async function createMock( // configuration below — the base returns, the non-recording flags, and // later every `returns`/`whenCalledWith` — is storage. Configuring first // and relocating afterwards left a pinned mock with none of it. - const code = await ethers.provider.getCode(mockContract.address) + const code = await ethers.provider.getCode(await mockContract.getAddress()) await ethers.provider.send("hardhat_setCode", [options.address, code]) - mockContract = mockContract.attach(options.address) + mockContract = await ethers.getContractAt("MockContract", options.address) } // Install the response of last resort for every function, so an unstubbed // one answers with a correctly sized zero instead of reverting the caller. - const baseFragments = Object.values(targetInterface.functions) - const baseSelectors = baseFragments.map((fragment) => - targetInterface.getSighash(fragment), - ) + const baseFragments = functionFragments(targetInterface) + const baseSelectors = baseFragments.map((fragment) => fragment.selector) const baseReturns = baseFragments.map((fragment) => fragment.outputs == null || fragment.outputs.length === 0 ? "0x" - : ethers.utils.defaultAbiCoder.encode( + : ethers.AbiCoder.defaultAbiCoder().encode( fragment.outputs, fragment.outputs.map((output) => zeroValueFor(output)), ), @@ -354,27 +373,26 @@ export async function createMock( fragment.stateMutability === "view" || fragment.stateMutability === "pure", ) - .map((fragment) => targetInterface.getSighash(fragment)) + .map((fragment) => fragment.selector) if (nonRecordingSelectors.length > 0) { await withoutAdvancingTime(() => mockContract.__mock__setNonRecordingSelectors(nonRecordingSelectors), ) } - await ethers.provider.send("hardhat_impersonateAccount", [ - mockContract.address, - ]) + const address = await mockContract.getAddress() + await ethers.provider.send("hardhat_impersonateAccount", [address]) await ethers.provider.send("hardhat_setBalance", [ - mockContract.address, + address, "0x21e19e0c9bab2400000", // 10_000 ETH, so the mock can pay for its own sends ]) - const wallet = await ethers.getSigner(mockContract.address) + const wallet = await ethers.getSigner(address) const byName = fragmentsByName(targetInterface) function buildFunction(name: string): MockedFunction { const fragment = resolveFragment(byName.get(name) ?? [], name, target) - const selector = targetInterface.getSighash(fragment) + const { selector } = fragment const readOnly = fragment.stateMutability === "view" || fragment.stateMutability === "pure" @@ -433,7 +451,7 @@ export async function createMock( ) } - const decodeCall = (callData: string, value: BigNumber): MockCall => ({ + const decodeCall = (callData: string, value: bigint): MockCall => ({ args: Array.from( targetInterface.decodeFunctionData(fragment, callData), ) as unknown[], @@ -487,7 +505,7 @@ export async function createMock( mockContract.__mock__callForSelectorAt(selector, index), mockContract.__mock__callValueForSelectorAt(selector, index), ]) - return decodeCall(callData as string, value as BigNumber) + return decodeCall(callData as string, value as bigint) }, async getCalls(): Promise { @@ -504,7 +522,7 @@ export async function createMock( mockContract.__mock__callForSelectorAt(selector, i), mockContract.__mock__callValueForSelectorAt(selector, i), ]) - calls.push(decodeCall(callData as string, value as BigNumber)) + calls.push(decodeCall(callData as string, value as bigint)) } return calls @@ -514,21 +532,21 @@ export async function createMock( const functions = new Map() const readContract = new ethers.Contract( - mockContract.address, + address, targetArtifact.abi, ethers.provider, ) const handle = { - address: mockContract.address, + address, wallet, mockContract, - connect(signer: Signer): Contract { + connect(signer: Signer): T { return new ethers.Contract( - mockContract.address, + address, targetArtifact.abi, signer, - ) + ) as unknown as T }, async reset(): Promise { await withoutAdvancingTime(() => mockContract.__mock__reset()) @@ -613,13 +631,9 @@ export async function expectCalledTwice(fn: MockedFunction): Promise { /** * Puts one recorded or expected argument into a comparable form. * - * The two sides never arrive in the same representation. ethers decodes an ABI - * integer to a `BigNumber` above 48 bits and to a plain `number` at or below - * it, so a `uint256` argument reaches this as a `BigNumber` while the - * `uint32` getter the test compared it against yields a `number`; and a struct - * or dynamic array puts both one level down, where the previous top-level-only - * check never looked. smock compared `BigNumberish` values numerically at any - * depth, so both shapes used to pass. + * ethers v6 decodes every ABI integer as a bigint, while test expectations + * can contain ordinary numbers. Arrays and structs can nest those values, + * so numeric comparison is normalized recursively. * * Numerics are wrapped rather than rendered bare, so that a genuine string * argument of `"100"` still fails against a numeric `100`. Everything else — @@ -628,9 +642,6 @@ export async function expectCalledTwice(fn: MockedFunction): Promise { * real mismatch. */ function normalizeForComparison(value: unknown): unknown { - if (BigNumber.isBigNumber(value)) { - return { numeric: value.toString() } - } if (typeof value === "number" || typeof value === "bigint") { return { numeric: value.toString() } } diff --git a/solidity/ecdsa/test/tasks/initialize.test.ts b/solidity/ecdsa/test/tasks/initialize.test.ts new file mode 100644 index 0000000000..a1fcf0e787 --- /dev/null +++ b/solidity/ecdsa/test/tasks/initialize.test.ts @@ -0,0 +1,102 @@ +import hre, { deployments, ethers, helpers } from "hardhat" +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" +import { expect } from "chai" + +import type { + WalletRegistry, + TokenStaking, + T, + SortitionPool, +} from "../../typechain" + +async function taskContracts() { + await deployments.fixture() + const [owner, provider, operator, beneficiary, authorizer] = ( + await ethers.getSigners() + ).slice(10) + return { + args: { + owner: owner.address, + provider: provider.address, + operator: operator.address, + beneficiary: beneficiary.address, + authorizer: authorizer.address, + amount: 1_000_000, + }, + staking: await helpers.contracts.getContract("TokenStaking"), + registry: + await helpers.contracts.getContract("WalletRegistry"), + token: await helpers.contracts.getContract("T"), + pool: await helpers.contracts.getContract( + "EcdsaSortitionPool", + ), + } +} + +async function initializedOperator() { + const contracts = await taskContracts() + await hre.run("initialize", contracts.args) + return contracts +} + +describe("ECDSA initialization tasks", () => { + it("initializes staking with distinct beneficiary and authorizer accounts", async () => { + const { args, staking, token } = await loadFixture(taskContracts) + await hre.run("initialize:staking", args) + expect((await staking.stakes(args.provider)).tStake).to.equal( + ethers.parseEther("1000000"), + ) + expect(await staking.rolesOf(args.provider)).to.deep.equal([ + args.owner, + args.beneficiary, + args.authorizer, + ]) + expect(await token.balanceOf(args.owner)).to.equal(0n) + }) + + it("registers an operator through register:ecdsa", async () => { + const { args, registry } = await loadFixture(taskContracts) + await hre.run("register:ecdsa", args) + expect(await registry.operatorToStakingProvider(args.operator)).to.equal( + args.provider, + ) + }) + + it("initializes staking, minimum authorization, registration and beta membership", async () => { + const { args, staking, registry, pool } = + await loadFixture(initializedOperator) + expect((await staking.stakes(args.provider)).tStake).to.equal( + ethers.parseEther("1000000"), + ) + expect( + await staking.authorizedStake(args.provider, await registry.getAddress()), + ).to.equal(await registry.minimumAuthorization()) + expect(await registry.operatorToStakingProvider(args.operator)).to.equal( + args.provider, + ) + expect(await pool.isBetaOperator(args.operator)).to.equal(true) + }) + + it("does not send another transaction when stake, authorization and registration match", async () => { + const { args } = await loadFixture(initializedOperator) + const before = await ethers.provider.getBlockNumber() + await hre.run("initialize:staking", args) + await hre.run("authorize:ecdsa", args) + await hre.run("register:ecdsa", args) + expect(await ethers.provider.getBlockNumber()).to.equal(before) + }) + + it("tops up an existing stake and increases ECDSA authorization", async () => { + const { args, staking, registry, token } = + await loadFixture(initializedOperator) + await hre.run("initialize:staking", { ...args, amount: 1_200_000 }) + await hre.run("authorize:ecdsa", { ...args, authorization: 700_000 }) + expect((await staking.stakes(args.provider)).tStake).to.equal( + ethers.parseEther("1200000"), + ) + expect( + await staking.authorizedStake(args.provider, await registry.getAddress()), + ).to.equal(ethers.parseEther("700000")) + expect(await token.balanceOf(args.owner)).to.equal(0n) + }) +}) diff --git a/solidity/ecdsa/test/tasks/unlock-accounts.test.ts b/solidity/ecdsa/test/tasks/unlock-accounts.test.ts new file mode 100644 index 0000000000..7984761d30 --- /dev/null +++ b/solidity/ecdsa/test/tasks/unlock-accounts.test.ts @@ -0,0 +1,63 @@ +import hre, { ethers } from "hardhat" +import { expect } from "chai" + +import type { HttpNetworkConfig } from "hardhat/types" + +describe("ECDSA account unlock task", () => { + it("uses the ethers v6 provider and signer APIs on development", async () => { + const account = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" + const requests: { + method: string + params: Array | Record + }[] = [] + + // Exercise the registered task without opening an RPC connection. + class TestProvider extends ethers.JsonRpcProvider { + private readonly rpcRequests = requests + + async listAccounts() { + return [new ethers.JsonRpcSigner(this, account)] + } + + async send( + method: string, + params: Array | Record, + ) { + this.rpcRequests.push({ method, params }) + return true + } + } + + const taskRuntime = { + ...hre, + ethers: { ...ethers, JsonRpcProvider: TestProvider }, + network: { + ...hre.network, + name: "development", + config: { url: "http://unused.invalid" } as HttpNetworkConfig, + }, + } + const password = process.env.KEEP_ETHEREUM_PASSWORD + process.env.KEEP_ETHEREUM_PASSWORD = "task-test-password" + try { + await hre.tasks["unlock-accounts"].action( + {}, + taskRuntime, + Object.assign(async () => undefined, { isDefined: false }), + ) + } finally { + if (password === undefined) { + delete process.env.KEEP_ETHEREUM_PASSWORD + } else { + process.env.KEEP_ETHEREUM_PASSWORD = password + } + } + + expect(requests).to.deep.equal([ + { + method: "personal_unlockAccount", + params: [account.toLowerCase(), "task-test-password", 0], + }, + ]) + }) +}) diff --git a/solidity/ecdsa/test/utils/dkg.ts b/solidity/ecdsa/test/utils/dkg.ts index 6e6dcedcee..17d9cb3422 100644 --- a/solidity/ecdsa/test/utils/dkg.ts +++ b/solidity/ecdsa/test/utils/dkg.ts @@ -2,12 +2,17 @@ import { ethers } from "hardhat" import { expect } from "chai" -import { BigNumber } from "ethers" + +import requireResult from "../helpers/chain" import { selectGroup } from "./groups" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { BigNumberish, ContractTransaction, BytesLike } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { + BigNumberish, + ContractTransactionResponse, + BytesLike, +} from "ethers" import type { SortitionPool, WalletRegistry } from "../../typechain" import type { Operator } from "./operators" import type { @@ -35,12 +40,12 @@ export const noMisbehaved: number[] = [] export function calculateDkgSeed( relayEntry: BigNumberish, blockNumber: BigNumberish, -): BigNumber { - return ethers.BigNumber.from( - ethers.utils.keccak256( - ethers.utils.solidityPack( +): bigint { + return BigInt( + ethers.keccak256( + ethers.solidityPacked( ["uint256", "uint256"], - [ethers.BigNumber.from(relayEntry), ethers.BigNumber.from(blockNumber)], + [BigInt(relayEntry), BigInt(blockNumber)], ), ), ) @@ -52,7 +57,7 @@ export function calculateDkgSeed( export async function signAndSubmitCorrectDkgResult( walletRegistry: WalletRegistry, groupPublicKey: BytesLike, - seed: BigNumber, + seed: bigint, startBlock: number, misbehavedIndices = noMisbehaved, submitterIndex = 1, @@ -62,8 +67,8 @@ export async function signAndSubmitCorrectDkgResult( dkgResult: DkgResult dkgResultHash: string submitter: SignerWithAddress - submitterInitialBalance: BigNumber - transaction: ContractTransaction + submitterInitialBalance: bigint + transaction: ContractTransactionResponse }> { const sortitionPool = (await ethers.getContractAt( "SortitionPool", @@ -104,8 +109,8 @@ export async function signAndSubmitArbitraryDkgResult( dkgResult: DkgResult dkgResultHash: string submitter: SignerWithAddress - submitterInitialBalance: BigNumber - transaction: ContractTransaction + submitterInitialBalance: bigint + transaction: ContractTransactionResponse }> { const { dkgResult } = await signDkgResult( signers, @@ -116,8 +121,8 @@ export async function signAndSubmitArbitraryDkgResult( numberOfSignatures, ) - const dkgResultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const dkgResultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( [DKG_RESULT_PARAMS_SIGNATURE], [dkgResult], ), @@ -152,7 +157,7 @@ export async function signAndSubmitUnrecoverableDkgResult( dkgResult: DkgResult dkgResultHash: string submitter: SignerWithAddress - transaction: ContractTransaction + transaction: ContractTransactionResponse }> { const { dkgResult } = await signDkgResult( signers, @@ -170,8 +175,8 @@ export async function signAndSubmitUnrecoverableDkgResult( )}` dkgResult.signatures = unrecoverableSignatures - const dkgResultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const dkgResultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( [DKG_RESULT_PARAMS_SIGNATURE], [dkgResult], ), @@ -199,8 +204,8 @@ export async function signDkgResult( signingMembersIndices: number[] signaturesBytes: string }> { - const resultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const resultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( ["uint256", "bytes", "uint8[]", "uint256"], [hardhatNetworkId, groupPublicKey, misbehavedMembersIndices, startBlock], ), @@ -223,13 +228,13 @@ export async function signDkgResult( signingMembersIndices.push(signerIndex) const signature = await ethersSigner.signMessage( - ethers.utils.arrayify(resultHash), + ethers.getBytes(resultHash), ) signatures.push(signature) } - const signaturesBytes: string = ethers.utils.hexConcat(signatures) + const signaturesBytes: string = ethers.concat(signatures) const dkgResult: DkgResult = { submitterMemberIndex: submitterIndex, @@ -249,7 +254,7 @@ export async function submitDkgResult( dkgResult: DkgResult, submitter: SignerWithAddress, ): Promise<{ - transaction: ContractTransaction + transaction: ContractTransactionResponse }> { const transaction = await walletRegistry .connect(submitter) @@ -271,19 +276,22 @@ export function hashDKGMembers( } } - return ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [activeDkgMembers]), + return ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint32[]"], + [activeDkgMembers], + ), ) } - return ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [members]), + return ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode(["uint32[]"], [members]), ) } export interface DkgResultSubmittedEventArgs { resultHash: string - seed: BigNumber + seed: bigint result: EcdsaDkg.ResultStruct } @@ -291,13 +299,15 @@ export interface DkgResultSubmittedEventArgs { // for Waffle's inability to verify events with an array nested in a struct. // See: https://github.com/EthWorks/Waffle/issues/245 export async function expectDkgResultSubmittedEvent( - tx: ContractTransaction, + tx: ContractTransactionResponse, expectedArgs: DkgResultSubmittedEventArgs, ): Promise { const eventName = "DkgResultSubmitted" - const event = (await tx.wait()).events?.find((e) => e.event === eventName) as - DkgResultSubmittedEvent | undefined + const event = requireResult(await tx.wait()).logs.find( + (log): log is DkgResultSubmittedEvent.Log => + log instanceof ethers.EventLog && log.eventName === eventName, + ) if (!event) { throw new Error(`Event ${eventName} not emitted`) @@ -333,7 +343,7 @@ export async function expectDkgResultSubmittedEvent( await expect( actualArgs.result.misbehavedMembersIndices, "invalid misbehavedMembersIndices", - ).to.be.deep.equal(expectedArgs.result.misbehavedMembersIndices) + ).to.be.deep.equal(expectedArgs.result.misbehavedMembersIndices.map(BigInt)) await expect(actualArgs.result.signatures, "invalid signatures").to.be.equal( expectedArgs.result.signatures, @@ -342,12 +352,10 @@ export async function expectDkgResultSubmittedEvent( await expect( actualArgs.result.signingMembersIndices, "invalid signingMembersIndices", - ).to.be.deep.equal( - expectedArgs.result.signingMembersIndices.map(BigNumber.from), - ) + ).to.be.deep.equal(expectedArgs.result.signingMembersIndices.map(BigInt)) await expect(actualArgs.result.members, "invalid members").to.be.deep.equal( - expectedArgs.result.members, + expectedArgs.result.members.map(BigInt), ) await expect( diff --git a/solidity/ecdsa/test/utils/groups.ts b/solidity/ecdsa/test/utils/groups.ts index a7a634e2cf..3c6ba8ea84 100644 --- a/solidity/ecdsa/test/utils/groups.ts +++ b/solidity/ecdsa/test/utils/groups.ts @@ -1,27 +1,32 @@ +import { toBeHex } from "ethers" import { ethers } from "hardhat" import { constants } from "../fixtures" -import type { BigNumber, BigNumberish } from "ethers" +import type { BigNumberish } from "ethers" import type { Operator } from "./operators" import type { SortitionPool } from "../../typechain" -const { keccak256, defaultAbiCoder } = ethers.utils +const { keccak256 } = ethers +const defaultAbiCoder = ethers.AbiCoder.defaultAbiCoder() export async function selectGroup( sortitionPool: SortitionPool, - seed: BigNumber, + seed: bigint, ): Promise { - const identifiers = await sortitionPool.selectGroup( - constants.groupSize, - ethers.utils.hexZeroPad(seed.toHexString(), 32), + // Copy the immutable ethers Result before passing these IDs to another call. + const identifiers = Array.from( + await sortitionPool.selectGroup( + constants.groupSize, + ethers.zeroPadValue(toBeHex(seed), 32), + ), ) const addresses = await sortitionPool.getIDOperators(identifiers) return Promise.all( identifiers.map(async (identifier, i): Promise => ({ - id: identifier, + id: Number(identifier), signer: await ethers.getSigner(addresses[i]), })), ) diff --git a/solidity/ecdsa/test/utils/inactivity.ts b/solidity/ecdsa/test/utils/inactivity.ts index e5de2ab144..90f6e5311d 100644 --- a/solidity/ecdsa/test/utils/inactivity.ts +++ b/solidity/ecdsa/test/utils/inactivity.ts @@ -17,8 +17,8 @@ export async function signOperatorInactivityClaim( signatures: string signingMembersIndices: number[] }> { - const messageHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const messageHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( ["uint256", "uint256", "bytes", "uint8[]", "bool"], [ hardhatNetworkId, @@ -45,14 +45,14 @@ export async function signOperatorInactivityClaim( // eslint-disable-next-line no-await-in-loop const signature = await signers[i].signer.signMessage( - ethers.utils.arrayify(messageHash), + ethers.getBytes(messageHash), ) signatures.push(signature) } return { - signatures: ethers.utils.hexConcat(signatures), + signatures: ethers.concat(signatures), signingMembersIndices, } } diff --git a/solidity/ecdsa/test/utils/operators.ts b/solidity/ecdsa/test/utils/operators.ts index 97b0ff4b8d..8ad85e13a9 100644 --- a/solidity/ecdsa/test/utils/operators.ts +++ b/solidity/ecdsa/test/utils/operators.ts @@ -36,8 +36,8 @@ import { ethers, helpers } from "hardhat" import { params } from "../fixtures" import { testConfig } from "../../hardhat.config" -import type { BigNumber, BigNumberish, Contract } from "ethers" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { BigNumberish, Contract } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { WalletRegistry, T, @@ -47,7 +47,7 @@ import type { } from "../../typechain" /** Minimal ABI for legacy TokenStaking methods not present on the generated typechain ABI. */ -const legacyTokenStakingIface = new ethers.utils.Interface([ +const legacyTokenStakingIface = new ethers.Interface([ "function stake(address,address,address,uint96)", "function increaseAuthorization(address,address,uint96)", "function approveApplication(address)", @@ -55,10 +55,10 @@ const legacyTokenStakingIface = new ethers.utils.Interface([ ]) export function legacyTokenStakingAt( - staking: Pick, + staking: Pick, signer: SignerWithAddress, ): Contract { - return new ethers.Contract(staking.address, legacyTokenStakingIface, signer) + return new ethers.Contract(staking, legacyTokenStakingIface, signer) } export type OperatorID = number @@ -116,7 +116,7 @@ export async function registerOperators( t: T, numberOfOperators = testConfig.operatorsCount, unnamedSignersOffset = testConfig.nonStakingAccountsCount, - stakeAmount: BigNumber = params.minimumAuthorization, + stakeAmount: bigint = params.minimumAuthorization, authorizationSource?: Allowlist, ): Promise { const operators: Operator[] = [] @@ -191,7 +191,7 @@ export async function registerOperators( await walletRegistry.connect(operator).joinSortitionPool() - const id = await sortitionPool.getOperatorID(operator.address) + const id = Number(await sortitionPool.getOperatorID(operator.address)) operators.push({ id, signer: operator, stakingProvider }) } @@ -227,7 +227,7 @@ export async function registerOperators( * is managed directly via Allowlist.addStakingProvider() without token staking. * * @example - * await stake(tToken, tokenStaking, walletRegistry, owner, provider, ethers.utils.parseEther("40000")) + * await stake(tToken, tokenStaking, walletRegistry, owner, provider, ethers.parseEther("40000")) */ export async function stake( t: T, @@ -242,7 +242,7 @@ export async function stake( const { deployer } = await helpers.signers.getNamedSigners() await t.connect(deployer).mint(owner.address, stakeAmount) - await t.connect(owner).approve(staking.address, stakeAmount) + await t.connect(owner).approve(await staking.getAddress(), stakeAmount) await legacyTokenStakingAt(staking, owner).stake( stakingProvider.address, @@ -253,7 +253,7 @@ export async function stake( await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakeAmount, ) } diff --git a/solidity/ecdsa/test/utils/random-beacon-export.test.ts b/solidity/ecdsa/test/utils/random-beacon-export.test.ts new file mode 100644 index 0000000000..72575c9182 --- /dev/null +++ b/solidity/ecdsa/test/utils/random-beacon-export.test.ts @@ -0,0 +1,174 @@ +import fs from "fs" +import os from "os" +import path from "path" + +import { expect } from "chai" + +import resolveRandomBeaconExport, { + resolveRandomBeaconExportIn, +} from "../../utils/random-beacon-export" + +const temporaryRoots: string[] = [] + +function temporaryRoot(...subdirectories: string[]): string { + const root = fs.mkdtempSync(path.join(os.tmpdir(), "beacon-export-")) + temporaryRoots.push(root) + subdirectories.forEach((subdirectory) => { + fs.mkdirSync(path.join(root, subdirectory), { recursive: true }) + }) + return root +} + +// utils/ sits inside the package, so the source root is the package root. +function sourceCheckout(root: string): string { + const packageRoot = path.join(root, "ecdsa") + fs.mkdirSync(packageRoot, { recursive: true }) + fs.writeFileSync(path.join(packageRoot, "hardhat.config.ts"), "") + return packageRoot +} + +function record(logs: string[]): (message: string) => void { + return (message) => { + logs.push(message) + } +} + +describe("resolveRandomBeaconExport", () => { + const originalExportPath = process.env.RANDOM_BEACON_EXPORT_PATH + + beforeEach(() => { + delete process.env.RANDOM_BEACON_EXPORT_PATH + }) + + afterEach(() => { + if (originalExportPath === undefined) { + delete process.env.RANDOM_BEACON_EXPORT_PATH + } else { + process.env.RANDOM_BEACON_EXPORT_PATH = originalExportPath + } + temporaryRoots.splice(0).forEach((root) => { + fs.rmSync(root, { recursive: true, force: true }) + }) + }) + + it("resolves the configured export path", () => { + const root = temporaryRoot("export/deploy") + process.env.RANDOM_BEACON_EXPORT_PATH = path.join(root, "export") + const logs: string[] = [] + const resolved = resolveRandomBeaconExportIn( + "deploy", + { sourceRoot: root, packageRoot: root }, + record(logs), + ) + expect(resolved).to.equal(path.join(root, "export", "deploy")) + expect(logs).to.deep.equal([ + `Random Beacon deploy from RANDOM_BEACON_EXPORT_PATH: ${resolved}`, + ]) + }) + + it("throws when the configured path misses the export", () => { + const root = temporaryRoot("export/deploy") + process.env.RANDOM_BEACON_EXPORT_PATH = path.join(root, "export") + const missingArtifacts = () => + resolveRandomBeaconExportIn( + "artifacts", + { sourceRoot: root, packageRoot: root }, + record([]), + ) + expect(missingArtifacts).to.throw( + /Random Beacon artifacts export is missing/, + ) + }) + + it("prefers the sibling checkout over the bundled scripts", () => { + const root = temporaryRoot( + "random-beacon/export/deploy", + "ecdsa/external/random-beacon-export/deploy", + ) + const packageRoot = sourceCheckout(root) + const logs: string[] = [] + const resolved = resolveRandomBeaconExportIn( + "deploy", + { sourceRoot: packageRoot, packageRoot }, + record(logs), + ) + expect(resolved).to.equal(path.join(root, "random-beacon/export/deploy")) + expect(logs).to.deep.equal([ + `Random Beacon deploy from the sibling checkout: ${resolved}`, + ]) + }) + + it("throws when the sibling checkout is partially built", () => { + const root = temporaryRoot( + "random-beacon/export/deploy", + "ecdsa/external/random-beacon-export/deploy", + ) + const packageRoot = sourceCheckout(root) + const partialSibling = () => + resolveRandomBeaconExportIn( + "artifacts", + { sourceRoot: packageRoot, packageRoot }, + record([]), + ) + expect(partialSibling).to.throw(/missing in the sibling checkout/) + }) + + it("uses the bundled scripts without a sibling checkout", () => { + const root = temporaryRoot("ecdsa/external/random-beacon-export/tasks") + const packageRoot = sourceCheckout(root) + const logs: string[] = [] + const resolved = resolveRandomBeaconExportIn( + "tasks", + { sourceRoot: packageRoot, packageRoot }, + record(logs), + ) + expect(resolved).to.equal( + path.join(packageRoot, "external/random-beacon-export/tasks"), + ) + expect(logs).to.deep.equal([ + `Random Beacon tasks from the bundled copy: ${resolved}`, + ]) + }) + + it("never falls back to the npm package for deploy scripts", () => { + const root = temporaryRoot("ecdsa") + const packageRoot = path.join(root, "ecdsa") + const missingBundle = () => + resolveRandomBeaconExportIn( + "deploy", + { sourceRoot: packageRoot, packageRoot }, + record([]), + ) + expect(missingBundle).to.throw(/Random Beacon deploy export is missing/) + }) + + it("never resolves artifacts from the bundled export", () => { + const root = temporaryRoot("ecdsa/external/random-beacon-export/artifacts") + const packageRoot = path.join(root, "ecdsa") + const logs: string[] = [] + const resolved = resolveRandomBeaconExportIn( + "artifacts", + { sourceRoot: packageRoot, packageRoot }, + record(logs), + ) + expect(resolved).to.not.match(/external[\\/]random-beacon-export/) + expect(resolved).to.equal( + path.join( + path.dirname( + require.resolve("@keep-network/random-beacon/package.json"), + ), + "export", + "artifacts", + ), + ) + expect(logs).to.deep.equal([ + `Random Beacon artifacts from the installed npm package: ${resolved}`, + ]) + }) + + it("resolves artifacts outside the bundled export", () => { + expect(resolveRandomBeaconExport("artifacts")).to.not.match( + /external[\\/]random-beacon-export/, + ) + }) +}) diff --git a/solidity/ecdsa/test/utils/randomBeacon.ts b/solidity/ecdsa/test/utils/randomBeacon.ts index beba15d751..007707c599 100644 --- a/solidity/ecdsa/test/utils/randomBeacon.ts +++ b/solidity/ecdsa/test/utils/randomBeacon.ts @@ -1,8 +1,9 @@ +import { toBigInt } from "ethers" import { ethers } from "hardhat" +import requireResult from "../helpers/chain" import { createMock } from "../helpers/mock" -import type { BigNumber } from "ethers" import type { WalletRegistry, IRandomBeacon } from "../../typechain" import type { Mock } from "../helpers/mock" @@ -10,14 +11,14 @@ export async function fakeRandomBeacon( walletRegistry: WalletRegistry, ): Promise> { const randomBeacon = await createMock("IRandomBeacon", { - address: await walletRegistry.callStatic.randomBeacon(), + address: await walletRegistry.randomBeacon.staticCall(), }) await ( await ethers.getSigners() )[0].sendTransaction({ to: randomBeacon.address, - value: ethers.utils.parseEther("1000"), + value: ethers.parseEther("1000"), }) return randomBeacon @@ -28,24 +29,22 @@ export async function submitRelayEntry( randomBeacon?: Mock, ): Promise<{ startBlock: number - dkgSeed: BigNumber + dkgSeed: bigint }> { if (!randomBeacon) { // eslint-disable-next-line no-param-reassign randomBeacon = await fakeRandomBeacon(walletRegistry) } - const relayEntry: BigNumber = ethers.BigNumber.from( - ethers.utils.randomBytes(32), - ) + const relayEntry: bigint = toBigInt(ethers.randomBytes(32)) // eslint-disable-next-line no-underscore-dangle const tx = await walletRegistry .connect(randomBeacon.wallet) - .__beaconCallback(relayEntry, 0) + .__beaconCallback(ethers.toBigInt(relayEntry), 0) return { - startBlock: (await tx.wait()).blockNumber, + startBlock: requireResult(await tx.wait()).blockNumber, dkgSeed: relayEntry, } } diff --git a/solidity/ecdsa/test/utils/wallets.ts b/solidity/ecdsa/test/utils/wallets.ts index 57989a257f..0a86d58240 100644 --- a/solidity/ecdsa/test/utils/wallets.ts +++ b/solidity/ecdsa/test/utils/wallets.ts @@ -1,5 +1,6 @@ import { helpers, ethers } from "hardhat" +import requireResult from "../helpers/chain" import { params } from "../fixtures" import ecdsaData from "../data/ecdsa" @@ -9,10 +10,10 @@ import type { Mock } from "../helpers/mock" import type { DkgResult } from "./dkg" import type { IRandomBeacon, WalletRegistry } from "../../typechain" import type { Operator } from "./operators" -import type { BytesLike, ContractTransaction, Signer } from "ethers" +import type { BytesLike, ContractTransactionResponse, Signer } from "ethers" const { mineBlocks } = helpers.time -const { keccak256 } = ethers.utils +const { keccak256 } = ethers // eslint-disable-next-line import/prefer-default-export export async function createNewWallet( @@ -24,20 +25,20 @@ export async function createNewWallet( members: Operator[] dkgResult: DkgResult walletID: string - tx: ContractTransaction + tx: ContractTransactionResponse }> { const requestNewWalletTx = await walletRegistry .connect(walletOwner) .requestNewWallet() - const relayEntry = ethers.utils.randomBytes(32) + const relayEntry = ethers.randomBytes(32) - const dkgSeed = ethers.BigNumber.from(keccak256(relayEntry)) + const dkgSeed = BigInt(keccak256(relayEntry)) // eslint-disable-next-line no-underscore-dangle await walletRegistry .connect(randomBeacon.wallet) - .__beaconCallback(relayEntry, 0) + .__beaconCallback(ethers.toBigInt(relayEntry), 0) const { dkgResult, @@ -47,7 +48,7 @@ export async function createNewWallet( walletRegistry, publicKey, dkgSeed, - (await requestNewWalletTx.wait()).blockNumber, + requireResult(await requestNewWalletTx.wait()).blockNumber, noMisbehaved, ) diff --git a/solidity/ecdsa/tsconfig.json b/solidity/ecdsa/tsconfig.json index 752a1dd6a4..eba3777f16 100644 --- a/solidity/ecdsa/tsconfig.json +++ b/solidity/ecdsa/tsconfig.json @@ -6,6 +6,7 @@ "./test", "./typechain", "./types", + "./utils", "./scripts" ], "compilerOptions": { diff --git a/solidity/ecdsa/types/random-beacon.d.ts b/solidity/ecdsa/types/random-beacon.d.ts index 1fae6ffabb..ee84a77e64 100644 --- a/solidity/ecdsa/types/random-beacon.d.ts +++ b/solidity/ecdsa/types/random-beacon.d.ts @@ -1,19 +1,18 @@ -// The published ethers-v5 Random Beacon package does not include declarations -// for these task exports. Keep this narrow compatibility surface in sync with -// random-beacon/tasks until its published package supplies the declarations. -declare module "@keep-network/random-beacon/export/tasks/initialize" { - export const TASK_INITIALIZE: string - export const TASK_INITIALIZE_STAKING: string - export const TASK_AUTHORIZE: string - export const TASK_REGISTER: string - export const TASK_ADD_BETA_OPERATOR: string -} +import type { BigNumberish } from "ethers" +import type { HardhatRuntimeEnvironment } from "hardhat/types" -declare module "@keep-network/random-beacon/export/tasks/utils" { - import type { BigNumberish } from "ethers" - import type { HardhatRuntimeEnvironment } from "hardhat/types" +// The resolved Beacon task exports are generated JavaScript. Keep this narrow +// interface in sync with the ethers v6 source in random-beacon/tasks. +export interface InitializationTasks { + TASK_INITIALIZE: string + TASK_INITIALIZE_STAKING: string + TASK_AUTHORIZE: string + TASK_REGISTER: string + TASK_ADD_BETA_OPERATOR: string +} - export function authorize( +export interface TaskUtils { + authorize( hre: HardhatRuntimeEnvironment, deploymentName: string, owner: string, @@ -22,14 +21,14 @@ declare module "@keep-network/random-beacon/export/tasks/utils" { authorization?: BigNumberish, ): Promise - export function register( + register( hre: HardhatRuntimeEnvironment, deploymentName: string, provider: string, operator: string, ): Promise - export function addBetaOperator( + addBetaOperator( hre: HardhatRuntimeEnvironment, sortitionPoolDeploymentName: string, operator: string, diff --git a/solidity/ecdsa/utils/random-beacon-export.ts b/solidity/ecdsa/utils/random-beacon-export.ts new file mode 100644 index 0000000000..8c02d4106c --- /dev/null +++ b/solidity/ecdsa/utils/random-beacon-export.ts @@ -0,0 +1,90 @@ +import fs from "fs" +import path from "path" + +// This module also runs from export/utils in a packed ECDSA package. +const sourceRoot = path.resolve(__dirname, "..") +const packageRoot = fs.existsSync(path.join(sourceRoot, "package.json")) + ? sourceRoot + : path.dirname(sourceRoot) + +export type RandomBeaconExportKind = "deploy" | "artifacts" | "tasks" + +export interface RandomBeaconExportRoots { + /** Directory holding this module's parent: a checkout or a packed export. */ + sourceRoot: string + /** Directory holding the ECDSA package.json. */ + packageRoot: string +} + +/** + * Resolves a Random Beacon export directory and logs the producer it came + * from. Every subdirectory comes from a single producer: the sibling checkout + * is selected on its export root alone, so a half-built sibling fails loudly + * instead of pairing its fresh deploy scripts with another producer's + * artifacts. + */ +export function resolveRandomBeaconExportIn( + subdir: RandomBeaconExportKind, + roots: RandomBeaconExportRoots, + log: (message: string) => void = console.log, +): string { + // Explicit producer checks must never fall back to another package's code. + const exportRoot = process.env.RANDOM_BEACON_EXPORT_PATH + if (exportRoot) { + const configured = path.resolve(exportRoot, subdir) + if (!fs.existsSync(configured)) { + throw new Error( + `Random Beacon ${subdir} export is missing: ${configured}`, + ) + } + log(`Random Beacon ${subdir} from RANDOM_BEACON_EXPORT_PATH: ${configured}`) + return configured + } + + // Published packages have only export/hardhat.config.js. Without a source + // config, the adjacent random-beacon is an npm dependency, potentially v5. + const siblingRoot = path.join(roots.packageRoot, "../random-beacon/export") + if ( + fs.existsSync(path.join(roots.sourceRoot, "hardhat.config.ts")) && + fs.existsSync(siblingRoot) + ) { + const sibling = path.join(siblingRoot, subdir) + if (!fs.existsSync(sibling)) { + throw new Error( + `Random Beacon ${subdir} export is missing in the sibling checkout: ${sibling}`, + ) + } + log(`Random Beacon ${subdir} from the sibling checkout: ${sibling}`) + return sibling + } + + // ECDSA never bundles Beacon artifacts, so only they may come from the + // installed package. Deploy scripts and tasks ship with this package and + // must never be paired with a possibly v5 dependency. + if (subdir === "artifacts") { + const installed = path.join( + path.dirname(require.resolve("@keep-network/random-beacon/package.json")), + "export", + subdir, + ) + log(`Random Beacon ${subdir} from the installed npm package: ${installed}`) + return installed + } + + const bundled = path.join( + roots.packageRoot, + "external/random-beacon-export", + subdir, + ) + if (!fs.existsSync(bundled)) { + throw new Error(`Random Beacon ${subdir} export is missing: ${bundled}`) + } + log(`Random Beacon ${subdir} from the bundled copy: ${bundled}`) + return bundled +} + +export default function resolveRandomBeaconExport( + subdir: RandomBeaconExportKind, +): string { + return resolveRandomBeaconExportIn(subdir, { sourceRoot, packageRoot }) +} diff --git a/solidity/ecdsa/yarn.lock b/solidity/ecdsa/yarn.lock index cd61fe5faa..f02f383ae2 100644 --- a/solidity/ecdsa/yarn.lock +++ b/solidity/ecdsa/yarn.lock @@ -5,7 +5,7 @@ __metadata: version: 8 cacheKey: 10c0 -"@adraffy/ens-normalize@npm:^1.11.0": +"@adraffy/ens-normalize@npm:1.11.1, @adraffy/ens-normalize@npm:^1.11.0": version: 1.11.1 resolution: "@adraffy/ens-normalize@npm:1.11.1" checksum: 10c0/b364e2a57131db278ebf2f22d1a1ac6d8aea95c49dd2bbbc1825870b38aa91fd8816aba580a1f84edc50a45eb6389213dacfd1889f32893afc8549a82d304767 @@ -157,6 +157,15 @@ __metadata: languageName: node linkType: hard +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": "npm:0.3.9" + checksum: 10c0/05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 + languageName: node + linkType: hard + "@emnapi/core@npm:1.10.0": version: 1.10.0 resolution: "@emnapi/core@npm:1.10.0" @@ -268,23 +277,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.5.0, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/abi@npm:5.5.0" - dependencies: - "@ethersproject/address": "npm:^5.5.0" - "@ethersproject/bignumber": "npm:^5.5.0" - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/constants": "npm:^5.5.0" - "@ethersproject/hash": "npm:^5.5.0" - "@ethersproject/keccak256": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/strings": "npm:^5.5.0" - checksum: 10c0/8b38b4462c6599fb83f9cbadfff4aa2bdfdc5ff7796c896f45360ab8edbecaf9dab4eb15c719393c1e7b5f7269c5940c553c3d7d256972291920208c75648f33 - languageName: node - linkType: hard - "@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abi@npm:5.7.0" @@ -302,7 +294,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.8.0, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.8.0": +"@ethersproject/abi@npm:5.8.0, @ethersproject/abi@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abi@npm:5.8.0" dependencies: @@ -319,18 +311,20 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:5.5.1, @ethersproject/abstract-provider@npm:^5.5.0": - version: 5.5.1 - resolution: "@ethersproject/abstract-provider@npm:5.5.1" +"@ethersproject/abi@npm:^5.1.2": + version: 5.5.0 + resolution: "@ethersproject/abi@npm:5.5.0" dependencies: + "@ethersproject/address": "npm:^5.5.0" "@ethersproject/bignumber": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" + "@ethersproject/constants": "npm:^5.5.0" + "@ethersproject/hash": "npm:^5.5.0" + "@ethersproject/keccak256": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/networks": "npm:^5.5.0" "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/transactions": "npm:^5.5.0" - "@ethersproject/web": "npm:^5.5.0" - checksum: 10c0/4eceaa1c48d7d4662eb56e78aab837dfb58f74823fee138bb5715e48b475d34946d2b9bc9c347e9d2bdd70a1e4e2f5aa82a0a7c3f68881e1a4eba8a948c4b315 + "@ethersproject/strings": "npm:^5.5.0" + checksum: 10c0/8b38b4462c6599fb83f9cbadfff4aa2bdfdc5ff7796c896f45360ab8edbecaf9dab4eb15c719393c1e7b5f7269c5940c553c3d7d256972291920208c75648f33 languageName: node linkType: hard @@ -364,16 +358,18 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:5.5.0, @ethersproject/abstract-signer@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/abstract-signer@npm:5.5.0" +"@ethersproject/abstract-provider@npm:^5.5.0": + version: 5.5.1 + resolution: "@ethersproject/abstract-provider@npm:5.5.1" dependencies: - "@ethersproject/abstract-provider": "npm:^5.5.0" "@ethersproject/bignumber": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" + "@ethersproject/networks": "npm:^5.5.0" "@ethersproject/properties": "npm:^5.5.0" - checksum: 10c0/6fdc8ee7b0ccbc2ea2cb493578b5ea1e6c33a462f4681066edd68638ae9fa8f58608f835daa27c1da94739e8f23ccbcafd22329b9e6b220bfc8092a88ea10715 + "@ethersproject/transactions": "npm:^5.5.0" + "@ethersproject/web": "npm:^5.5.0" + checksum: 10c0/4eceaa1c48d7d4662eb56e78aab837dfb58f74823fee138bb5715e48b475d34946d2b9bc9c347e9d2bdd70a1e4e2f5aa82a0a7c3f68881e1a4eba8a948c4b315 languageName: node linkType: hard @@ -403,16 +399,16 @@ __metadata: languageName: node linkType: hard -"@ethersproject/address@npm:5.5.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.5.0": +"@ethersproject/abstract-signer@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/address@npm:5.5.0" + resolution: "@ethersproject/abstract-signer@npm:5.5.0" dependencies: + "@ethersproject/abstract-provider": "npm:^5.5.0" "@ethersproject/bignumber": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/keccak256": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/rlp": "npm:^5.5.0" - checksum: 10c0/55f358c1edf8c4f4951acab9ed4db9bc64cc65d6897ba4820a6dbff4eeb99bf49bbfe36447a6fff39f50e86bc3f089bf658f56db9b8c792f5b05bbc6fd99cc39 + "@ethersproject/properties": "npm:^5.5.0" + checksum: 10c0/6fdc8ee7b0ccbc2ea2cb493578b5ea1e6c33a462f4681066edd68638ae9fa8f58608f835daa27c1da94739e8f23ccbcafd22329b9e6b220bfc8092a88ea10715 languageName: node linkType: hard @@ -442,12 +438,16 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:5.5.0, @ethersproject/base64@npm:^5.5.0": +"@ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/base64@npm:5.5.0" + resolution: "@ethersproject/address@npm:5.5.0" dependencies: + "@ethersproject/bignumber": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" - checksum: 10c0/1c93c88420be379222021ad3b3e2dc775fa0ead584a308de31d01be87fbf9fe3d5eb982cdd68db2d3a4686510df1ad426a4f968b90fa0372abcf24b51a5d88fa + "@ethersproject/keccak256": "npm:^5.5.0" + "@ethersproject/logger": "npm:^5.5.0" + "@ethersproject/rlp": "npm:^5.5.0" + checksum: 10c0/55f358c1edf8c4f4951acab9ed4db9bc64cc65d6897ba4820a6dbff4eeb99bf49bbfe36447a6fff39f50e86bc3f089bf658f56db9b8c792f5b05bbc6fd99cc39 languageName: node linkType: hard @@ -469,13 +469,12 @@ __metadata: languageName: node linkType: hard -"@ethersproject/basex@npm:5.5.0, @ethersproject/basex@npm:^5.5.0": +"@ethersproject/base64@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/basex@npm:5.5.0" + resolution: "@ethersproject/base64@npm:5.5.0" dependencies: "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - checksum: 10c0/ec08761b4df546406ccda432c92a32ab6ac6b4b36c73a129f0a5b262a3af31c94b6749973f26900c541ebead4586d6551120644a0e2557c7bb107f4a3000ef0e + checksum: 10c0/1c93c88420be379222021ad3b3e2dc775fa0ead584a308de31d01be87fbf9fe3d5eb982cdd68db2d3a4686510df1ad426a4f968b90fa0372abcf24b51a5d88fa languageName: node linkType: hard @@ -499,17 +498,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.5.0, @ethersproject/bignumber@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/bignumber@npm:5.5.0" - dependencies: - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - bn.js: "npm:^4.11.9" - checksum: 10c0/9d0e827e0575b0e852c709b7fe56766f10edb04afb31ad7e18776eca837fcc08778458867dc23f8f02f773c37b2591f52dc14b6e329aff077feacc8f2dae0ed8 - languageName: node - linkType: hard - "@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" @@ -521,7 +509,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.8.0, @ethersproject/bignumber@npm:^5.6.2, @ethersproject/bignumber@npm:^5.8.0": +"@ethersproject/bignumber@npm:5.8.0, @ethersproject/bignumber@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/bignumber@npm:5.8.0" dependencies: @@ -532,12 +520,14 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:5.5.0, @ethersproject/bytes@npm:^5.5.0": +"@ethersproject/bignumber@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/bytes@npm:5.5.0" + resolution: "@ethersproject/bignumber@npm:5.5.0" dependencies: + "@ethersproject/bytes": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - checksum: 10c0/4964aace98f17c9d8a4c13decdcc9b5a6362bf6ea9647aabeae0e834faa470ea80ce5ae0e4c4d08697102aafe5b97e5fb29a58623a4fb4d5a06e19bedc5de779 + bn.js: "npm:^4.11.9" + checksum: 10c0/9d0e827e0575b0e852c709b7fe56766f10edb04afb31ad7e18776eca837fcc08778458867dc23f8f02f773c37b2591f52dc14b6e329aff077feacc8f2dae0ed8 languageName: node linkType: hard @@ -559,12 +549,12 @@ __metadata: languageName: node linkType: hard -"@ethersproject/constants@npm:5.5.0, @ethersproject/constants@npm:^5.5.0": +"@ethersproject/bytes@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/constants@npm:5.5.0" + resolution: "@ethersproject/bytes@npm:5.5.0" dependencies: - "@ethersproject/bignumber": "npm:^5.5.0" - checksum: 10c0/68ea669b79e6e2735561a32fc1d1237d8cc940c2a986885a6ba1dcd067ce23e2659103ce90e804a24533262da5231c81b374370b1fb4a838dae625254341e84b + "@ethersproject/logger": "npm:^5.5.0" + checksum: 10c0/4964aace98f17c9d8a4c13decdcc9b5a6362bf6ea9647aabeae0e834faa470ea80ce5ae0e4c4d08697102aafe5b97e5fb29a58623a4fb4d5a06e19bedc5de779 languageName: node linkType: hard @@ -586,21 +576,12 @@ __metadata: languageName: node linkType: hard -"@ethersproject/contracts@npm:5.5.0": +"@ethersproject/constants@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/contracts@npm:5.5.0" + resolution: "@ethersproject/constants@npm:5.5.0" dependencies: - "@ethersproject/abi": "npm:^5.5.0" - "@ethersproject/abstract-provider": "npm:^5.5.0" - "@ethersproject/abstract-signer": "npm:^5.5.0" - "@ethersproject/address": "npm:^5.5.0" "@ethersproject/bignumber": "npm:^5.5.0" - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/constants": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/transactions": "npm:^5.5.0" - checksum: 10c0/53904d7a76b930812dd70ad9b8fd3544821a8bec77aa62b01a2039706fb09d3461737ec1c68d95b3d1b7ebe458e36d2d9af4ad093caa110c43177f0962aab86b + checksum: 10c0/68ea669b79e6e2735561a32fc1d1237d8cc940c2a986885a6ba1dcd067ce23e2659103ce90e804a24533262da5231c81b374370b1fb4a838dae625254341e84b languageName: node linkType: hard @@ -640,22 +621,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/hash@npm:5.5.0, @ethersproject/hash@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/hash@npm:5.5.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.5.0" - "@ethersproject/address": "npm:^5.5.0" - "@ethersproject/bignumber": "npm:^5.5.0" - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/keccak256": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/strings": "npm:^5.5.0" - checksum: 10c0/ac1abdb4e76b3537bd989d42aac0fda55a8c647141c87ccd03691f4922d3cb29ced4d50f5bbfd09560c178471121d6e68a67b570d1cb476481ea1ab9242effb3 - languageName: node - linkType: hard - "@ethersproject/hash@npm:5.7.0, @ethersproject/hash@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/hash@npm:5.7.0" @@ -690,23 +655,19 @@ __metadata: languageName: node linkType: hard -"@ethersproject/hdnode@npm:5.5.0, @ethersproject/hdnode@npm:^5.5.0": +"@ethersproject/hash@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/hdnode@npm:5.5.0" + resolution: "@ethersproject/hash@npm:5.5.0" dependencies: "@ethersproject/abstract-signer": "npm:^5.5.0" - "@ethersproject/basex": "npm:^5.5.0" + "@ethersproject/address": "npm:^5.5.0" "@ethersproject/bignumber": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" + "@ethersproject/keccak256": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/pbkdf2": "npm:^5.5.0" "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/sha2": "npm:^5.5.0" - "@ethersproject/signing-key": "npm:^5.5.0" "@ethersproject/strings": "npm:^5.5.0" - "@ethersproject/transactions": "npm:^5.5.0" - "@ethersproject/wordlists": "npm:^5.5.0" - checksum: 10c0/b0e3b55c954fb366ba60fb060ee04d15ac9fe0125587cc911e119086d807b9a5ea13e38b96dafc826f9c018e3342b306777251094dd903e6f459bb172e2f2be1 + checksum: 10c0/ac1abdb4e76b3537bd989d42aac0fda55a8c647141c87ccd03691f4922d3cb29ced4d50f5bbfd09560c178471121d6e68a67b570d1cb476481ea1ab9242effb3 languageName: node linkType: hard @@ -750,27 +711,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/json-wallets@npm:5.5.0, @ethersproject/json-wallets@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/json-wallets@npm:5.5.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.5.0" - "@ethersproject/address": "npm:^5.5.0" - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/hdnode": "npm:^5.5.0" - "@ethersproject/keccak256": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/pbkdf2": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/random": "npm:^5.5.0" - "@ethersproject/strings": "npm:^5.5.0" - "@ethersproject/transactions": "npm:^5.5.0" - aes-js: "npm:3.0.0" - scrypt-js: "npm:3.0.1" - checksum: 10c0/383a982701a04312bfccbc99633b24b7ff5b070f7a220d071e6b8e2f1d7c4c9038ca0e76177ff741ab26b40c12e8341217481b5c6aaee91979bac9b9158acbcc - languageName: node - linkType: hard - "@ethersproject/json-wallets@npm:5.7.0, @ethersproject/json-wallets@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/json-wallets@npm:5.7.0" @@ -813,16 +753,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/keccak256@npm:5.5.0, @ethersproject/keccak256@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/keccak256@npm:5.5.0" - dependencies: - "@ethersproject/bytes": "npm:^5.5.0" - js-sha3: "npm:0.8.0" - checksum: 10c0/e88d9db6f84227dc8216677fc692a10289c383bf63d207da7ad8beb0d8b112650dc3fbacadb6cc864304d9fe5243235bc6a49de6a37321ab05793717cedcaaac - languageName: node - linkType: hard - "@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/keccak256@npm:5.7.0" @@ -843,10 +773,13 @@ __metadata: languageName: node linkType: hard -"@ethersproject/logger@npm:5.5.0, @ethersproject/logger@npm:^5.5.0": +"@ethersproject/keccak256@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/logger@npm:5.5.0" - checksum: 10c0/e8f83396ee505f8556dfc04aad252ddab4cdc40636cb186e420977e498864312d9b32f336843ab666b30730893bd972b57658518eefacc425ca469adaa8f385e + resolution: "@ethersproject/keccak256@npm:5.5.0" + dependencies: + "@ethersproject/bytes": "npm:^5.5.0" + js-sha3: "npm:0.8.0" + checksum: 10c0/e88d9db6f84227dc8216677fc692a10289c383bf63d207da7ad8beb0d8b112650dc3fbacadb6cc864304d9fe5243235bc6a49de6a37321ab05793717cedcaaac languageName: node linkType: hard @@ -864,12 +797,10 @@ __metadata: languageName: node linkType: hard -"@ethersproject/networks@npm:5.5.2, @ethersproject/networks@npm:^5.5.0": - version: 5.5.2 - resolution: "@ethersproject/networks@npm:5.5.2" - dependencies: - "@ethersproject/logger": "npm:^5.5.0" - checksum: 10c0/46b65590f33f1221fbed1d3fc7fe3ff8e5d431e9137ec725dd505ededbcbecfd40f89f71dfdf754fc1168a3ee7c1e0adf2ff888ac500c5ab4fefa146d6a89d8d +"@ethersproject/logger@npm:^5.5.0": + version: 5.5.0 + resolution: "@ethersproject/logger@npm:5.5.0" + checksum: 10c0/e8f83396ee505f8556dfc04aad252ddab4cdc40636cb186e420977e498864312d9b32f336843ab666b30730893bd972b57658518eefacc425ca469adaa8f385e languageName: node linkType: hard @@ -891,13 +822,12 @@ __metadata: languageName: node linkType: hard -"@ethersproject/pbkdf2@npm:5.5.0, @ethersproject/pbkdf2@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/pbkdf2@npm:5.5.0" +"@ethersproject/networks@npm:^5.5.0": + version: 5.5.2 + resolution: "@ethersproject/networks@npm:5.5.2" dependencies: - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/sha2": "npm:^5.5.0" - checksum: 10c0/ac761fa8286463dafd4531be3de8f0f0421fc4b6fe008226e828b5a7c0369fe965fc6985539b0f1facaa80e332f25e52d4fc460ab082486d079255da9e570f7a + "@ethersproject/logger": "npm:^5.5.0" + checksum: 10c0/46b65590f33f1221fbed1d3fc7fe3ff8e5d431e9137ec725dd505ededbcbecfd40f89f71dfdf754fc1168a3ee7c1e0adf2ff888ac500c5ab4fefa146d6a89d8d languageName: node linkType: hard @@ -921,15 +851,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/properties@npm:5.5.0, @ethersproject/properties@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/properties@npm:5.5.0" - dependencies: - "@ethersproject/logger": "npm:^5.5.0" - checksum: 10c0/bc5521fe27f648d90def99333f579852902d7ee0842401c9e76fe60c96f905b0e3f06aa0f2581befa61107ec9b5e36106dab7af293896a474389efef61bdd1be - languageName: node - linkType: hard - "@ethersproject/properties@npm:5.7.0, @ethersproject/properties@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/properties@npm:5.7.0" @@ -948,30 +869,12 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.5.2": - version: 5.5.2 - resolution: "@ethersproject/providers@npm:5.5.2" +"@ethersproject/properties@npm:^5.5.0": + version: 5.5.0 + resolution: "@ethersproject/properties@npm:5.5.0" dependencies: - "@ethersproject/abstract-provider": "npm:^5.5.0" - "@ethersproject/abstract-signer": "npm:^5.5.0" - "@ethersproject/address": "npm:^5.5.0" - "@ethersproject/basex": "npm:^5.5.0" - "@ethersproject/bignumber": "npm:^5.5.0" - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/constants": "npm:^5.5.0" - "@ethersproject/hash": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/networks": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/random": "npm:^5.5.0" - "@ethersproject/rlp": "npm:^5.5.0" - "@ethersproject/sha2": "npm:^5.5.0" - "@ethersproject/strings": "npm:^5.5.0" - "@ethersproject/transactions": "npm:^5.5.0" - "@ethersproject/web": "npm:^5.5.0" - bech32: "npm:1.1.4" - ws: "npm:7.4.6" - checksum: 10c0/a65b0d1a6e2a85c1ce4f07bea6ee7d7ce4d24c168a8a49cd115ead6df13d4f08a5d637612c9475a43a9e31cb8861f699a8221f9dc05077b1c040368d3c1cf7ef + checksum: 10c0/bc5521fe27f648d90def99333f579852902d7ee0842401c9e76fe60c96f905b0e3f06aa0f2581befa61107ec9b5e36106dab7af293896a474389efef61bdd1be languageName: node linkType: hard @@ -1031,16 +934,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/random@npm:5.5.1, @ethersproject/random@npm:^5.5.0": - version: 5.5.1 - resolution: "@ethersproject/random@npm:5.5.1" - dependencies: - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - checksum: 10c0/241f7b60b6983a17b698f8f9a67bbcac98b1f6eed8ea1f96577279a6ecc5dc457f41d1c8e8d2f534bade3e4bfbed7d0d8b89be1b0b01a16a4584abbd58cb55cc - languageName: node - linkType: hard - "@ethersproject/random@npm:5.7.0, @ethersproject/random@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/random@npm:5.7.0" @@ -1061,16 +954,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:5.5.0, @ethersproject/rlp@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/rlp@npm:5.5.0" - dependencies: - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - checksum: 10c0/0e3a3297843531aa572ce5eae6ec9ef0c9b3aecc4829d970f370e6a1cda58b71a8340378618f0e4e9b52b830f99081b3b4ec02c3cdf5a50cec3bb2cf25745ece - languageName: node - linkType: hard - "@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/rlp@npm:5.7.0" @@ -1091,14 +974,13 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:5.5.0, @ethersproject/sha2@npm:^5.5.0": +"@ethersproject/rlp@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/sha2@npm:5.5.0" + resolution: "@ethersproject/rlp@npm:5.5.0" dependencies: "@ethersproject/bytes": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - hash.js: "npm:1.1.7" - checksum: 10c0/fef85ce64f285773580d5a9903557d6b356109745267314b8b94f0976dbce48295f56668a01b175adcaaa0820f9567e4fce56febd1f93539619214183069d48e + checksum: 10c0/0e3a3297843531aa572ce5eae6ec9ef0c9b3aecc4829d970f370e6a1cda58b71a8340378618f0e4e9b52b830f99081b3b4ec02c3cdf5a50cec3bb2cf25745ece languageName: node linkType: hard @@ -1124,20 +1006,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/signing-key@npm:5.5.0, @ethersproject/signing-key@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/signing-key@npm:5.5.0" - dependencies: - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - bn.js: "npm:^4.11.9" - elliptic: "npm:6.5.4" - hash.js: "npm:1.1.7" - checksum: 10c0/ab99a8477780bb92183cbd8b591668c7a58c15db3cee85ea522e081dfaf379a009995a6df390586bb9bf6d41b5c96d320e898b5c326c0db2b06bc823efb3fe5e - languageName: node - linkType: hard - "@ethersproject/signing-key@npm:5.7.0, @ethersproject/signing-key@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/signing-key@npm:5.7.0" @@ -1166,17 +1034,17 @@ __metadata: languageName: node linkType: hard -"@ethersproject/solidity@npm:5.5.0": +"@ethersproject/signing-key@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/solidity@npm:5.5.0" + resolution: "@ethersproject/signing-key@npm:5.5.0" dependencies: - "@ethersproject/bignumber": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/keccak256": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/sha2": "npm:^5.5.0" - "@ethersproject/strings": "npm:^5.5.0" - checksum: 10c0/1953cb73f2f7fb1f20165ad501dfaac2c65b921ae32c5b1acd3de7ff6d6236eca4ba22ec1db67392d22dc5d90680d0a18c12c9fcea33c7c67a0d5f5a40d4ab02 + "@ethersproject/properties": "npm:^5.5.0" + bn.js: "npm:^4.11.9" + elliptic: "npm:6.5.4" + hash.js: "npm:1.1.7" + checksum: 10c0/ab99a8477780bb92183cbd8b591668c7a58c15db3cee85ea522e081dfaf379a009995a6df390586bb9bf6d41b5c96d320e898b5c326c0db2b06bc823efb3fe5e languageName: node linkType: hard @@ -1208,17 +1076,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/strings@npm:5.5.0, @ethersproject/strings@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/strings@npm:5.5.0" - dependencies: - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/constants": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - checksum: 10c0/b1893dbfaeff931ca6193b06e58a4929b527922154372c07877340ed744b3dce2cc529efdaa01e59a98fc2a8703ea17aacbb4f9581df284fdf0f8a30eb99cb32 - languageName: node - linkType: hard - "@ethersproject/strings@npm:5.7.0, @ethersproject/strings@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/strings@npm:5.7.0" @@ -1241,20 +1098,14 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:5.5.0, @ethersproject/transactions@npm:^5.5.0": +"@ethersproject/strings@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/transactions@npm:5.5.0" + resolution: "@ethersproject/strings@npm:5.5.0" dependencies: - "@ethersproject/address": "npm:^5.5.0" - "@ethersproject/bignumber": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" "@ethersproject/constants": "npm:^5.5.0" - "@ethersproject/keccak256": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/rlp": "npm:^5.5.0" - "@ethersproject/signing-key": "npm:^5.5.0" - checksum: 10c0/7dc61ad8bc8e7542b7034d37ee0b896b192a8610084111eaa70eb495c3d3a4e282407a568fcf40baae1cc9db87bb7345bfd2c15512ae7ac9036b8227525f02e1 + checksum: 10c0/b1893dbfaeff931ca6193b06e58a4929b527922154372c07877340ed744b3dce2cc529efdaa01e59a98fc2a8703ea17aacbb4f9581df284fdf0f8a30eb99cb32 languageName: node linkType: hard @@ -1292,14 +1143,20 @@ __metadata: languageName: node linkType: hard -"@ethersproject/units@npm:5.5.0": +"@ethersproject/transactions@npm:^5.5.0": version: 5.5.0 - resolution: "@ethersproject/units@npm:5.5.0" + resolution: "@ethersproject/transactions@npm:5.5.0" dependencies: + "@ethersproject/address": "npm:^5.5.0" "@ethersproject/bignumber": "npm:^5.5.0" + "@ethersproject/bytes": "npm:^5.5.0" "@ethersproject/constants": "npm:^5.5.0" + "@ethersproject/keccak256": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" - checksum: 10c0/dc24228ef7c3336087494ceb3fc0b274a5c57fba8e39e6f960c085e1661908d68670790c15953c440ebf590850045572578a4bec947549d77b0134280aab8e00 + "@ethersproject/properties": "npm:^5.5.0" + "@ethersproject/rlp": "npm:^5.5.0" + "@ethersproject/signing-key": "npm:^5.5.0" + checksum: 10c0/7dc61ad8bc8e7542b7034d37ee0b896b192a8610084111eaa70eb495c3d3a4e282407a568fcf40baae1cc9db87bb7345bfd2c15512ae7ac9036b8227525f02e1 languageName: node linkType: hard @@ -1325,29 +1182,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wallet@npm:5.5.0": - version: 5.5.0 - resolution: "@ethersproject/wallet@npm:5.5.0" - dependencies: - "@ethersproject/abstract-provider": "npm:^5.5.0" - "@ethersproject/abstract-signer": "npm:^5.5.0" - "@ethersproject/address": "npm:^5.5.0" - "@ethersproject/bignumber": "npm:^5.5.0" - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/hash": "npm:^5.5.0" - "@ethersproject/hdnode": "npm:^5.5.0" - "@ethersproject/json-wallets": "npm:^5.5.0" - "@ethersproject/keccak256": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/random": "npm:^5.5.0" - "@ethersproject/signing-key": "npm:^5.5.0" - "@ethersproject/transactions": "npm:^5.5.0" - "@ethersproject/wordlists": "npm:^5.5.0" - checksum: 10c0/b824957e482b3df43a9b09d589157ee89bf8d2e7d40e74dc5dbc3b65f861c0d7d9b8ff44392b878a9cb6c8e91e494da7a4b189dade343f08dd5d21043010221a - languageName: node - linkType: hard - "@ethersproject/wallet@npm:5.7.0": version: 5.7.0 resolution: "@ethersproject/wallet@npm:5.7.0" @@ -1394,19 +1228,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/web@npm:5.5.1, @ethersproject/web@npm:^5.5.0": - version: 5.5.1 - resolution: "@ethersproject/web@npm:5.5.1" - dependencies: - "@ethersproject/base64": "npm:^5.5.0" - "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/logger": "npm:^5.5.0" - "@ethersproject/properties": "npm:^5.5.0" - "@ethersproject/strings": "npm:^5.5.0" - checksum: 10c0/6933c952a1638fdff949babc37c7eb47c1fcb2245ae2accb67f4fb03e5b00ee099c5f80bd2d1dc93f2b4fb9f3e2d3f3b4d7a8ac4eb46d3adbf1081611968bb52 - languageName: node - linkType: hard - "@ethersproject/web@npm:5.7.1, @ethersproject/web@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/web@npm:5.7.1" @@ -1433,16 +1254,16 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wordlists@npm:5.5.0, @ethersproject/wordlists@npm:^5.5.0": - version: 5.5.0 - resolution: "@ethersproject/wordlists@npm:5.5.0" +"@ethersproject/web@npm:^5.5.0": + version: 5.5.1 + resolution: "@ethersproject/web@npm:5.5.1" dependencies: + "@ethersproject/base64": "npm:^5.5.0" "@ethersproject/bytes": "npm:^5.5.0" - "@ethersproject/hash": "npm:^5.5.0" "@ethersproject/logger": "npm:^5.5.0" "@ethersproject/properties": "npm:^5.5.0" "@ethersproject/strings": "npm:^5.5.0" - checksum: 10c0/6f690525f787d177354e2ac49c607ea885c688505aba6666893cfa75ece216904e91581c8b88f48991b9662976fd130fc37f273067e89a29d4917603d91518cc + checksum: 10c0/6933c952a1638fdff949babc37c7eb47c1fcb2245ae2accb67f4fb03e5b00ee099c5f80bd2d1dc93f2b4fb9f3e2d3f3b4d7a8ac4eb46d3adbf1081611968bb52 languageName: node linkType: hard @@ -1550,25 +1371,50 @@ __metadata: languageName: node linkType: hard +"@jridgewell/resolve-uri@npm:^3.0.3": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10": + version: 1.6.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.6.0" + checksum: 10c0/b5be700e45a775f218589c3466c4ffea630582b4988657652da464e5ab8a7d18bf928ee4fd2363fb346ede4bea9c6ff0bae05a538358c4565ece6199531b5f72 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.0.3" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b + languageName: node + linkType: hard + "@keep-network/ecdsa@workspace:.": version: 0.0.0-use.local resolution: "@keep-network/ecdsa@workspace:." dependencies: - "@keep-network/hardhat-helpers": "github:threshold-network/hardhat-helpers#v0.6.0-pre.21" + "@keep-network/hardhat-helpers": "patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch" "@keep-network/hardhat-local-networks-config": "github:threshold-network/hardhat-local-networks-config#6dff5bc8648127ca5d8696c321076bddb6d4142a" - "@keep-network/random-beacon": "npm:development" + "@keep-network/random-beacon": "npm:2.1.0-dev.18" "@keep-network/sortition-pools": "npm:^2.0.0-pre.16" - "@nomicfoundation/hardhat-chai-matchers": "npm:^1.0.6" + "@nomicfoundation/hardhat-chai-matchers": "npm:^2.1.2" + "@nomicfoundation/hardhat-ethers": "npm:^3.1.3" + "@nomicfoundation/hardhat-network-helpers": "npm:^1.1.2" "@nomicfoundation/hardhat-verify": "npm:^2.1.3" - "@nomiclabs/hardhat-ethers": "npm:^2.0.6" "@openzeppelin/contracts": "npm:^4.9.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.6" - "@openzeppelin/hardhat-upgrades": "npm:^1.20.4" + "@openzeppelin/hardhat-upgrades": "patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch" "@stylistic/eslint-plugin": "npm:^5.10.0" - "@tenderly/hardhat-tenderly": "npm:>=1.0.13 <1.2.0" + "@tenderly/hardhat-tenderly": "npm:2.1.1" "@threshold-network/solidity-contracts": "npm:1.3.0-dev.14" - "@typechain/ethers-v5": "npm:^11.1.2" - "@typechain/hardhat": "npm:^7.0.0" + "@typechain/ethers-v6": "patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch" + "@typechain/hardhat": "npm:^9.1.0" "@types/chai": "npm:^4.3.20" "@types/chai-as-promised": "npm:^7.1.5" "@types/mocha": "npm:^10.0.10" @@ -1580,7 +1426,7 @@ __metadata: eslint-import-resolver-typescript: "npm:^4.4.5" eslint-plugin-import-x: "npm:^4.17.1" eslint-plugin-no-only-tests: "npm:^3.4.0" - ethers: "npm:^5.5.3" + ethers: "npm:^6.17.0" fs-extra: "npm:^11.2.0" globals: "npm:^17.12.0" hardhat: "npm:2.29.0" @@ -1600,17 +1446,31 @@ __metadata: languageName: unknown linkType: soft -"@keep-network/hardhat-helpers@github:threshold-network/hardhat-helpers#v0.6.0-pre.21": - version: 0.6.0-pre.21 - resolution: "@keep-network/hardhat-helpers@https://github.com/threshold-network/hardhat-helpers.git#commit=beeec4afb3f41f6c46e1499e899d814248771a8e" +"@keep-network/hardhat-helpers@npm:0.7.2": + version: 0.7.2 + resolution: "@keep-network/hardhat-helpers@npm:0.7.2" peerDependencies: - "@nomiclabs/hardhat-ethers": ^2.1.0 - "@nomiclabs/hardhat-etherscan": ^3.1.0 - "@openzeppelin/hardhat-upgrades": ^1.22.0 - ethers: ^5.6.9 - hardhat: ^2.10.0 - hardhat-deploy: ^0.11.11 - checksum: 10c0/2c7828b30ae4a824a0f31a9ed9fbed323af82ac4daea06480143e7b4265b9a95982b4967cfb2276e2c1437ce2482f3fe04737de79f9103457e62a74c6edba095 + "@nomicfoundation/hardhat-ethers": ^3.0.5 + "@nomicfoundation/hardhat-verify": ^2.0.3 + "@openzeppelin/hardhat-upgrades": ^3.0.2 + ethers: ^6.10.0 + hardhat: ^2.19.4 + hardhat-deploy: ^0.11.45 + checksum: 10c0/55949a24dd5425629cd914d17c60aaced658c84820f5eb6cfb27ab8e1e231afc17d3a360b03700ebde11c10013e7eee8fe3f45bc7866121c80ffbdaf1f6d9185 + languageName: node + linkType: hard + +"@keep-network/hardhat-helpers@patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch": + version: 0.7.2 + resolution: "@keep-network/hardhat-helpers@patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch::version=0.7.2&hash=b77b8f" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.5 + "@nomicfoundation/hardhat-verify": ^2.0.3 + "@openzeppelin/hardhat-upgrades": ^3.0.2 + ethers: ^6.10.0 + hardhat: ^2.19.4 + hardhat-deploy: ^0.11.45 + checksum: 10c0/5705dad93a94d9f571853a325c7134bf2bddcb2fd9811e330e1744033449628175adc2b9e60c0987622b9a465b2744fa8f766ef7114ffee8370b920b4ad5d4c0 languageName: node linkType: hard @@ -1636,7 +1496,7 @@ __metadata: languageName: node linkType: hard -"@keep-network/random-beacon@npm:development": +"@keep-network/random-beacon@npm:2.1.0-dev.18": version: 2.1.0-dev.18 resolution: "@keep-network/random-beacon@npm:2.1.0-dev.18" dependencies: @@ -1696,6 +1556,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" + dependencies: + "@noble/hashes": "npm:1.3.2" + checksum: 10c0/0bac7d1bbfb3c2286910b02598addd33243cb97c3f36f987ecc927a4be8d7d88e0fcb12b0f0ef8a044e7307d1844dd5c49bb724bfa0a79c8ec50ba60768c97f6 + languageName: node + linkType: hard + "@noble/curves@npm:1.4.2, @noble/curves@npm:~1.4.0": version: 1.4.2 resolution: "@noble/curves@npm:1.4.2" @@ -1739,6 +1608,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.3.2": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: 10c0/2482cce3bce6a596626f94ca296e21378e7a5d4c09597cbc46e65ffacc3d64c8df73111f2265444e36a3168208628258bbbaccba2ef24f65f58b2417638a20e7 + languageName: node + linkType: hard + "@noble/hashes@npm:1.4.0, @noble/hashes@npm:~1.4.0": version: 1.4.0 resolution: "@noble/hashes@npm:1.4.0" @@ -1838,21 +1714,44 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/hardhat-chai-matchers@npm:^1.0.6": - version: 1.0.6 - resolution: "@nomicfoundation/hardhat-chai-matchers@npm:1.0.6" +"@nomicfoundation/hardhat-chai-matchers@npm:^2.1.2": + version: 2.1.2 + resolution: "@nomicfoundation/hardhat-chai-matchers@npm:2.1.2" dependencies: - "@ethersproject/abi": "npm:^5.1.2" "@types/chai-as-promised": "npm:^7.1.3" chai-as-promised: "npm:^7.1.1" deep-eql: "npm:^4.0.1" ordinal: "npm:^1.0.3" peerDependencies: - "@nomiclabs/hardhat-ethers": ^2.0.0 + "@nomicfoundation/hardhat-ethers": ^3.1.0 chai: ^4.2.0 - ethers: ^5.0.0 - hardhat: ^2.9.4 - checksum: 10c0/d5e0327aee476ddd1ff25ab6d0fb47af0ccf081a9ff072499dccba7656eea9911aab4bd7e19fe46e5dfb920d2690df3c64dbb324a83e15f8ec9dd13a56ebbe66 + ethers: ^6.14.0 + hardhat: ^2.26.0 + checksum: 10c0/ed51e9d5e20869fc50f13ee7c8ad65e9531a6222a8b19c1afe21c28d563c8d2361c2f6f36a0c8a7b4e9b6c9c8df9f1878d6512b27919e18ea4e71bf28249bf86 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-ethers@npm:^3.0.4, @nomicfoundation/hardhat-ethers@npm:^3.1.3": + version: 3.1.3 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.1.3" + dependencies: + debug: "npm:^4.1.1" + lodash.isequal: "npm:^4.5.0" + peerDependencies: + ethers: ^6.14.0 + hardhat: ^2.28.0 + checksum: 10c0/77a20741634a4028324cf329cac28205eff4a318ab92b0f42af4e714ebaab97a760bdba551fec446f4cea171a8964a6a89d19f33105fb8c8538d779a8a975093 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-network-helpers@npm:^1.1.2": + version: 1.1.2 + resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.1.2" + dependencies: + ethereumjs-util: "npm:^7.1.4" + peerDependencies: + hardhat: ^2.26.0 + checksum: 10c0/00fb7392bc0a0c3df635a52fe350ae5e5a71610f3718e11e6b17753f6723231c81def37a19933cd96174cbc5362c0168c8fa98ea73910d46dd9d4bbba0c7990f languageName: node linkType: hard @@ -1972,16 +1871,6 @@ __metadata: languageName: node linkType: hard -"@nomiclabs/hardhat-ethers@npm:^2.0.6": - version: 2.0.6 - resolution: "@nomiclabs/hardhat-ethers@npm:2.0.6" - peerDependencies: - ethers: ^5.0.0 - hardhat: ^2.0.0 - checksum: 10c0/f8bad2d51f05bc65ebd0061e80a3a3e9f3731bdabde3881aa913c94868916c01c3bef4835a170538a56544cd361f7dc06bdf38e6c46ca20e29c854c0038da8d5 - languageName: node - linkType: hard - "@npmcli/agent@npm:^4.0.0": version: 4.0.0 resolution: "@npmcli/agent@npm:4.0.0" @@ -2046,7 +1935,20 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/defender-base-client@npm:^1.46.0": +"@openzeppelin/defender-admin-client@npm:^1.52.0": + version: 1.54.6 + resolution: "@openzeppelin/defender-admin-client@npm:1.54.6" + dependencies: + "@openzeppelin/defender-base-client": "npm:1.54.6" + axios: "npm:^1.4.0" + ethers: "npm:^5.7.2" + lodash: "npm:^4.17.19" + node-fetch: "npm:^2.6.0" + checksum: 10c0/784d7d0eee87916546654f8265f0823401b18f34f0c168daa5c3c353000b5a8e595edc26a384a5f4052dedf2602947e58620442c6f1f46760bfb99a77a5ae69d + languageName: node + linkType: hard + +"@openzeppelin/defender-base-client@npm:1.54.6, @openzeppelin/defender-base-client@npm:^1.52.0": version: 1.54.6 resolution: "@openzeppelin/defender-base-client@npm:1.54.6" dependencies: @@ -2059,60 +1961,101 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/hardhat-upgrades@npm:^1.20.4": - version: 1.28.0 - resolution: "@openzeppelin/hardhat-upgrades@npm:1.28.0" +"@openzeppelin/defender-sdk-base-client@npm:^1.15.2, @openzeppelin/defender-sdk-base-client@npm:^1.8.0": + version: 1.15.2 + resolution: "@openzeppelin/defender-sdk-base-client@npm:1.15.2" dependencies: - "@openzeppelin/defender-base-client": "npm:^1.46.0" - "@openzeppelin/platform-deploy-client": "npm:^0.8.0" - "@openzeppelin/upgrades-core": "npm:^1.27.0" + amazon-cognito-identity-js: "npm:^6.3.6" + async-retry: "npm:^1.3.3" + checksum: 10c0/cb1f5a286564b7f4da0c6f4b21f032b7e09697c2e476c2cf3d957287bc9dc880d0f1c2a4b21d42bc8246a99ea117ce39cfff6fd18f20ca63ac3dc859a43b62a1 + languageName: node + linkType: hard + +"@openzeppelin/defender-sdk-deploy-client@npm:^1.8.0": + version: 1.15.2 + resolution: "@openzeppelin/defender-sdk-deploy-client@npm:1.15.2" + dependencies: + "@openzeppelin/defender-sdk-base-client": "npm:^1.15.2" + axios: "npm:^1.7.2" + lodash: "npm:^4.17.21" + checksum: 10c0/af3db2976d14bdeb7b24e109209a37fcd98ab14176ebd62f0543d0dff552fd9359b382e35c2698315e195c42f55b2bc52b2aea0f598a070ac0a24274a1ba93d9 + languageName: node + linkType: hard + +"@openzeppelin/hardhat-upgrades@npm:2.5.1": + version: 2.5.1 + resolution: "@openzeppelin/hardhat-upgrades@npm:2.5.1" + dependencies: + "@openzeppelin/defender-admin-client": "npm:^1.52.0" + "@openzeppelin/defender-base-client": "npm:^1.52.0" + "@openzeppelin/defender-sdk-base-client": "npm:^1.8.0" + "@openzeppelin/defender-sdk-deploy-client": "npm:^1.8.0" + "@openzeppelin/upgrades-core": "npm:^1.31.2" chalk: "npm:^4.1.0" debug: "npm:^4.1.1" + ethereumjs-util: "npm:^7.1.5" proper-lockfile: "npm:^4.1.1" + undici: "npm:^5.14.0" peerDependencies: - "@nomiclabs/hardhat-ethers": ^2.0.0 - "@nomiclabs/hardhat-etherscan": ^3.1.0 - ethers: ^5.0.5 + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-verify": ^1.1.0 + ethers: ^6.6.0 hardhat: ^2.0.2 peerDependenciesMeta: - "@nomiclabs/harhdat-etherscan": + "@nomicfoundation/hardhat-verify": optional: true bin: migrate-oz-cli-project: dist/scripts/migrate-oz-cli-project.js - checksum: 10c0/8cd6c52ab966aac09435e58c8d5a80747adbd34ffbe3808205c30d6851a7e4ef35272a36f8c837da4841b4643ac3df8ea1d982218f38b99144df16e68ada3b9f + checksum: 10c0/3c032048a2d58fd59a1287234c5d045e7b231afb6ed3d906f9d5751b93f29dd5f1cbfdd0898c62cc8397ca111a98b7fa032cc93929adbc2072d1ad8bfbcded72 languageName: node linkType: hard -"@openzeppelin/platform-deploy-client@npm:^0.8.0": - version: 0.8.0 - resolution: "@openzeppelin/platform-deploy-client@npm:0.8.0" +"@openzeppelin/hardhat-upgrades@patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch": + version: 2.5.1 + resolution: "@openzeppelin/hardhat-upgrades@patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch::version=2.5.1&hash=6d2f71" dependencies: - "@ethersproject/abi": "npm:^5.6.3" - "@openzeppelin/defender-base-client": "npm:^1.46.0" - axios: "npm:^0.21.2" - lodash: "npm:^4.17.19" - node-fetch: "npm:^2.6.0" - checksum: 10c0/7a85c19fd94b268386fdcef5951218467ea146e7047fd4e0536f8044138a7867c904358e681cd6a56bf1e0d1a82ffe7172df4b291b4278c54094925c8890d35a + "@openzeppelin/defender-admin-client": "npm:^1.52.0" + "@openzeppelin/defender-base-client": "npm:^1.52.0" + "@openzeppelin/defender-sdk-base-client": "npm:^1.8.0" + "@openzeppelin/defender-sdk-deploy-client": "npm:^1.8.0" + "@openzeppelin/upgrades-core": "npm:^1.31.2" + chalk: "npm:^4.1.0" + debug: "npm:^4.1.1" + ethereumjs-util: "npm:^7.1.5" + proper-lockfile: "npm:^4.1.1" + undici: "npm:^5.14.0" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-verify": ^1.1.0 + ethers: ^6.6.0 + hardhat: ^2.0.2 + peerDependenciesMeta: + "@nomicfoundation/hardhat-verify": + optional: true + bin: + migrate-oz-cli-project: dist/scripts/migrate-oz-cli-project.js + checksum: 10c0/8a15e1ed75c3833f501bca1b53baf56babc4d6055576e92d3b18752a92352dbe7a39c7836d49bff0ba786c7c2fc842773da70aee8a7765c7fed8dd2530295dd4 languageName: node linkType: hard -"@openzeppelin/upgrades-core@npm:^1.27.0": - version: 1.42.1 - resolution: "@openzeppelin/upgrades-core@npm:1.42.1" +"@openzeppelin/upgrades-core@npm:^1.31.2": + version: 1.46.0 + resolution: "@openzeppelin/upgrades-core@npm:1.46.0" dependencies: "@nomicfoundation/slang": "npm:^0.18.3" + bignumber.js: "npm:^9.1.2" cbor: "npm:^10.0.0" chalk: "npm:^4.1.0" compare-versions: "npm:^6.0.0" debug: "npm:^4.1.1" ethereumjs-util: "npm:^7.0.3" - minimatch: "npm:^9.0.5" + minimatch: "npm:^10.2.5" minimist: "npm:^1.2.7" proper-lockfile: "npm:^4.1.1" - solidity-ast: "npm:^0.4.51" + solidity-ast: "npm:^0.4.60" bin: openzeppelin-upgrades-core: dist/cli/cli.js - checksum: 10c0/e4586ff5edeaf7436ec0c0a58def5b69576753d3dbc345f227f5d44e0a737d2bf46de679ef3369b7bc377006decdf46e9645274e2fe5de4aa1c0cefc07abc841 + checksum: 10c0/11b938ef442cecb8441a8022f67b5fb3e87e84f521b8d33d2b1f94ef954382f8538e59afa58e23cd5ec29f39446ea67f428d30416b8a03671dc509aff87167e4 languageName: node linkType: hard @@ -2505,20 +2448,24 @@ __metadata: languageName: node linkType: hard -"@tenderly/hardhat-tenderly@npm:>=1.0.13 <1.2.0": - version: 1.1.6 - resolution: "@tenderly/hardhat-tenderly@npm:1.1.6" +"@tenderly/hardhat-tenderly@npm:2.1.1": + version: 2.1.1 + resolution: "@tenderly/hardhat-tenderly@npm:2.1.1" dependencies: - "@ethersproject/bignumber": "npm:^5.6.2" - "@nomiclabs/hardhat-ethers": "npm:^2.0.6" - axios: "npm:^0.21.1" - ethers: "npm:^5.6.8" - fs-extra: "npm:^9.0.1" - hardhat-deploy: "npm:^0.11.10" - js-yaml: "npm:^3.14.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@nomicfoundation/hardhat-ethers": "npm:^3.0.4" + axios: "npm:^0.27.2" + ethers: "npm:^6.8.1" + fs-extra: "npm:^10.1.0" + hardhat-deploy: "npm:^0.11.43" + tenderly: "npm:^0.8.0" + ts-node: "npm:^10.9.1" + tslog: "npm:^4.3.1" + typescript: "npm:^5.2.2" peerDependencies: - hardhat: ^2.10.1 - checksum: 10c0/8a6768949270bbec727641920dd7e344160fed5ff93777f404117d22cad754ea6623ef5873d05721e98330108044c577046d166702f82f95bc70376b4492e3fa + ethers: ^6.8.1 + hardhat: ^2.19.0 + checksum: 10c0/f51fdef7e3b857d5f7f6bc0f139f2b565641dc9f31805376245d65af815493a79cf60a6888f3a70f0d29c55eabed4fe972e7ab6ac138a13d4fb71046d60a671f languageName: node linkType: hard @@ -2556,6 +2503,17 @@ __metadata: languageName: node linkType: hard +"@threshold-network/solidity-contracts@patch:@threshold-network/solidity-contracts@npm%3A1.3.0-dev.14#./.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch::locator=%40keep-network%2Fecdsa%40workspace%3A.": + version: 1.3.0-dev.14 + resolution: "@threshold-network/solidity-contracts@patch:@threshold-network/solidity-contracts@npm%3A1.3.0-dev.14#./.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch::version=1.3.0-dev.14&hash=fd9350&locator=%40keep-network%2Fecdsa%40workspace%3A." + dependencies: + "@openzeppelin/contracts": "npm:~4.5.0" + "@openzeppelin/contracts-upgradeable": "npm:~4.5.2" + "@thesis/solidity-contracts": "github:thesis/solidity-contracts#4985bcf" + checksum: 10c0/a6a7d2facb4e5ee695b55706dfe2c47eeca68bc3e73a3e76eaffa4df5e677360a33282101a25209aada1d83c1234839a013f93d784bb9a9c435b24f1d3cbf902 + languageName: node + linkType: hard + "@tsconfig/node10@npm:^1.0.7": version: 1.0.8 resolution: "@tsconfig/node10@npm:1.0.8" @@ -2593,35 +2551,45 @@ __metadata: languageName: node linkType: hard -"@typechain/ethers-v5@npm:^11.1.2": - version: 11.1.2 - resolution: "@typechain/ethers-v5@npm:11.1.2" +"@typechain/ethers-v6@npm:0.5.1": + version: 0.5.1 + resolution: "@typechain/ethers-v6@npm:0.5.1" dependencies: lodash: "npm:^4.17.15" ts-essentials: "npm:^7.0.1" peerDependencies: - "@ethersproject/abi": ^5.0.0 - "@ethersproject/providers": ^5.0.0 - ethers: ^5.1.3 + ethers: 6.x typechain: ^8.3.2 - typescript: ">=4.3.0" - checksum: 10c0/5da6109ded6e02701e5ad718479b8a316011c5366adcbfbd8b7ee1c149c02960714c6906d823d76ab1839046aad127f9c8793f4b36a65f4299d7ce4314265ae1 + typescript: ">=4.7.0" + checksum: 10c0/f3c80151c07e01adbf520e0854426649edb0ee540920569487dd8da7eca2fa8615710f4c0eda008e7afdf255fbb8dfdebf721a5d324a4dffeb087611d9bd64b9 languageName: node linkType: hard -"@typechain/hardhat@npm:^7.0.0": - version: 7.0.0 - resolution: "@typechain/hardhat@npm:7.0.0" +"@typechain/ethers-v6@patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch": + version: 0.5.1 + resolution: "@typechain/ethers-v6@patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch::version=0.5.1&hash=496509" + dependencies: + lodash: "npm:^4.17.15" + ts-essentials: "npm:^7.0.1" + peerDependencies: + ethers: 6.x + typechain: ^8.3.2 + typescript: ">=4.7.0" + checksum: 10c0/cbf3447ec6ac2351df39f69c11066d8f3e48d1c9792281127499cc53da66b537db97e4a4385c925ab9c2fe04ea25912a126bd71f28564a93343d4f1c901f764b + languageName: node + linkType: hard + +"@typechain/hardhat@npm:^9.1.0": + version: 9.1.0 + resolution: "@typechain/hardhat@npm:9.1.0" dependencies: fs-extra: "npm:^9.1.0" peerDependencies: - "@ethersproject/abi": ^5.4.7 - "@ethersproject/providers": ^5.4.7 - "@typechain/ethers-v5": ^11.0.0 - ethers: ^5.4.7 + "@typechain/ethers-v6": ^0.5.1 + ethers: ^6.1.0 hardhat: ^2.9.9 - typechain: ^8.2.0 - checksum: 10c0/80732203ec94fd6933eedbef24d2b74ce167e0bdaf697ca1a98edbcb88775814a02e1e0fabdb2fd1e53d53730204fcad392580b42c0b47beeb30c403535dd652 + typechain: ^8.3.2 + checksum: 10c0/3a1220efefc7b02ca335696167f6c5332a33ff3fbf9f20552468566a1760f76bc88d330683e97ca6213eb9518a2a901391c31c84c0548006b72bd2ec62d4af9c languageName: node linkType: hard @@ -2726,6 +2694,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:22.7.5": + version: 22.7.5 + resolution: "@types/node@npm:22.7.5" + dependencies: + undici-types: "npm:~6.19.2" + checksum: 10c0/cf11f74f1a26053ec58066616e3a8685b6bcd7259bc569738b8f752009f9f0f7f85a1b2d24908e5b0f752482d1e8b6babdf1fbb25758711ec7bb9500bfcd6e60 + languageName: node + linkType: hard + "@types/node@npm:^10.12.18, @types/node@npm:^10.3.2": version: 10.17.60 resolution: "@types/node@npm:10.17.60" @@ -2766,9 +2743,9 @@ __metadata: linkType: hard "@types/qs@npm:^6.9.7": - version: 6.15.1 - resolution: "@types/qs@npm:6.15.1" - checksum: 10c0/1dfdbcb4cf2a8f66d57f0b9a9fe6b1c7091cb816687b6698c1351eaf31f62e412cea9b7453a9637b570cd5fad8dced527e5a9e69b4fcc6e318daacd8b749f094 + version: 6.14.0 + resolution: "@types/qs@npm:6.14.0" + checksum: 10c0/5b3036df6e507483869cdb3858201b2e0b64b4793dc4974f188caa5b5732f2333ab9db45c08157975054d3b070788b35088b4bc60257ae263885016ee2131310 languageName: node linkType: hard @@ -3178,6 +3155,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: 10c0/444f4eefa1e602cbc4f2a3c644bc990f93fd982b148425fee17634da510586fc09da940dcf8ace1b2d001453c07ff042e55f7a0482b3cc9372bf1ef75479090c + languageName: node + linkType: hard + "agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -3265,6 +3249,19 @@ __metadata: languageName: node linkType: hard +"amazon-cognito-identity-js@npm:^6.3.6": + version: 6.3.21 + resolution: "amazon-cognito-identity-js@npm:6.3.21" + dependencies: + "@aws-crypto/sha256-js": "npm:1.2.2" + buffer: "npm:4.9.2" + fast-base64-decode: "npm:^1.0.0" + isomorphic-unfetch: "npm:^3.0.0" + js-cookie: "npm:^3.0.7" + checksum: 10c0/c7541a70f5fc7a9cdc9642dec5c223420c4719219a24eab05decb1292741ebd82e4746dccc396f26436550896f5aa249311c4628f2b0f40ef4b436d50c05a16d + languageName: node + linkType: hard + "ansi-align@npm:^3.0.0": version: 3.0.1 resolution: "ansi-align@npm:3.0.1" @@ -3367,15 +3364,6 @@ __metadata: languageName: node linkType: hard -"argparse@npm:^1.0.7": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: "npm:~1.0.2" - checksum: 10c0/b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -3506,45 +3494,15 @@ __metadata: languageName: node linkType: hard -"axios@npm:^0.18.0": - version: 0.18.1 - resolution: "axios@npm:0.18.1" - dependencies: - follow-redirects: "npm:1.5.10" - is-buffer: "npm:^2.0.2" - checksum: 10c0/13d86542ad3e1de286a6262213b1cd62654307d89617bef5015e82aad389408c6f66bafa1e467b80af971cfe5ac5ed0b40a250f682f46ab9a1487060f0b6b661 - languageName: node - linkType: hard - -"axios@npm:^0.21.1, axios@npm:^0.21.2": - version: 0.21.4 - resolution: "axios@npm:0.21.4" - dependencies: - follow-redirects: "npm:^1.14.0" - checksum: 10c0/fbcff55ec68f71f02d3773d467db2fcecdf04e749826c82c2427a232f9eba63242150a05f15af9ef15818352b814257541155de0281f8fb2b7e8a5b79f7f2142 - languageName: node - linkType: hard - -"axios@npm:^1.4.0": - version: 1.8.1 - resolution: "axios@npm:1.8.1" - dependencies: - follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.0" - proxy-from-env: "npm:^1.1.0" - checksum: 10c0/b2e1d5a61264502deee4b50f0a6df0aa3b174c546ccf68c0dff714a2b8863232e0bd8cb5b84f853303e97f242a98260f9bb9beabeafe451ad5af538e9eb7ac22 - languageName: node - linkType: hard - -"axios@npm:^1.6.7": - version: 1.18.1 - resolution: "axios@npm:1.18.1" +"axios@npm:^1.8.4": + version: 1.20.0 + resolution: "axios@npm:1.20.0" dependencies: follow-redirects: "npm:^1.16.0" - form-data: "npm:^4.0.5" + form-data: "npm:^4.0.6" https-proxy-agent: "npm:^5.0.1" proxy-from-env: "npm:^2.1.0" - checksum: 10c0/9d9378a3af0d0ad730a52ad9d15ec7201f3926ad6e7e8bbffc5ae21ca2835ad11d1d9598698f5dd9718917486039f55ea1d7dc23d8e44fa827a55cc3262c02fc + checksum: 10c0/976088acf532286356f4c2e65df1ef47ba7da3936d83e928d0d64357bbf5370456abd3eb5826c15df322335fcb1fe200d4a84b4fcf20ffccdd63b40d80fa495c languageName: node linkType: hard @@ -3623,6 +3581,13 @@ __metadata: languageName: node linkType: hard +"bignumber.js@npm:^9.1.2": + version: 9.3.1 + resolution: "bignumber.js@npm:9.3.1" + checksum: 10c0/61342ba5fe1c10887f0ecf5be02ff6709271481aff48631f86b4d37d55a99b87ce441cfd54df3d16d10ee07ceab7e272fc0be430c657ffafbbbf7b7d631efb75 + languageName: node + linkType: hard + "binary-extensions@npm:^2.0.0": version: 2.2.0 resolution: "binary-extensions@npm:2.2.0" @@ -4292,7 +4257,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.3": +"cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": version: 0.6.5 resolution: "cli-table3@npm:0.6.5" dependencies: @@ -4439,6 +4404,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^9.4.0": + version: 9.5.0 + resolution: "commander@npm:9.5.0" + checksum: 10c0/5f7784fbda2aaec39e89eb46f06a999e00224b3763dc65976e05929ec486e174fe9aac2655f03ba6a5e83875bd173be5283dc19309b7c65954701c02025b3c1d + languageName: node + linkType: hard + "comment-parser@npm:^1.4.1": version: 1.4.8 resolution: "comment-parser@npm:1.4.8" @@ -4676,15 +4648,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:=3.1.0": - version: 3.1.0 - resolution: "debug@npm:3.1.0" - dependencies: - ms: "npm:2.0.0" - checksum: 10c0/5bff34a352d7b2eaa31886eeaf2ee534b5461ec0548315b2f9f80bd1d2533cab7df1fa52e130ce27bc31c3945fbffb0fc72baacdceb274b95ce853db89254ea4 - languageName: node - linkType: hard - "debug@npm:^3.1.0": version: 3.2.7 resolution: "debug@npm:3.2.7" @@ -4865,6 +4828,13 @@ __metadata: languageName: node linkType: hard +"define-lazy-prop@npm:^2.0.0": + version: 2.0.0 + resolution: "define-lazy-prop@npm:2.0.0" + checksum: 10c0/db6c63864a9d3b7dc9def55d52764968a5af296de87c1b2cc71d8be8142e445208071953649e0386a8cc37cfcf9a2067a47207f1eb9ff250c2a269658fdae422 + languageName: node + linkType: hard + "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -5355,16 +5325,6 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 - languageName: node - linkType: hard - "esquery@npm:^1.7.0": version: 1.7.0 resolution: "esquery@npm:1.7.0" @@ -5540,6 +5500,19 @@ __metadata: languageName: node linkType: hard +"ethereumjs-util@npm:^7.1.4, ethereumjs-util@npm:^7.1.5": + version: 7.1.5 + resolution: "ethereumjs-util@npm:7.1.5" + dependencies: + "@types/bn.js": "npm:^5.1.0" + bn.js: "npm:^5.1.2" + create-hash: "npm:^1.1.2" + ethereum-cryptography: "npm:^0.1.3" + rlp: "npm:^2.2.4" + checksum: 10c0/8b9487f35ecaa078bf9af6858eba6855fc61c73cc2b90c8c37486fcf94faf4fc1c5cda9758e6769f9ef2658daedaf2c18b366312ac461f8c8a122b392e3041eb + languageName: node + linkType: hard + "ethers@npm:4.0.0-beta.3": version: 4.0.0-beta.3 resolution: "ethers@npm:4.0.0-beta.3" @@ -5575,45 +5548,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^5.5.3": - version: 5.5.3 - resolution: "ethers@npm:5.5.3" - dependencies: - "@ethersproject/abi": "npm:5.5.0" - "@ethersproject/abstract-provider": "npm:5.5.1" - "@ethersproject/abstract-signer": "npm:5.5.0" - "@ethersproject/address": "npm:5.5.0" - "@ethersproject/base64": "npm:5.5.0" - "@ethersproject/basex": "npm:5.5.0" - "@ethersproject/bignumber": "npm:5.5.0" - "@ethersproject/bytes": "npm:5.5.0" - "@ethersproject/constants": "npm:5.5.0" - "@ethersproject/contracts": "npm:5.5.0" - "@ethersproject/hash": "npm:5.5.0" - "@ethersproject/hdnode": "npm:5.5.0" - "@ethersproject/json-wallets": "npm:5.5.0" - "@ethersproject/keccak256": "npm:5.5.0" - "@ethersproject/logger": "npm:5.5.0" - "@ethersproject/networks": "npm:5.5.2" - "@ethersproject/pbkdf2": "npm:5.5.0" - "@ethersproject/properties": "npm:5.5.0" - "@ethersproject/providers": "npm:5.5.2" - "@ethersproject/random": "npm:5.5.1" - "@ethersproject/rlp": "npm:5.5.0" - "@ethersproject/sha2": "npm:5.5.0" - "@ethersproject/signing-key": "npm:5.5.0" - "@ethersproject/solidity": "npm:5.5.0" - "@ethersproject/strings": "npm:5.5.0" - "@ethersproject/transactions": "npm:5.5.0" - "@ethersproject/units": "npm:5.5.0" - "@ethersproject/wallet": "npm:5.5.0" - "@ethersproject/web": "npm:5.5.1" - "@ethersproject/wordlists": "npm:5.5.0" - checksum: 10c0/9ba7d7a06e536e7374ec0aa769dc8a9bb38b42c18a1a486d8e2f5bf04573b3cc5c9149c8467f17af16db14acfe86f04b20432b9afa4cf541108f1223552e65c9 - languageName: node - linkType: hard - -"ethers@npm:^5.6.8, ethers@npm:^5.7.0": +"ethers@npm:^5.7.0, ethers@npm:^5.7.2": version: 5.8.0 resolution: "ethers@npm:5.8.0" dependencies: @@ -5651,6 +5586,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.17.0, ethers@npm:^6.8.1": + version: 6.17.0 + resolution: "ethers@npm:6.17.0" + dependencies: + "@adraffy/ens-normalize": "npm:1.11.1" + "@noble/curves": "npm:1.2.0" + "@noble/hashes": "npm:1.3.2" + "@types/node": "npm:22.7.5" + aes-js: "npm:4.0.0-beta.5" + tslib: "npm:2.7.0" + ws: "npm:8.21.0" + checksum: 10c0/0a75f3b4cedaaddb95ba31fecdfca04202735564e66512f202069dd1a11946e01c310a158e3a1299b994274e9d9fe11db10c6f7997222a28d79dfecb8f1fd162 + languageName: node + linkType: hard + "ethers@npm:~5.7.0": version: 5.7.2 resolution: "ethers@npm:5.7.2" @@ -5991,16 +5941,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:1.5.10": - version: 1.5.10 - resolution: "follow-redirects@npm:1.5.10" - dependencies: - debug: "npm:=3.1.0" - checksum: 10c0/f56ca26dcf3c9996a6cf8868b61e369a35d4000ade0292bdd27b5e0934902681b037060b9fabe58e7042bb8b85166d5db8bbcf027f1825c1577e4cffd904fd3f - languageName: node - linkType: hard - -"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0": +"follow-redirects@npm:^1.12.1": version: 1.14.7 resolution: "follow-redirects@npm:1.14.7" peerDependenciesMeta: @@ -6010,16 +5951,6 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.15.6": - version: 1.15.9 - resolution: "follow-redirects@npm:1.15.9" - peerDependenciesMeta: - debug: - optional: true - checksum: 10c0/5829165bd112c3c0e82be6c15b1a58fa9dcfaede3b3c54697a82fe4a62dd5ae5e8222956b448d2f98e331525f05d00404aba7d696de9e761ef6e42fdc780244f - languageName: node - linkType: hard - "follow-redirects@npm:^1.16.0": version: 1.16.0 resolution: "follow-redirects@npm:1.16.0" @@ -6074,7 +6005,7 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^4.0.5": +"form-data@npm:^4.0.6": version: 4.0.6 resolution: "form-data@npm:4.0.6" dependencies: @@ -6144,6 +6075,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^10.1.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/5f579466e7109719d162a9249abbeffe7f426eb133ea486e020b89bc6d67a741134076bf439983f2eb79276ceaf6bd7b7c1e43c3fd67fe889863e69072fb0a5e + languageName: node + linkType: hard + "fs-extra@npm:^11.2.0": version: 11.3.4 resolution: "fs-extra@npm:11.3.4" @@ -6177,7 +6119,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^9.0.1, fs-extra@npm:^9.1.0": +"fs-extra@npm:^9.1.0": version: 9.1.0 resolution: "fs-extra@npm:9.1.0" dependencies: @@ -6576,7 +6518,7 @@ __metadata: languageName: node linkType: hard -"hardhat-deploy@npm:^0.11.10": +"hardhat-deploy@npm:^0.11.43": version: 0.11.45 resolution: "hardhat-deploy@npm:0.11.45" dependencies: @@ -7132,13 +7074,6 @@ __metadata: languageName: node linkType: hard -"is-buffer@npm:^2.0.2": - version: 2.0.5 - resolution: "is-buffer@npm:2.0.5" - checksum: 10c0/e603f6fced83cf94c53399cff3bda1a9f08e391b872b64a73793b0928be3e5f047f2bcece230edb7632eaea2acdbfcb56c23b33d8a20c820023b230f1485679a - languageName: node - linkType: hard - "is-bun-module@npm:^2.0.0": version: 2.0.0 resolution: "is-bun-module@npm:2.0.0" @@ -7155,6 +7090,15 @@ __metadata: languageName: node linkType: hard +"is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": + version: 2.2.1 + resolution: "is-docker@npm:2.2.1" + bin: + is-docker: cli.js + checksum: 10c0/e828365958d155f90c409cdbe958f64051d99e8aedc2c8c4cd7c89dcf35329daed42f7b99346f7828df013e27deb8f721cf9408ba878c76eb9e8290235fbcdcc + languageName: node + linkType: hard + "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -7271,6 +7215,15 @@ __metadata: languageName: node linkType: hard +"is-wsl@npm:^2.2.0": + version: 2.2.0 + resolution: "is-wsl@npm:2.2.0" + dependencies: + is-docker: "npm:^2.0.0" + checksum: 10c0/a6fa2d370d21be487c0165c7a440d567274fbba1a817f2f0bfa41cc5e3af25041d84267baa22df66696956038a43973e72fca117918c91431920bdef490fa25e + languageName: node + linkType: hard + "isarray@npm:^1.0.0, isarray@npm:~1.0.0": version: 1.0.0 resolution: "isarray@npm:1.0.0" @@ -7355,6 +7308,13 @@ __metadata: languageName: node linkType: hard +"js-cookie@npm:^3.0.7": + version: 3.0.8 + resolution: "js-cookie@npm:3.0.8" + checksum: 10c0/421912a4a55535bda32b3059835864e1182c3af5b4516df00a060edc1fa5a53d38bb8d5a91d5d305e396206f4fd11e829f17850aa5aa8164118c04d8ebf1ff5d + languageName: node + linkType: hard + "js-sha3@npm:0.5.7, js-sha3@npm:^0.5.7": version: 0.5.7 resolution: "js-sha3@npm:0.5.7" @@ -7376,18 +7336,6 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.14.0": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: "npm:^1.0.7" - esprima: "npm:^4.0.0" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/6746baaaeac312c4db8e75fa22331d9a04cccb7792d126ed8ce6a0bbcfef0cedaddd0c5098fade53db067c09fe00aa1c957674b4765610a8b06a5a189e46433b - languageName: node - linkType: hard - "js-yaml@npm:^4.1.0": version: 4.3.0 resolution: "js-yaml@npm:4.3.0" @@ -7580,6 +7528,13 @@ __metadata: languageName: node linkType: hard +"kleur@npm:^3.0.3": + version: 3.0.3 + resolution: "kleur@npm:3.0.3" + checksum: 10c0/cd3a0b8878e7d6d3799e54340efe3591ca787d9f95f109f28129bdd2915e37807bf8918bb295ab86afb8c82196beec5a1adcaf29042ce3f2bd932b038fe3aa4b + languageName: node + linkType: hard + "latest-version@npm:^7.0.0": version: 7.0.0 resolution: "latest-version@npm:7.0.0" @@ -7646,6 +7601,13 @@ __metadata: languageName: node linkType: hard +"lodash.isequal@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.isequal@npm:4.5.0" + checksum: 10c0/dfdb2356db19631a4b445d5f37868a095e2402292d59539a987f134a8778c62a2810c2452d11ae9e6dcac71fc9de40a6fedcb20e2952a15b431ad8b29e50e28f + languageName: node + linkType: hard + "lodash.truncate@npm:^4.4.2": version: 4.4.2 resolution: "lodash.truncate@npm:4.4.2" @@ -8402,7 +8364,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": version: 1.13.4 resolution: "object-inspect@npm:1.13.4" checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 @@ -8452,6 +8414,17 @@ __metadata: languageName: node linkType: hard +"open@npm:^8.4.0": + version: 8.4.2 + resolution: "open@npm:8.4.2" + dependencies: + define-lazy-prop: "npm:^2.0.0" + is-docker: "npm:^2.1.1" + is-wsl: "npm:^2.2.0" + checksum: 10c0/bb6b3a58401dacdb0aad14360626faf3fb7fba4b77816b373495988b724fb48941cad80c1b65d62bb31a17609b2cd91c41a181602caea597ca80dfbcc27e84c9 + languageName: node + linkType: hard + "openzeppelin-solidity@npm:2.4.0": version: 2.4.0 resolution: "openzeppelin-solidity@npm:2.4.0" @@ -8931,6 +8904,16 @@ __metadata: languageName: node linkType: hard +"prompts@npm:^2.4.2": + version: 2.4.2 + resolution: "prompts@npm:2.4.2" + dependencies: + kleur: "npm:^3.0.3" + sisteransi: "npm:^1.0.5" + checksum: 10c0/16f1ac2977b19fe2cf53f8411cc98db7a3c8b115c479b2ca5c82b5527cd937aa405fa04f9a5960abeb9daef53191b53b4d13e35c1f5d50e8718c76917c5f1ea4 + languageName: node + linkType: hard + "proper-lockfile@npm:^4.1.1": version: 4.1.2 resolution: "proper-lockfile@npm:4.1.2" @@ -8959,13 +8942,6 @@ __metadata: languageName: node linkType: hard -"proxy-from-env@npm:^1.1.0": - version: 1.1.0 - resolution: "proxy-from-env@npm:1.1.0" - checksum: 10c0/fe7dd8b1bdbbbea18d1459107729c3e4a2243ca870d26d34c2c1bcd3e4425b7bcc5112362df2d93cc7fb9746f6142b5e272fd1cc5c86ddf8580175186f6ad42b - languageName: node - linkType: hard - "proxy-from-env@npm:^2.1.0": version: 2.1.0 resolution: "proxy-from-env@npm:2.1.0" @@ -9027,7 +9003,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.10.3, qs@npm:^6.9.4": +"qs@npm:6.10.3": version: 6.10.3 resolution: "qs@npm:6.10.3" dependencies: @@ -9036,6 +9012,16 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.9.4": + version: 6.15.3 + resolution: "qs@npm:6.15.3" + dependencies: + es-define-property: "npm:^1.0.1" + side-channel: "npm:^1.1.1" + checksum: 10c0/8f3f6e45ece255347d57696628401cde29e9ec649fff698b53bd3150dea7cefdf33036e1bc1826b9f110bfa7cb0ec4ab9f5297eca628ce216c55af82c304e08e + languageName: node + linkType: hard + "qs@npm:~6.5.2": version: 6.5.3 resolution: "qs@npm:6.5.3" @@ -9599,6 +9585,16 @@ __metadata: languageName: node linkType: hard +"side-channel-list@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-list@npm:1.0.1" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.4" + checksum: 10c0/d346c787fd2f9f1c2fdea14f00e8250118db0e7596d85a6cb9faa75f105d31a73a8f7a341c93d7df2a2429098c3d37a77bd3be9e88c37094b8c01807bc77c7a2 + languageName: node + linkType: hard + "side-channel-map@npm:^1.0.1": version: 1.0.1 resolution: "side-channel-map@npm:1.0.1" @@ -9637,6 +9633,19 @@ __metadata: languageName: node linkType: hard +"side-channel@npm:^1.1.1": + version: 1.1.1 + resolution: "side-channel@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.4" + side-channel-list: "npm:^1.0.1" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10c0/dc0ab81d67f61bda9247d053ce93f41c3fd8ad2bdcb9cf9d8d2f8540d488f26d87a5e99ebfc07eea49ec025867b2452b705442d974b1478f0395e69f6bfb3270 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.2": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -9669,6 +9678,13 @@ __metadata: languageName: node linkType: hard +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: 10c0/230ac975cca485b7f6fe2b96a711aa62a6a26ead3e6fb8ba17c5a00d61b8bed0d7adc21f5626b70d7c33c62ff4e63933017a6462942c719d1980bb0b1207ad46 + languageName: node + linkType: hard + "slice-ansi@npm:^4.0.0": version: 4.0.0 resolution: "slice-ansi@npm:4.0.0" @@ -9763,10 +9779,10 @@ __metadata: languageName: node linkType: hard -"solidity-ast@npm:^0.4.51": - version: 0.4.59 - resolution: "solidity-ast@npm:0.4.59" - checksum: 10c0/d296ea890bfb026580b0b87623a1450d7de5be417395c1b017778b390e978c717e26c79fddcfb25d36134c425d4a4f813d60a1532ecc53c704ce5c9d4e322215 +"solidity-ast@npm:^0.4.60": + version: 0.4.62 + resolution: "solidity-ast@npm:0.4.62" + checksum: 10c0/8f9bfb41dddaa68e48d8620785cae43583a6711e79b132d3110f8cbf8f028a41004ca6ff8a3896f1e7f408932efb28b9f0390a67e729c12033ec95895430efeb languageName: node linkType: hard @@ -9810,13 +9826,6 @@ __metadata: languageName: node linkType: hard -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 10c0/ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb - languageName: node - linkType: hard - "sshpk@npm:^1.7.0": version: 1.17.0 resolution: "sshpk@npm:1.17.0" @@ -10125,6 +10134,29 @@ __metadata: languageName: node linkType: hard +"tenderly@npm:^0.8.0": + version: 0.8.0 + resolution: "tenderly@npm:0.8.0" + dependencies: + axios: "npm:^0.27.2" + cli-table3: "npm:^0.6.2" + commander: "npm:^9.4.0" + js-yaml: "npm:^4.1.0" + open: "npm:^8.4.0" + prompts: "npm:^2.4.2" + tslog: "npm:^4.4.0" + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + checksum: 10c0/090d3a526d9881968a1bb4f6d2fbe33db3a00677adfcf05ae54c7a585cab14760651982d0a5ded3caa9efdc3f6744cbf55abfcca74e4713941f2167be76cbfea + languageName: node + linkType: hard + "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -10309,6 +10341,51 @@ __metadata: languageName: node linkType: hard +"ts-node@npm:^10.9.1": + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" + dependencies: + "@cspotcode/source-map-support": "npm:^0.8.0" + "@tsconfig/node10": "npm:^1.0.7" + "@tsconfig/node12": "npm:^1.0.7" + "@tsconfig/node14": "npm:^1.0.0" + "@tsconfig/node16": "npm:^1.0.2" + acorn: "npm:^8.4.1" + acorn-walk: "npm:^8.1.1" + arg: "npm:^4.1.0" + create-require: "npm:^1.1.0" + diff: "npm:^4.0.1" + make-error: "npm:^1.1.1" + v8-compile-cache-lib: "npm:^3.0.1" + yn: "npm:3.1.1" + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: 10c0/5f29938489f96982a25ba650b64218e83a3357d76f7bede80195c65ab44ad279c8357264639b7abdd5d7e75fc269a83daa0e9c62fd8637a3def67254ecc9ddc2 + languageName: node + linkType: hard + +"tslib@npm:2.7.0": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 + languageName: node + linkType: hard + "tslib@npm:^1.11.1, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" @@ -10323,6 +10400,13 @@ __metadata: languageName: node linkType: hard +"tslog@npm:^4.3.1, tslog@npm:^4.4.0": + version: 4.11.0 + resolution: "tslog@npm:4.11.0" + checksum: 10c0/1bf7aa08d110da69bfe34aadf24fd1e61d3823d5fe82986e35d3279f3dd11ce1c94430620d55dccc05c280351060b6cd0ef31944abf9320884e8572576f4d71d + languageName: node + linkType: hard + "tsort@npm:0.0.1": version: 0.0.1 resolution: "tsort@npm:0.0.1" @@ -10464,6 +10548,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.2.2": + version: 5.9.3 + resolution: "typescript@npm:5.9.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/6bd7552ce39f97e711db5aa048f6f9995b53f1c52f7d8667c1abdc1700c68a76a308f579cd309ce6b53646deb4e9a1be7c813a93baaf0a28ccd536a30270e1c5 + languageName: node + linkType: hard + "typescript@npm:^6.0.3": version: 6.0.3 resolution: "typescript@npm:6.0.3" @@ -10474,6 +10568,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.2.2#optional!builtin": + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/ad09fdf7a756814dce65bc60c1657b40d44451346858eea230e10f2e95a289d9183b6e32e5c11e95acc0ccc214b4f36289dcad4bf1886b0adb84d711d336a430 + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A^6.0.3#optional!builtin": version: 6.0.3 resolution: "typescript@patch:typescript@npm%3A6.0.3#optional!builtin::version=6.0.3&hash=5786d5" @@ -10531,6 +10635,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.19.2": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 + languageName: node + linkType: hard + "undici-types@npm:~7.18.0": version: 7.18.2 resolution: "undici-types@npm:7.18.2" @@ -10754,6 +10865,13 @@ __metadata: languageName: node linkType: hard +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 10c0/bdc36fb8095d3b41df197f5fb6f11e3a26adf4059df3213e3baa93810d8f0cc76f9a74aaefc18b73e91fe7e19154ed6f134eda6fded2e0f1c8d2272ed2d2d391 + languageName: node + linkType: hard + "vary@npm:^1, vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" diff --git a/solidity/random-beacon/.dockerignore b/solidity/random-beacon/.dockerignore index 17165d83c9..1e58a46276 100644 --- a/solidity/random-beacon/.dockerignore +++ b/solidity/random-beacon/.dockerignore @@ -2,6 +2,12 @@ .* !.yarnrc.yml +# Include local dependency patches, but exclude Yarn caches and install state. +!.yarn +.yarn/** +!.yarn/patches +!.yarn/patches/** + # Documentation docs/ diff --git a/solidity/random-beacon/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch b/solidity/random-beacon/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch new file mode 100644 index 0000000000..3acb0a3521 --- /dev/null +++ b/solidity/random-beacon/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch @@ -0,0 +1,520 @@ +diff --git a/dist/contracts.d.ts b/dist/contracts.d.ts +index e67607c..de33123 100644 +--- a/dist/contracts.d.ts ++++ b/dist/contracts.d.ts +@@ -1,7 +1,7 @@ +-import type { Contract } from "ethers"; ++import type { BaseContract, Contract } from "ethers"; + import type { HardhatRuntimeEnvironment } from "hardhat/types"; + export interface HardhatContractsHelpers { +- getContract(deploymentName: string): Promise; ++ getContract(deploymentName: string): Promise; + } + export default function (hre: HardhatRuntimeEnvironment): HardhatContractsHelpers; + //# sourceMappingURL=contracts.d.ts.map +\ No newline at end of file +diff --git a/dist/upgrades.d.ts b/dist/upgrades.d.ts +index 2eb5874..a07f2ae 100644 +--- a/dist/upgrades.d.ts ++++ b/dist/upgrades.d.ts +@@ -1,24 +1,24 @@ + import "@openzeppelin/hardhat-upgrades"; +-import type { Contract, ContractTransaction } from "ethers"; ++import type { BaseContract, Contract, ContractTransaction } from "ethers"; + import type { FactoryOptions, HardhatRuntimeEnvironment } from "hardhat/types"; + import type { Deployment } from "hardhat-deploy/dist/types"; + import type { DeployProxyOptions, UpgradeProxyOptions } from "@openzeppelin/hardhat-upgrades/src/utils/options"; + import { Libraries } from "hardhat-deploy/types"; + export interface HardhatUpgradesHelpers { +- deployProxy(name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; +- upgradeProxy(currentContractName: string, newContractName: string, opts?: UpgradesUpgradeOptions): Promise<[T, Deployment]>; ++ deployProxy(name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; ++ upgradeProxy(currentContractName: string, newContractName: string, opts?: UpgradesUpgradeOptions): Promise<[T, Deployment]>; + prepareProxyUpgrade(proxyDeploymentName: string, newContractName: string, opts?: UpgradesPrepareProxyUpgradeOptions): Promise<{ + newImplementationAddress: string; + preparedTransaction: ContractTransaction; + }>; + } + type CustomFactoryOptions = FactoryOptions & { + libraries?: Libraries; + }; + export interface UpgradesDeployOptions { + contractName?: string; + initializerArgs?: unknown[]; + factoryOpts?: CustomFactoryOptions; + proxyOpts?: DeployProxyOptions; + } + export interface UpgradesUpgradeOptions { +@@ -27,19 +27,19 @@ export interface UpgradesUpgradeOptions { + factoryOpts?: CustomFactoryOptions; + proxyOpts?: UpgradeProxyOptions; + } + export interface UpgradesPrepareProxyUpgradeOptions { + contractName?: string; + factoryOpts?: CustomFactoryOptions; + callData?: string; + } + /** + * Deploys contract as a TransparentProxy. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} name Contract Name + * @param {UpgradesDeployOptions} opts + */ +-export declare function deployProxy(hre: HardhatRuntimeEnvironment, name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; ++export declare function deployProxy(hre: HardhatRuntimeEnvironment, name: string, opts?: UpgradesDeployOptions): Promise<[T, Deployment]>; + export default function (hre: HardhatRuntimeEnvironment): HardhatUpgradesHelpers; + export {}; + //# sourceMappingURL=upgrades.d.ts.map +\ No newline at end of file +diff --git a/dist/upgrades.js b/dist/upgrades.js +index 6367def..cfb0e32 100644 +--- a/dist/upgrades.js ++++ b/dist/upgrades.js +@@ -1,54 +1,85 @@ + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.deployProxy = void 0; + require("@openzeppelin/hardhat-upgrades"); +-const utils_1 = require("@openzeppelin/hardhat-upgrades/dist/utils"); ++const ProxyAdminV4 = require("@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json"); ++const ProxyAdminV5 = require("@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts-v5/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json"); + const upgrades_core_1 = require("@openzeppelin/upgrades-core"); + /** + * Deploys contract as a TransparentProxy. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} name Contract Name + * @param {UpgradesDeployOptions} opts + */ ++// Preserve the receipt metadata published by hardhat-helpers 0.6. ++function toDeploymentReceipt(receipt) { ++ return { ++ to: receipt.to, ++ from: receipt.from, ++ contractAddress: receipt.contractAddress, ++ transactionIndex: receipt.index, ++ gasUsed: receipt.gasUsed.toString(), ++ logsBloom: receipt.logsBloom, ++ blockHash: receipt.blockHash, ++ transactionHash: receipt.hash, ++ logs: receipt.logs.map((log) => ({ ++ transactionIndex: log.transactionIndex, ++ blockNumber: log.blockNumber, ++ transactionHash: log.transactionHash, ++ address: log.address, ++ topics: [...log.topics], ++ data: log.data, ++ logIndex: log.index, ++ blockHash: log.blockHash, ++ // Mined receipt logs omit the removed field in the existing export format. ++ removed: undefined, ++ })), ++ blockNumber: receipt.blockNumber, ++ cumulativeGasUsed: receipt.cumulativeGasUsed.toString(), ++ status: receipt.status, ++ byzantium: receipt.status !== null, ++ } ++} + async function deployProxy(hre, name, opts) { + const { ethers, upgrades, deployments, artifacts } = hre; + const { log } = deployments; + const existingDeployment = await deployments.getOrNull(name); + if (existingDeployment) { + throw new Error(`${name} was already deployed at ${existingDeployment.address}`); + } + const contractFactory = await ethers.getContractFactory(opts?.contractName || name, opts?.factoryOpts); + const contractInstance = (await upgrades.deployProxy(contractFactory, opts?.initializerArgs, opts?.proxyOpts)); + const deploymentTransaction = contractInstance.deploymentTransaction(); + // Let the transaction propagate across the ethereum nodes. This is mostly to + // wait for all Alchemy nodes to catch up their state. + const transactionReceipt = await deploymentTransaction?.wait(1); + const contractAddress = await contractInstance.getAddress(); + const transactionHash = deploymentTransaction?.hash; + log(`Deployed ${name} as ${opts?.proxyOpts?.kind || "transparent"} proxy at ${contractAddress} (tx: ${transactionHash})`); + const artifact = artifacts.readArtifactSync(opts?.contractName || name); + const implementation = await upgrades.erc1967.getImplementationAddress(contractAddress); + if (!transactionReceipt || !transactionHash) { + throw new Error(`Could not find transaction receipt for transaction hash: ${transactionHash}`); + } + const deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + }; + await deployments.save(name, deployment); + return [contractInstance, deployment]; + } + exports.deployProxy = deployProxy; + /** + * Upgrades previously deployed contract. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} proxyDeploymentName Name of the proxy deployment that will be + * upgraded. + * @param {string} newContractName Name of the new implementation contract. +@@ -72,30 +103,31 @@ async function upgradeProxy(hre, proxyDeploymentName, newContractName, opts) { + const contractAddress = await newContractInstance.getAddress(); + const transactionHash = deploymentTransaction?.hash; + log(`Upgraded ${proxyDeploymentName} proxy contract (address: ${proxyDeployment.address}) ` + + `in tx: ${transactionHash}`); + const artifact = artifacts.readArtifactSync(opts?.contractName || newContractName); + const implementation = await upgrades.erc1967.getImplementationAddress(contractAddress); + log(`New ${proxyDeploymentName} proxy contract implementation address is: ${implementation}`); + if (!transactionReceipt || !transactionHash) { + throw new Error(`Could not find transaction receipt for transaction hash: ${transactionHash}`); + } + const deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + }; + await deployments.save(proxyDeploymentName, deployment); + return [newContractInstance, deployment]; + } + /** + * Prepare upgrade of deployed contract. + * It deploys new implementation contract and prepares transaction to upgrade + * the proxy contract to the new implementation thorough a Proxy Admin instance. + * The transaction has to be executed by the owner of the Proxy Admin. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} proxyDeploymentName Name of the proxy deployment that will be +@@ -108,40 +140,40 @@ async function prepareProxyUpgrade(hre, proxyDeploymentName, newContractName, op + const signer = await ethers.provider.getSigner(); + const { log } = deployments; + const proxyDeployment = await deployments.get(proxyDeploymentName); + const implementationContractFactory = await ethers.getContractFactory(opts?.contractName || newContractName, opts?.factoryOpts); + const newImplementationAddress = (await upgrades.prepareUpgrade(proxyDeployment.address, implementationContractFactory, { + kind: "transparent", + getTxResponse: false, + })); + log(`new implementation contract deployed at: ${newImplementationAddress}`); + const proxyAdminAddress = await hre.upgrades.erc1967.getAdminAddress(proxyDeployment.address); + let proxyAdmin; + let upgradeTxData; + const proxyInterfaceVersion = await (0, upgrades_core_1.getUpgradeInterfaceVersion)(hre.network.provider, proxyAdminAddress); + switch (proxyInterfaceVersion) { + case "5.0.0": { +- proxyAdmin = await (0, utils_1.attachProxyAdminV5)(hre, proxyAdminAddress, signer); ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV5.abi, proxyAdminAddress, signer); + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgradeAndCall", [ + proxyDeployment.address, + newImplementationAddress, + opts?.callData ?? "0x", + ]); + break; + } + default: { +- proxyAdmin = await (0, utils_1.attachProxyAdminV4)(hre, proxyAdminAddress, signer); ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV4.abi, proxyAdminAddress, signer); + if (opts?.callData) { + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgradeAndCall", [proxyDeployment.address, newImplementationAddress, opts?.callData]); + } + else { + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgrade", [ + proxyDeployment.address, + newImplementationAddress, + ]); + } + } + } + const preparedTransaction = { + from: (await proxyAdmin.owner()), + to: proxyAdminAddress, + data: upgradeTxData, +diff --git a/src/contracts.ts b/src/contracts.ts +index dc82311..b8f4d3a 100644 +--- a/src/contracts.ts ++++ b/src/contracts.ts +@@ -1,23 +1,23 @@ +-import type { Contract } from "ethers" ++import type { BaseContract, Contract } from "ethers" + import type { HardhatRuntimeEnvironment } from "hardhat/types" + + export interface HardhatContractsHelpers { +- getContract(deploymentName: string): Promise ++ getContract(deploymentName: string): Promise + } + +-async function getContract( ++async function getContract( + hre: HardhatRuntimeEnvironment, + deploymentName: string + ): Promise { + const deployment = await hre.deployments.get(deploymentName) + + return (await hre.ethers.getContractAt( + deployment.abi, + deployment.address + )) as T + } + + export default function ( + hre: HardhatRuntimeEnvironment + ): HardhatContractsHelpers { + return { +diff --git a/src/upgrades.ts b/src/upgrades.ts +index 22edb53..c7abdf3 100644 +--- a/src/upgrades.ts ++++ b/src/upgrades.ts +@@ -1,47 +1,77 @@ + import "@openzeppelin/hardhat-upgrades" + + import type { ++ BaseContract, + Contract, + ContractFactory, + ContractTransaction, + ContractTransactionResponse, ++ TransactionReceipt, + } from "ethers" + import type { + Artifact, + FactoryOptions, + HardhatRuntimeEnvironment, + } from "hardhat/types" +-import type { Deployment } from "hardhat-deploy/dist/types" ++import type { Deployment, Receipt } from "hardhat-deploy/dist/types" + import type { + DeployProxyOptions, + UpgradeProxyOptions, + } from "@openzeppelin/hardhat-upgrades/src/utils/options" + import { Libraries } from "hardhat-deploy/types" +-import { +- attachProxyAdminV4, +- attachProxyAdminV5, +-} from "@openzeppelin/hardhat-upgrades/dist/utils" ++import ProxyAdminV4 from "@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json" ++import ProxyAdminV5 from "@openzeppelin/upgrades-core/artifacts/@openzeppelin/contracts-v5/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json" + + import { getUpgradeInterfaceVersion } from "@openzeppelin/upgrades-core" + ++// Preserve the receipt metadata published by hardhat-helpers 0.6. ++function toDeploymentReceipt(receipt: TransactionReceipt): Receipt { ++ return { ++ to: receipt.to, ++ from: receipt.from, ++ contractAddress: receipt.contractAddress, ++ transactionIndex: receipt.index, ++ gasUsed: receipt.gasUsed.toString(), ++ logsBloom: receipt.logsBloom, ++ blockHash: receipt.blockHash, ++ transactionHash: receipt.hash, ++ logs: receipt.logs.map((log) => ({ ++ transactionIndex: log.transactionIndex, ++ blockNumber: log.blockNumber, ++ transactionHash: log.transactionHash, ++ address: log.address, ++ topics: [...log.topics], ++ data: log.data, ++ logIndex: log.index, ++ blockHash: log.blockHash, ++ // Mined receipt logs omit the removed field in the existing export format. ++ removed: undefined, ++ })), ++ blockNumber: receipt.blockNumber, ++ cumulativeGasUsed: receipt.cumulativeGasUsed.toString(), ++ status: receipt.status, ++ byzantium: receipt.status !== null, ++ } ++} ++ + export interface HardhatUpgradesHelpers { +- deployProxy( ++ deployProxy( + name: string, + opts?: UpgradesDeployOptions + ): Promise<[T, Deployment]> +- upgradeProxy( ++ upgradeProxy( + currentContractName: string, + newContractName: string, + opts?: UpgradesUpgradeOptions + ): Promise<[T, Deployment]> + prepareProxyUpgrade( + proxyDeploymentName: string, + newContractName: string, + opts?: UpgradesPrepareProxyUpgradeOptions + ): Promise<{ + newImplementationAddress: string + preparedTransaction: ContractTransaction + }> + } + + type CustomFactoryOptions = FactoryOptions & { +@@ -63,31 +93,31 @@ export interface UpgradesUpgradeOptions { + } + + export interface UpgradesPrepareProxyUpgradeOptions { + contractName?: string + factoryOpts?: CustomFactoryOptions + callData?: string + } + + /** + * Deploys contract as a TransparentProxy. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} name Contract Name + * @param {UpgradesDeployOptions} opts + */ +-export async function deployProxy( ++export async function deployProxy( + hre: HardhatRuntimeEnvironment, + name: string, + opts?: UpgradesDeployOptions + ): Promise<[T, Deployment]> { + const { ethers, upgrades, deployments, artifacts } = hre + const { log } = deployments + + const existingDeployment = await deployments.getOrNull(name) + if (existingDeployment) { + throw new Error( + `${name} was already deployed at ${existingDeployment.address}` + ) + } + + const contractFactory: ContractFactory = await ethers.getContractFactory( +@@ -121,50 +151,51 @@ export async function deployProxy( + const implementation = await upgrades.erc1967.getImplementationAddress( + contractAddress + ) + + if (!transactionReceipt || !transactionHash) { + throw new Error( + `Could not find transaction receipt for transaction hash: ${transactionHash}` + ) + } + + const deployment: Deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + } + + await deployments.save(name, deployment) + + return [contractInstance, deployment] + } + + /** + * Upgrades previously deployed contract. + * + * @param {HardhatRuntimeEnvironment} hre Hardhat runtime environment. + * @param {string} proxyDeploymentName Name of the proxy deployment that will be + * upgraded. + * @param {string} newContractName Name of the new implementation contract. + * @param {UpgradesDeployOptions} opts + */ +-async function upgradeProxy( ++async function upgradeProxy( + hre: HardhatRuntimeEnvironment, + proxyDeploymentName: string, + newContractName: string, + opts?: UpgradesUpgradeOptions + ): Promise<[T, Deployment]> { + const { ethers, upgrades, deployments, artifacts } = hre + const { log } = deployments + + const proxyDeployment: Deployment = await deployments.get(proxyDeploymentName) + + const newContract: ContractFactory = await ethers.getContractFactory( + opts?.contractName || newContractName, + opts?.factoryOpts + ) + +@@ -205,30 +236,31 @@ async function upgradeProxy( + log( + `New ${proxyDeploymentName} proxy contract implementation address is: ${implementation}` + ) + + if (!transactionReceipt || !transactionHash) { + throw new Error( + `Could not find transaction receipt for transaction hash: ${transactionHash}` + ) + } + + const deployment: Deployment = { + address: contractAddress, + abi: artifact.abi, + transactionHash: transactionHash, + implementation: implementation, ++ receipt: toDeploymentReceipt(transactionReceipt), + libraries: opts?.factoryOpts?.libraries, + devdoc: "Contract deployed as upgradable proxy", + args: opts?.proxyOpts?.constructorArgs, + } + + await deployments.save(proxyDeploymentName, deployment) + + return [newContractInstance, deployment] + } + + /** + * Prepare upgrade of deployed contract. + * It deploys new implementation contract and prepares transaction to upgrade + * the proxy contract to the new implementation thorough a Proxy Admin instance. + * The transaction has to be executed by the owner of the Proxy Admin. +@@ -273,44 +305,44 @@ async function prepareProxyUpgrade( + + const proxyAdminAddress = await hre.upgrades.erc1967.getAdminAddress( + proxyDeployment.address + ) + + let proxyAdmin: Contract + let upgradeTxData: string + + const proxyInterfaceVersion = await getUpgradeInterfaceVersion( + hre.network.provider, + proxyAdminAddress + ) + + switch (proxyInterfaceVersion) { + case "5.0.0": { +- proxyAdmin = await attachProxyAdminV5(hre, proxyAdminAddress, signer) ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV5.abi, proxyAdminAddress, signer) + + upgradeTxData = proxyAdmin.interface.encodeFunctionData( + "upgradeAndCall", + [ + proxyDeployment.address, + newImplementationAddress, + opts?.callData ?? "0x", + ] + ) + break + } + default: { +- proxyAdmin = await attachProxyAdminV4(hre, proxyAdminAddress, signer) ++ proxyAdmin = await hre.ethers.getContractAt(ProxyAdminV4.abi, proxyAdminAddress, signer) + + if (opts?.callData) { + upgradeTxData = proxyAdmin.interface.encodeFunctionData( + "upgradeAndCall", + [proxyDeployment.address, newImplementationAddress, opts?.callData] + ) + } else { + upgradeTxData = proxyAdmin.interface.encodeFunctionData("upgrade", [ + proxyDeployment.address, + newImplementationAddress, + ]) + } + } + } + diff --git a/solidity/random-beacon/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch b/solidity/random-beacon/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch new file mode 100644 index 0000000000..06d2c0a560 --- /dev/null +++ b/solidity/random-beacon/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch @@ -0,0 +1,85 @@ +diff --git a/src/utils/etherscan-api.ts b/src/utils/etherscan-api.ts +--- a/src/utils/etherscan-api.ts ++++ b/src/utils/etherscan-api.ts +@@ -2,36 +2,39 @@ + import { HardhatRuntimeEnvironment } from 'hardhat/types'; + + import { request } from 'undici'; + + import debug from './debug'; + import { Etherscan } from '@nomicfoundation/hardhat-verify/etherscan'; + + /** + * Call the configured Etherscan API with the given parameters. + * + * @param etherscan Etherscan instance + * @param params The API parameters to call with + * @returns The Etherscan API response + */ + export async function callEtherscanApi(etherscan: Etherscan, params: any): Promise { + const parameters = new URLSearchParams({ ...params, apikey: etherscan.apiKey }); ++ if (etherscan.chainId !== undefined) { ++ parameters.set('chainid', etherscan.chainId); ++ } + + const response = await request(etherscan.apiUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: parameters.toString(), + }); + + if (!(response.statusCode >= 200 && response.statusCode <= 299)) { + const responseBodyText = await response.body.text(); + throw new UpgradesError( + `Etherscan API call failed with status ${response.statusCode}, response: ${responseBodyText}`, + ); + } + + const responseBodyJson = await response.body.json(); + debug('Etherscan response', JSON.stringify(responseBodyJson)); + + return responseBodyJson; + } + +diff --git a/dist/utils/etherscan-api.js b/dist/utils/etherscan-api.js +--- a/dist/utils/etherscan-api.js ++++ b/dist/utils/etherscan-api.js +@@ -4,35 +4,38 @@ + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.verifyAndGetStatus = exports.RESPONSE_OK = exports.getEtherscanInstance = exports.callEtherscanApi = void 0; + const upgrades_core_1 = require("@openzeppelin/upgrades-core"); + const undici_1 = require("undici"); + const debug_1 = __importDefault(require("./debug")); + const etherscan_1 = require("@nomicfoundation/hardhat-verify/etherscan"); + /** + * Call the configured Etherscan API with the given parameters. + * + * @param etherscan Etherscan instance + * @param params The API parameters to call with + * @returns The Etherscan API response + */ + async function callEtherscanApi(etherscan, params) { + const parameters = new URLSearchParams({ ...params, apikey: etherscan.apiKey }); ++ if (etherscan.chainId !== undefined) { ++ parameters.set('chainid', etherscan.chainId); ++ } + const response = await (0, undici_1.request)(etherscan.apiUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: parameters.toString(), + }); + if (!(response.statusCode >= 200 && response.statusCode <= 299)) { + const responseBodyText = await response.body.text(); + throw new upgrades_core_1.UpgradesError(`Etherscan API call failed with status ${response.statusCode}, response: ${responseBodyText}`); + } + const responseBodyJson = await response.body.json(); + (0, debug_1.default)('Etherscan response', JSON.stringify(responseBodyJson)); + return responseBodyJson; + } + exports.callEtherscanApi = callEtherscanApi; + /** + * Gets an Etherscan instance based on Hardhat config. + * Throws an error if Etherscan API key is not present in config. + */ + async function getEtherscanInstance(hre) { diff --git a/solidity/random-beacon/.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch b/solidity/random-beacon/.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch new file mode 100644 index 0000000000..3e3b7c21ed --- /dev/null +++ b/solidity/random-beacon/.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch @@ -0,0 +1,28 @@ +diff --git a/export/deploy/07_deploy_token_staking.js b/export/deploy/07_deploy_token_staking.js +--- a/export/deploy/07_deploy_token_staking.js ++++ b/export/deploy/07_deploy_token_staking.js +@@ -62,10 +62,10 @@ + })]; + case 4: + tokenStaking = _a.sent(); +- tokenStakingAddress = tokenStaking.address; ++ tokenStakingAddress = tokenStaking.target; + log("Deployed TokenStaking with TransparentProxy at ".concat(tokenStakingAddress)); + implementationInterface = tokenStaking.interface; +- jsonAbi = implementationInterface.format(hardhat_1.ethers.utils.FormatTypes.json); ++ jsonAbi = implementationInterface.formatJson(); + tokenStakingDeployment = { + address: tokenStakingAddress, + abi: JSON.parse(jsonAbi), +diff --git a/export/deploy/30_deploy_tokenholder_timelock.js b/export/deploy/30_deploy_tokenholder_timelock.js +--- a/export/deploy/30_deploy_tokenholder_timelock.js ++++ b/export/deploy/30_deploy_tokenholder_timelock.js +@@ -51,7 +51,7 @@ + case 1: + deployer = (_a.sent()).deployer; + proposers = []; +- executors = [ethers_1.ethers.constants.AddressZero]; ++ executors = [ethers_1.ethers.ZeroAddress]; + minDelay = 172800 // 2 days in seconds (2 * 24 * 60 * 60) + ; + return [4 /*yield*/, deployments.deploy("TokenholderTimelock", { diff --git a/solidity/random-beacon/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch b/solidity/random-beacon/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch new file mode 100644 index 0000000000..85cccd3381 --- /dev/null +++ b/solidity/random-beacon/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch @@ -0,0 +1,13 @@ +diff --git a/dist/codegen/reserved-keywords.js b/dist/codegen/reserved-keywords.js +index f5a47b105a31e5ae3a6e40da476a37f748d962d9..f05f5ec9582c56a264fe6a61f7a098e2008047a3 100644 +--- a/dist/codegen/reserved-keywords.js ++++ b/dist/codegen/reserved-keywords.js +@@ -1,7 +1,7 @@ + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.reservedKeywordsLabels = exports.reservedKeywords = void 0; +-exports.reservedKeywords = new Set(['signer', 'provider', 'deployTransaction', 'deployed', 'fallback', 'connect']); ++exports.reservedKeywords = new Set(['signer', 'provider', 'deployTransaction', 'deployed', 'fallback', 'connect', 'target']); + exports.reservedKeywordsLabels = new Set([ + 'class', + 'function', diff --git a/solidity/random-beacon/Dockerfile b/solidity/random-beacon/Dockerfile index 52b71b5962..d95aa8789a 100644 --- a/solidity/random-beacon/Dockerfile +++ b/solidity/random-beacon/Dockerfile @@ -16,7 +16,10 @@ ENV COREPACK_DEFAULT_TO_LATEST=0 # node: it writes Corepack's per-user cache under $HOME. `chown` targets only # $WORK_DIR here because `yarn install` creates node_modules inside it; # dependency/source ownership is set later via `COPY --chown`. -RUN corepack enable && mkdir -p $WORK_DIR && chown node:node $WORK_DIR +# Native dependencies need a compiler while Yarn packs Git dependencies; the +# build tools are installed/removed as root since `apk` requires root. +RUN apk add --no-cache --virtual .build-deps python3 make g++ && \ + corepack enable && mkdir -p $WORK_DIR && chown node:node $WORK_DIR WORKDIR $WORK_DIR USER node @@ -24,8 +27,13 @@ USER node RUN git config --global url."https://".insteadOf git:// COPY --chown=node:node package*.json yarn.lock .yarnrc.yml ./ +COPY --chown=node:node .yarn/patches/ ./.yarn/patches/ RUN corepack prepare yarn@4.12.0 --activate && yarn install --immutable +USER root +RUN apk del .build-deps +USER node + COPY --chown=node:node . ./ ENTRYPOINT ["npx", "hardhat"] diff --git a/solidity/random-beacon/README.adoc b/solidity/random-beacon/README.adoc index c013a86883..d4bd8b1251 100644 --- a/solidity/random-beacon/README.adoc +++ b/solidity/random-beacon/README.adoc @@ -486,7 +486,7 @@ presented below. Please make sure you have the following prerequisites installed on your machine: - https://nodejs.org[Node.js] >=24.0.0 -- https://yarnpkg.com[Yarn] >=1.22.17 +- https://yarnpkg.com[Yarn] >=4.12.0 (via Corepack) === Build contracts diff --git a/solidity/random-beacon/deploy/01_deploy_reimbursement_pool.ts b/solidity/random-beacon/deploy/01_deploy_reimbursement_pool.ts index 94a3d3f632..eb328e5a46 100644 --- a/solidity/random-beacon/deploy/01_deploy_reimbursement_pool.ts +++ b/solidity/random-beacon/deploy/01_deploy_reimbursement_pool.ts @@ -1,3 +1,5 @@ +import waitForConfirmations from "../utils/wait-for-confirmations" + import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction } from "hardhat-deploy/types" @@ -17,7 +19,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { if (hre.network.tags.etherscan) { if (ReimbursementPool.transactionHash) { - await hre.ethers.provider.waitForTransaction( + await waitForConfirmations( + hre.ethers.provider, ReimbursementPool.transactionHash, 2, 300000, diff --git a/solidity/random-beacon/deploy/02_deploy_beacon_sortition_pool.ts b/solidity/random-beacon/deploy/02_deploy_beacon_sortition_pool.ts index df1d226fc4..5417b40c0e 100644 --- a/solidity/random-beacon/deploy/02_deploy_beacon_sortition_pool.ts +++ b/solidity/random-beacon/deploy/02_deploy_beacon_sortition_pool.ts @@ -1,3 +1,5 @@ +import waitForConfirmations from "../utils/wait-for-confirmations" + import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction } from "hardhat-deploy/types" @@ -28,7 +30,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { if (hre.network.tags.etherscan) { if (BeaconSortitionPool.transactionHash) { - await hre.ethers.provider.waitForTransaction( + await waitForConfirmations( + hre.ethers.provider, BeaconSortitionPool.transactionHash, 2, 300000, diff --git a/solidity/random-beacon/deploy/03_deploy_beacon_dkg_validator.ts b/solidity/random-beacon/deploy/03_deploy_beacon_dkg_validator.ts index 4f02878abe..e4af9bcec3 100644 --- a/solidity/random-beacon/deploy/03_deploy_beacon_dkg_validator.ts +++ b/solidity/random-beacon/deploy/03_deploy_beacon_dkg_validator.ts @@ -1,3 +1,5 @@ +import waitForConfirmations from "../utils/wait-for-confirmations" + import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction } from "hardhat-deploy/types" @@ -16,7 +18,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { if (hre.network.tags.etherscan) { if (BeaconDkgValidator.transactionHash) { - await hre.ethers.provider.waitForTransaction( + await waitForConfirmations( + hre.ethers.provider, BeaconDkgValidator.transactionHash, 2, 300000, diff --git a/solidity/random-beacon/deploy/04_deploy_random_beacon.ts b/solidity/random-beacon/deploy/04_deploy_random_beacon.ts index 33a6ebf0bc..77ff2c7a58 100644 --- a/solidity/random-beacon/deploy/04_deploy_random_beacon.ts +++ b/solidity/random-beacon/deploy/04_deploy_random_beacon.ts @@ -1,3 +1,5 @@ +import waitForConfirmations from "../utils/wait-for-confirmations" + import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction, DeployOptions } from "hardhat-deploy/types" @@ -60,7 +62,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { if (hre.network.tags.etherscan) { if (RandomBeacon.transactionHash) { - await hre.ethers.provider.waitForTransaction( + await waitForConfirmations( + hre.ethers.provider, RandomBeacon.transactionHash, 2, 300000, diff --git a/solidity/random-beacon/deploy/05_approve_random_beacon_in_token_staking.ts b/solidity/random-beacon/deploy/05_approve_random_beacon_in_token_staking.ts index 90d912fa35..0095c21ad9 100644 --- a/solidity/random-beacon/deploy/05_approve_random_beacon_in_token_staking.ts +++ b/solidity/random-beacon/deploy/05_approve_random_beacon_in_token_staking.ts @@ -1,14 +1,13 @@ import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction } from "hardhat-deploy/types" -import type { utils } from "ethers" +import type { Interface } from "ethers" // ApplicationStatus enum: NOT_APPROVED=0, APPROVED=1, PAUSED=2, DISABLED=3 -const APPLICATION_STATUS_APPROVED = 1 +const APPLICATION_STATUS_APPROVED = 1n -function ifaceHasFunction(iface: utils.Interface, name: string): boolean { +function ifaceHasFunction(iface: Interface, name: string): boolean { try { - iface.getFunction(name) - return true + return iface.getFunction(name) !== null } catch { return false } @@ -22,7 +21,7 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const RandomBeacon = await deployments.get("RandomBeacon") const TokenStaking = await get("TokenStaking") - const iface = new ethers.utils.Interface(TokenStaking.abi) + const iface = new ethers.Interface(TokenStaking.abi) if (!ifaceHasFunction(iface, "approveApplication")) { hre.deployments.log( "TokenStaking does not have approveApplication (Threshold TokenStaking); skipping", diff --git a/solidity/random-beacon/deploy/07_deploy_random_beacon_governance.ts b/solidity/random-beacon/deploy/07_deploy_random_beacon_governance.ts index 266a31f731..b38064c867 100644 --- a/solidity/random-beacon/deploy/07_deploy_random_beacon_governance.ts +++ b/solidity/random-beacon/deploy/07_deploy_random_beacon_governance.ts @@ -1,3 +1,5 @@ +import waitForConfirmations from "../utils/wait-for-confirmations" + import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction } from "hardhat-deploy/types" @@ -21,7 +23,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { if (hre.network.tags.etherscan) { if (RandomBeaconGovernance.transactionHash) { - await hre.ethers.provider.waitForTransaction( + await waitForConfirmations( + hre.ethers.provider, RandomBeaconGovernance.transactionHash, 2, 300000, diff --git a/solidity/random-beacon/deploy/09_deploy_random_beacon_chaosnet.ts b/solidity/random-beacon/deploy/09_deploy_random_beacon_chaosnet.ts index 7b71a79f63..02009e92e7 100644 --- a/solidity/random-beacon/deploy/09_deploy_random_beacon_chaosnet.ts +++ b/solidity/random-beacon/deploy/09_deploy_random_beacon_chaosnet.ts @@ -1,3 +1,5 @@ +import waitForConfirmations from "../utils/wait-for-confirmations" + import type { HardhatRuntimeEnvironment } from "hardhat/types" import type { DeployFunction, DeployOptions } from "hardhat-deploy/types" @@ -20,7 +22,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { if (hre.network.tags.etherscan) { if (RandomBeaconChaosnet.transactionHash) { - await hre.ethers.provider.waitForTransaction( + await waitForConfirmations( + hre.ethers.provider, RandomBeaconChaosnet.transactionHash, 2, 300000, diff --git a/solidity/random-beacon/export-baseline.sha256 b/solidity/random-beacon/export-baseline.sha256 index db8ac93db3..9c8ac48b91 100644 --- a/solidity/random-beacon/export-baseline.sha256 +++ b/solidity/random-beacon/export-baseline.sha256 @@ -20,7 +20,7 @@ aaa8155fe24a23cd56e575a0b758861f44de93c1c18af3a45dc6df8df3e1577e export/artifac 3e59336a8232358551aa460637d30cac6aab7959c1c444dd3699e04f16736752 export/artifacts/@openzeppelin/contracts/utils/math/SafeCast.sol/SafeCast.json 088b73bcfab23644f2a20a4bbefa94a313ca0ff4a3d290f3539990b6fc91369a export/artifacts/@thesis/solidity-contracts/contracts/token/ERC20WithPermit.sol/ERC20WithPermit.json b0cd72a81ec2bec852ed9669f805214e4494ade6ad1737f9b13401aba5aa44c8 export/artifacts/@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol/MisfundRecovery.json -d8446e242ad6a784fc4369b432bbd9424e6bfb3d75312ffce528133c469db85e export/artifacts/@threshold-network/solidity-contracts/contracts/staking/TokenStaking.sol/TokenStaking.json +b09e63de02efc682ed9a0f71056bc79b5e338fb24df2cf48e082f7dbefb9bb3d export/artifacts/@threshold-network/solidity-contracts/contracts/staking/TokenStaking.sol/TokenStaking.json a8e61fa781f4c99024ba7ca6b40552b0a00d4aa22930963968b7c5d16dc90af3 export/artifacts/@threshold-network/solidity-contracts/contracts/token/T.sol/T.json 74a7677ccb441fcbdf1086f8b6ff4c946a262cf66175b4e8fd5b7de5c2156b50 export/artifacts/@threshold-network/solidity-contracts/contracts/utils/PercentUtils.sol/PercentUtils.json 920396ad3fd010c3e007c615a640e18fdd2a0eddb1be89ca5bfc76c7c2a41b2a export/artifacts/@threshold-network/solidity-contracts/contracts/utils/SafeTUpgradeable.sol/SafeTUpgradeable.json @@ -50,26 +50,27 @@ c49675131b9f9b6b1babef5cc43676ba40eff9b64b4c7478dabcda6d7c80307a export/artifac 63ead28705908a2cd2f4c8e68a192a32debefff8dcaaa08337526717993eb12b export/artifacts/contracts/test/RelayStub.sol/RelayStub.json d3d1237733fac01032798354423d49792b6aeeba7a36044279f8ce6e4d3c5616 export/artifacts/contracts/test/TestAltBn128.sol/TestAltBn128.json 4c4f182d3e4d125fe2498879bb68b49888d0ea4e2ee897b72b575fe8ca0343a1 export/artifacts/contracts/test/TestModUtils.sol/TestModUtils.json -d1ccbbf073406ddece9a03c83336fba3889c6c110c3c1576859cc9243808a5cb export/deploy/01_deploy_reimbursement_pool.js -828c74a03d03f12bc9c49dcc8e34ea8dcac59cb769d3869bed8c0701d2fcc0d7 export/deploy/02_deploy_beacon_sortition_pool.js -17bedd62fc018afe3af92e0fd88861b3fa08eab8bc16e7eafdd2e8aa42e75816 export/deploy/03_deploy_beacon_dkg_validator.js -99d4923ea0de5e618eb3a834e93079725e99615e5f498e73b9e75a76a3eee76e export/deploy/04_deploy_random_beacon.js -f63e4b7fa89ea26a15a6298f88ff3f6992d20af69f1bb1ed5651f0fc2e51f768 export/deploy/05_approve_random_beacon_in_token_staking.js +a8ca0d41130c14c7644e1dc71110fc07138f4341c2993aafd4aeee5cbdd39173 export/deploy/01_deploy_reimbursement_pool.js +abc3259ad23e6a59e15255c6048f71456c5dca6166c7b03e9b8efb4909a541e3 export/deploy/02_deploy_beacon_sortition_pool.js +72cbcb2a9a3b18b50f1e2d71ab35b89d452ddfa09b560a290449ad3f7473503c export/deploy/03_deploy_beacon_dkg_validator.js +f720c254e218bd2a2dc3dd36921c6cd460cab202a609c71665a7cb85fd4f5311 export/deploy/04_deploy_random_beacon.js +dc4beb5cabe48f3fb18a1465cc85a34a9d20a0049189d7cf5b665ba9f4c1bd78 export/deploy/05_approve_random_beacon_in_token_staking.js 470005455547dcb19ffe6e023202659a6ba41d2875c98469a7e11e9a216d9ac3 export/deploy/06_authorize_random_beacon_in_reimbursement_pool.js -88a572999bc43c0e16a1a39a8105133fd226f9a792d54a891408a7038e6528b7 export/deploy/07_deploy_random_beacon_governance.js +1668d54172cc24b9af6be627914a84923e0d9102d741d0b0c631e2b3e280c5ff export/deploy/07_deploy_random_beacon_governance.js 70206a22d3784195128c4138fcc661ea2fdde7f636935f18be46e67ebd605883 export/deploy/08_transfer_governance.js -709afb436e81e61e85101226de01c82ba8b88cc37ef425f06cd87280ab65caca export/deploy/09_deploy_random_beacon_chaosnet.js -266f475dc3a4305dc6f1f12922b337d4736768ad51f94c754192820171e80012 export/hardhat.config.js -938d9d674327dfc2484e15b72725905c8601330c7d74345fbb3cc6dd2920343e export/tasks/ensure-eth-balance.js -fb4b7d40feba86675f6c3fcd5e6701a85449ed1fa960b450ab80aefb711bcf79 export/tasks/genesis.js +af570a509d46452a69cbf6974ee527193f6975ccda181aa150621026d6107570 export/deploy/09_deploy_random_beacon_chaosnet.js +148c81cd0ba5a4fd2d84a7ea474ec20337644a813cb33909154e95e25cb515b6 export/hardhat.config.js +bbfa690e72cae56c992ed6755a1e505211fed8e675726bf792abafa74a1e3157 export/tasks/ensure-eth-balance.js +760337573ef1fcddc7e84a0685564fb19ba7bef2ddf133ff2a8067b7e2be68e8 export/tasks/genesis.js 02c4969955c262cf674f578430c360c9c659a9ed4a1da71e28831b93df17eb94 export/tasks/index.js -25998f68d97c863dab5636f8e64cc8a342caa7eace4d160f818c2d31f262d68f export/tasks/initialize.js +313df6ab058fb3fc561e8dd62476c8fdf5d4d12f037647fffd554f029548036e export/tasks/initialize.js d5391cfac7a359721f5fd7f247165607e1fc57bca7b9f80f18f63b0cb86fb582 export/tasks/send-eth.js -05ab5b3508f2e4afc086f26881adce3a1bbd628311237b328e2759d00e625996 export/tasks/unlock-eth-accounts.js -f7a138a01380e8547efa1d4b0638183ee0a1f9954dfef7a7abf73af76441a240 export/tasks/utils/add_beta_operator.js -eddca7e1d3466b441d4384f36ef28511ec299e352a129bdb65a39863684aac9f export/tasks/utils/authorize.js -8f2408a4b588979e5be386c53a7ad04d6a163fafffbe5028c6f22faa3b0f36a1 export/tasks/utils/ether.js +6c638999c74e89a3f0b6d260e7c77e8450c2426762059f79f41923f8fb5d4a3b export/tasks/unlock-eth-accounts.js +05f78656bda56e2f012198eadd00a8b5557aba5944465a9b5e4de4c62d052fd1 export/tasks/utils/add_beta_operator.js +1934377c80a43005e2144d4b2e4417e68ebcfa3ef614f1edef635b3877442828 export/tasks/utils/authorize.js +aeec915daa6d27c4b6615a766b121009d5416a5f4f385a4c571dd0f134ba5a5b export/tasks/utils/ether.js 1ca808e3ccad8dbdb882f7545892ae4e690f1d349501baadcbf087ea5c655078 export/tasks/utils/index.js -7a744cb9d28a54412f65fd32144851a5672b6dbe0c1a59c9f97514151832ca97 export/tasks/utils/mint.js -7db685b8bca9e4f65e418ecd0d1dfc0df56c0bdeb6c3cdc9bf76402472d56010 export/tasks/utils/register.js -dceec4b83941f7822fabda3ff0af4307901dc8a95a2e9b4aed45c4157a6adf3b export/tasks/utils/stake.js +8a1f59568550491baad027eca95ca39ab21afb3939dabc28b0f4a4dae6c08f5e export/tasks/utils/mint.js +d509094d66bb589e43fccf4df5caed7062de0aca8377ac319e1a2fce1a0eb4f6 export/tasks/utils/register.js +b89f0927e05341a48587ac54f7658a52b4c10febff6615730fe9df0f2e8c92c6 export/tasks/utils/stake.js +1e6cefa2d8eb6f09d61abf2744797bc88d241fb3e45fa955038281e1038c92fb export/utils/wait-for-confirmations.js diff --git a/solidity/random-beacon/hardhat.config.ts b/solidity/random-beacon/hardhat.config.ts index 2762e00c1e..db65c37170 100644 --- a/solidity/random-beacon/hardhat.config.ts +++ b/solidity/random-beacon/hardhat.config.ts @@ -1,9 +1,9 @@ import "@nomicfoundation/hardhat-verify" import "@keep-network/hardhat-local-networks-config" import "@keep-network/hardhat-helpers" -import "@nomiclabs/hardhat-ethers" +import "@nomicfoundation/hardhat-ethers" import "hardhat-deploy" -import "@tenderly/hardhat-tenderly" +import { setup as setupTenderly } from "@tenderly/hardhat-tenderly" import "@nomicfoundation/hardhat-chai-matchers" import "hardhat-gas-reporter" import "hardhat-contract-sizer" @@ -16,6 +16,8 @@ import { task } from "hardhat/config" import type { HardhatUserConfig } from "hardhat/config" +setupTenderly({ automaticVerifications: false }) + const thresholdSolidityCompilerConfig = { version: "0.8.9", settings: { diff --git a/solidity/random-beacon/package.json b/solidity/random-beacon/package.json index d155b5e2f7..ee90b1e1de 100644 --- a/solidity/random-beacon/package.json +++ b/solidity/random-beacon/package.json @@ -11,6 +11,7 @@ "deploy/", "export/", "tasks/", + "utils/", "export.json" ], "scripts": { @@ -32,7 +33,7 @@ "lint:config:fix": "prettier --write '**/*.@(json|yaml)'", "typecheck": "tsc --noEmit -p tsconfig.json", "prepack": "tsc -p tsconfig.export.json && hardhat export-artifacts --including-no-public-functions export/artifacts", - "prepublishOnly": "hardhat prepare-artifacts --network $npm_config_network" + "prepublishOnly": "hardhat export-deployment-artifacts --network \"${npm_config_network:-hardhat}\"" }, "dependencies": { "@keep-network/sortition-pools": "^2.0.0-pre.16", @@ -41,17 +42,17 @@ "@threshold-network/solidity-contracts": "1.3.0-dev.14" }, "devDependencies": { - "@keep-network/hardhat-helpers": "github:threshold-network/hardhat-helpers#v0.6.0-pre.21", + "@keep-network/hardhat-helpers": "patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch", "@keep-network/hardhat-local-networks-config": "github:threshold-network/hardhat-local-networks-config#6dff5bc8648127ca5d8696c321076bddb6d4142a", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", + "@nomicfoundation/hardhat-chai-matchers": "^2.1.2", + "@nomicfoundation/hardhat-ethers": "^3.1.3", "@nomicfoundation/hardhat-network-helpers": "^1.1.2", "@nomicfoundation/hardhat-verify": "^2.1.3", - "@nomiclabs/hardhat-ethers": "^2.0.6", - "@openzeppelin/hardhat-upgrades": "^1.20.0", + "@openzeppelin/hardhat-upgrades": "patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch", "@stylistic/eslint-plugin": "^5.10.0", - "@tenderly/hardhat-tenderly": "1.0.12", - "@typechain/ethers-v5": "^11.1.2", - "@typechain/hardhat": "^7.0.0", + "@tenderly/hardhat-tenderly": "2.1.1", + "@typechain/ethers-v6": "patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch", + "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.3.20", "@types/mocha": "^10.0.10", "@types/node": "^24.13.3", @@ -60,7 +61,7 @@ "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-import-x": "^4.17.1", "eslint-plugin-no-only-tests": "^3.4.0", - "ethers": "^5.4.7", + "ethers": "^6.17.0", "fs-extra": "^11.2.0", "globals": "^17.12.0", "hardhat": "2.29.0", @@ -81,8 +82,10 @@ "node": ">=24.0.0" }, "resolutions": { + "axios": "^1.8.4", "ethereumjs-abi": "npm:0.6.8", - "@ethersproject/abstract-provider": "5.8.0" + "@ethersproject/abstract-provider": "5.8.0", + "@threshold-network/solidity-contracts@npm:1.3.0-dev.14": "patch:@threshold-network/solidity-contracts@npm%3A1.3.0-dev.14#./.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch" }, "packageManager": "yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8" } diff --git a/solidity/random-beacon/tasks/ensure-eth-balance.ts b/solidity/random-beacon/tasks/ensure-eth-balance.ts index 0717858194..150a548664 100644 --- a/solidity/random-beacon/tasks/ensure-eth-balance.ts +++ b/solidity/random-beacon/tasks/ensure-eth-balance.ts @@ -47,13 +47,13 @@ task( const currentBalance = await ethers.provider.getBalance(address) console.log( - `current balance of ${address} is ${ethers.utils.formatEther( + `current balance of ${address} is ${ethers.formatEther( currentBalance, )} ether`, ) - if (currentBalance.lt(expectedBalance)) { - const topUpAmount = expectedBalance.sub(currentBalance) + if (currentBalance < expectedBalance) { + const topUpAmount = expectedBalance - currentBalance await hre.run(TASK_SEND_ETH, { from: args.from, diff --git a/solidity/random-beacon/tasks/genesis.ts b/solidity/random-beacon/tasks/genesis.ts index 92a839be48..7851eed46f 100644 --- a/solidity/random-beacon/tasks/genesis.ts +++ b/solidity/random-beacon/tasks/genesis.ts @@ -14,7 +14,9 @@ async function genesis(hre: HardhatRuntimeEnvironment) { const randomBeacon = await helpers.contracts.getContract("RandomBeacon") - const genesisTx = await randomBeacon.connect(governance).genesis() + const genesisTx = await randomBeacon + .connect(governance) + .getFunction("genesis")() await genesisTx.wait() console.log("Genesis was triggered successfully") diff --git a/solidity/random-beacon/tasks/initialize.ts b/solidity/random-beacon/tasks/initialize.ts index 763a028440..bc05368bac 100644 --- a/solidity/random-beacon/tasks/initialize.ts +++ b/solidity/random-beacon/tasks/initialize.ts @@ -1,3 +1,4 @@ +import { getNumber } from "ethers" import { task, types } from "hardhat/config" import { @@ -65,8 +66,8 @@ task(TASK_INITIALIZE_STAKING, "Initializes staking for a service provider") args.amount, ) - if (!tokensToMint.isZero()) { - await hre.run(TASK_MINT, { ...args, amount: tokensToMint.toNumber() }) + if (tokensToMint !== 0n) { + await hre.run(TASK_MINT, { ...args, amount: getNumber(tokensToMint) }) } await hre.run(TASK_STAKE, args) diff --git a/solidity/random-beacon/tasks/send-eth.ts b/solidity/random-beacon/tasks/send-eth.ts index 039d7a10a7..844eb055fb 100644 --- a/solidity/random-beacon/tasks/send-eth.ts +++ b/solidity/random-beacon/tasks/send-eth.ts @@ -2,9 +2,8 @@ import { task, types } from "hardhat/config" import { parseValue } from "./utils" -import type { BigNumber } from "ethers" -import type { TransactionResponse } from "@ethersproject/abstract-provider" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { TransactionResponse } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" // eslint-disable-next-line import/prefer-default-export export const TASK_SEND_ETH = "send-eth" @@ -28,7 +27,7 @@ task(TASK_SEND_ETH, "Send ether to an address") ? await hre.ethers.getSigner(args.from) : (await hre.ethers.getSigners())[0] - const amount: BigNumber = parseValue(args.amount, hre) + const amount: bigint = parseValue(args.amount, hre) // FIXME: `validate` will fail for badly checksummed addresses // see: https://github.com/ethers-io/ethers.js/discussions/3261 diff --git a/solidity/random-beacon/tasks/unlock-eth-accounts.ts b/solidity/random-beacon/tasks/unlock-eth-accounts.ts index 03ef3fa490..53c8eb341f 100644 --- a/solidity/random-beacon/tasks/unlock-eth-accounts.ts +++ b/solidity/random-beacon/tasks/unlock-eth-accounts.ts @@ -9,7 +9,7 @@ task("unlock-accounts", "Unlock ethereum accounts").setAction( if (hre.network.name === "development") { const password = process.env.KEEP_ETHEREUM_PASSWORD || "password" - const provider = new ethers.providers.JsonRpcProvider( + const provider = new ethers.JsonRpcProvider( (hre.network.config as HttpNetworkConfig).url, ) const accounts = await provider.listAccounts() @@ -18,7 +18,7 @@ task("unlock-accounts", "Unlock ethereum accounts").setAction( console.log("---------------------------------") for (let i = 0; i < accounts.length; i++) { - const account = accounts[i] + const account = await accounts[i].getAddress() try { console.log(`\nUnlocking account: ${account}`) diff --git a/solidity/random-beacon/tasks/utils/add_beta_operator.ts b/solidity/random-beacon/tasks/utils/add_beta_operator.ts index 5caddf3cdb..bc5ae752ed 100644 --- a/solidity/random-beacon/tasks/utils/add_beta_operator.ts +++ b/solidity/random-beacon/tasks/utils/add_beta_operator.ts @@ -13,10 +13,15 @@ export async function addBetaOperator( ) const chaosnetOwner = await sortitionPool.chaosnetOwner() + if (await sortitionPool.isBetaOperator(operator)) { + console.log(`Operator ${operator} is already a beta operator`) + return + } + console.log(`Adding ${operator} to the set of beta operators...`) await ( await sortitionPool .connect(await ethers.getSigner(chaosnetOwner)) - .addBetaOperators([operator]) + .getFunction("addBetaOperators")([operator]) ).wait() } diff --git a/solidity/random-beacon/tasks/utils/authorize.ts b/solidity/random-beacon/tasks/utils/authorize.ts index db350810ee..f11a93517d 100644 --- a/solidity/random-beacon/tasks/utils/authorize.ts +++ b/solidity/random-beacon/tasks/utils/authorize.ts @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -import type { BigNumber, BigNumberish } from "ethers" +import type { BigNumberish } from "ethers" import type { HardhatRuntimeEnvironment } from "hardhat/types" // eslint-disable-next-line import/prefer-default-export @@ -12,41 +12,41 @@ export async function authorize( authorization?: BigNumberish, ): Promise { const { ethers, helpers } = hre - const ownerAddress = ethers.utils.getAddress(owner) - const providerAddress = ethers.utils.getAddress(provider) + const ownerAddress = ethers.getAddress(owner) + const providerAddress = ethers.getAddress(provider) const application = await helpers.contracts.getContract(deploymentName) console.log( - `Authorizing provider's ${providerAddress} stake in ${deploymentName} application (${application.address})`, + `Authorizing provider's ${providerAddress} stake in ${deploymentName} application (${await application.getAddress()})`, ) // Authorizer can equal to the owner if not set otherwise. This simplification // is used for development purposes. const authorizerAddress = authorizer - ? ethers.utils.getAddress(authorizer) + ? ethers.getAddress(authorizer) : ownerAddress const { to1e18, from1e18 } = helpers.number const staking = await helpers.contracts.getContract("TokenStaking") - const authorizationBN: BigNumber = authorization + const authorizationBN: bigint = authorization ? to1e18(authorization) : await application.minimumAuthorization() - const currentAuthorization = await staking.authorizedStake( + const currentAuthorization: bigint = await staking.authorizedStake( providerAddress, - application.address, + await application.getAddress(), ) - if (currentAuthorization.gte(authorizationBN)) { + if (currentAuthorization >= authorizationBN) { console.log( `Authorized stake is already ${from1e18(currentAuthorization)} T`, ) return } - const increaseAmount: BigNumber = authorizationBN.sub(currentAuthorization) + const increaseAmount: bigint = authorizationBN - currentAuthorization console.log( `Increasing authorization by ${from1e18(increaseAmount)} T to ${from1e18( @@ -57,10 +57,10 @@ export async function authorize( await ( await staking .connect(await ethers.getSigner(authorizerAddress)) - .increaseAuthorization( - providerAddress, - application.address, - increaseAmount, - ) + .getFunction("increaseAuthorization")( + providerAddress, + await application.getAddress(), + increaseAmount, + ) ).wait() } diff --git a/solidity/random-beacon/tasks/utils/ether.ts b/solidity/random-beacon/tasks/utils/ether.ts index aaca89a89c..a63ed7decf 100644 --- a/solidity/random-beacon/tasks/utils/ether.ts +++ b/solidity/random-beacon/tasks/utils/ether.ts @@ -1,16 +1,15 @@ -import type { BigNumber } from "ethers" import type { HardhatRuntimeEnvironment } from "hardhat/types" // eslint-disable-next-line import/prefer-default-export export function parseValue( value: string, hre: HardhatRuntimeEnvironment, -): BigNumber { +): bigint { const parsed = String(value).trim().split(" ") if (parsed.length === 0 || parsed.length > 2) { throw new Error(`invalid value: ${value}`) } - return hre.ethers.utils.parseUnits(parsed[0], parsed[1] || "wei") + return hre.ethers.parseUnits(parsed[0], parsed[1] || "wei") } diff --git a/solidity/random-beacon/tasks/utils/mint.ts b/solidity/random-beacon/tasks/utils/mint.ts index d82ba28024..01f9d844b4 100644 --- a/solidity/random-beacon/tasks/utils/mint.ts +++ b/solidity/random-beacon/tasks/utils/mint.ts @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -import type { BigNumberish, BigNumber } from "ethers" +import type { BigNumberish } from "ethers" import type { HardhatRuntimeEnvironment } from "hardhat/types" // eslint-disable-next-line import/prefer-default-export @@ -10,7 +10,7 @@ export async function mint( ): Promise { const { ethers, helpers } = hre const { to1e18, from1e18 } = helpers.number - const ownerAddress = ethers.utils.getAddress(owner) + const ownerAddress = ethers.getAddress(owner) const stakeAmount = to1e18(amount) const t = await helpers.contracts.getContract("T") @@ -18,43 +18,43 @@ export async function mint( const tokenContractOwner = await t.owner() - const currentBalance: BigNumber = await t.balanceOf(ownerAddress) + const currentBalance: bigint = await t.balanceOf(ownerAddress) console.log( `Account ${ownerAddress} balance is ${from1e18(currentBalance)} T`, ) - if (currentBalance.lt(stakeAmount)) { - const mintAmount = stakeAmount.sub(currentBalance) + if (currentBalance < stakeAmount) { + const mintAmount = stakeAmount - currentBalance console.log(`Minting ${from1e18(mintAmount)} T for ${ownerAddress}...`) await ( await t .connect(await ethers.getSigner(tokenContractOwner)) - .mint(ownerAddress, mintAmount) + .getFunction("mint")(ownerAddress, mintAmount) ).wait() } - const currentAllowance: BigNumber = await t.allowance( + const currentAllowance: bigint = await t.allowance( ownerAddress, - staking.address, + await staking.getAddress(), ) console.log( - `Account ${ownerAddress} allowance for ${staking.address} is ${from1e18( + `Account ${ownerAddress} allowance for ${await staking.getAddress()} is ${from1e18( currentAllowance, )} T`, ) - if (currentAllowance.lt(stakeAmount)) { + if (currentAllowance < stakeAmount) { console.log( - `Approving ${from1e18(stakeAmount)} T for ${staking.address}...`, + `Approving ${from1e18(stakeAmount)} T for ${await staking.getAddress()}...`, ) await ( await t .connect(await ethers.getSigner(ownerAddress)) - .approve(staking.address, stakeAmount) + .getFunction("approve")(await staking.getAddress(), stakeAmount) ).wait() } } diff --git a/solidity/random-beacon/tasks/utils/register.ts b/solidity/random-beacon/tasks/utils/register.ts index 3a3b2210a9..4207930481 100644 --- a/solidity/random-beacon/tasks/utils/register.ts +++ b/solidity/random-beacon/tasks/utils/register.ts @@ -10,17 +10,17 @@ export async function register( ): Promise { const { ethers, helpers } = hre - const providerAddress = ethers.utils.getAddress(provider) - const operatorAddress = ethers.utils.getAddress(operator) + const providerAddress = ethers.getAddress(provider) + const operatorAddress = ethers.getAddress(operator) const application = await helpers.contracts.getContract(deploymentName) console.log( - `Registering operator ${operatorAddress} in ${deploymentName} application (${application.address})`, + `Registering operator ${operatorAddress} in ${deploymentName} application (${await application.getAddress()})`, ) - const currentProvider = ethers.utils.getAddress( - await application.callStatic.operatorToStakingProvider(operatorAddress), + const currentProvider = ethers.getAddress( + await application.operatorToStakingProvider.staticCall(operatorAddress), ) switch (currentProvider) { @@ -30,7 +30,7 @@ export async function register( ) return } - case ethers.constants.AddressZero: { + case ethers.ZeroAddress: { console.log( `Registering operator ${operatorAddress} for a staking provider ${providerAddress}...`, ) @@ -38,7 +38,7 @@ export async function register( await ( await application .connect(await ethers.getSigner(providerAddress)) - .registerOperator(operatorAddress) + .getFunction("registerOperator")(operatorAddress) ).wait() break diff --git a/solidity/random-beacon/tasks/utils/stake.ts b/solidity/random-beacon/tasks/utils/stake.ts index cf130c1d70..3c1e772921 100644 --- a/solidity/random-beacon/tasks/utils/stake.ts +++ b/solidity/random-beacon/tasks/utils/stake.ts @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -import type { BigNumberish, BigNumber } from "ethers" +import type { BigNumberish } from "ethers" import type { HardhatRuntimeEnvironment } from "hardhat/types" export async function stake( @@ -12,32 +12,32 @@ export async function stake( ): Promise { const { ethers, helpers } = hre const { to1e18, from1e18 } = helpers.number - const ownerAddress = ethers.utils.getAddress(owner) - const providerAddress = ethers.utils.getAddress(provider) + const ownerAddress = ethers.getAddress(owner) + const providerAddress = ethers.getAddress(provider) const stakeAmount = to1e18(amount) // Beneficiary can equal to the owner if not set otherwise. This simplification // is used for development purposes. const beneficiaryAddress = beneficiary - ? ethers.utils.getAddress(beneficiary) + ? ethers.getAddress(beneficiary) : ownerAddress // Authorizer can equal to the owner if not set otherwise. This simplification // is used for development purposes. const authorizerAddress = authorizer - ? ethers.utils.getAddress(authorizer) + ? ethers.getAddress(authorizer) : ownerAddress const staking = await helpers.contracts.getContract("TokenStaking") - const { tStake: currentStake } = - await staking.callStatic.stakes(providerAddress) + const { tStake: currentStake }: { tStake: bigint } = + await staking.stakes.staticCall(providerAddress) console.log( `Current stake for ${providerAddress} is ${from1e18(currentStake)} T`, ) - if (currentStake.eq(0)) { + if (currentStake === 0n) { console.log( `Staking ${from1e18( stakeAmount, @@ -47,15 +47,15 @@ export async function stake( await ( await staking .connect(await ethers.getSigner(ownerAddress)) - .stake( - providerAddress, - beneficiaryAddress, - authorizerAddress, - stakeAmount, - ) + .getFunction("stake")( + providerAddress, + beneficiaryAddress, + authorizerAddress, + stakeAmount, + ) ).wait() - } else if (currentStake.lt(stakeAmount)) { - const topUpAmount = stakeAmount.sub(currentStake) + } else if (currentStake < stakeAmount) { + const topUpAmount = stakeAmount - currentStake console.log( `Topping up ${from1e18( @@ -66,7 +66,7 @@ export async function stake( await ( await staking .connect(await ethers.getSigner(ownerAddress)) - .topUp(providerAddress, topUpAmount) + .getFunction("topUp")(providerAddress, topUpAmount) ).wait() } } @@ -75,7 +75,7 @@ export async function calculateTokensNeededForStake( hre: HardhatRuntimeEnvironment, provider: string, amount: BigNumberish, -): Promise { +): Promise { const { ethers, helpers } = hre const { to1e18, from1e18 } = helpers.number @@ -83,11 +83,12 @@ export async function calculateTokensNeededForStake( const staking = await helpers.contracts.getContract("TokenStaking") - const { tStake: currentStake } = await staking.callStatic.stakes(provider) + const { tStake: currentStake }: { tStake: bigint } = + await staking.stakes.staticCall(provider) - if (currentStake.lt(stakeAmount)) { - return ethers.BigNumber.from(from1e18(stakeAmount.sub(currentStake))) + if (currentStake < stakeAmount) { + return BigInt(from1e18(stakeAmount - currentStake)) } - return ethers.constants.Zero + return 0n } diff --git a/solidity/random-beacon/test/AltBn128.test.ts b/solidity/random-beacon/test/AltBn128.test.ts index a95be3ca01..082a2d8883 100644 --- a/solidity/random-beacon/test/AltBn128.test.ts +++ b/solidity/random-beacon/test/AltBn128.test.ts @@ -17,7 +17,7 @@ describe("AltBn128", () => { const fixture = async () => { const TestAltBn128 = await ethers.getContractFactory("TestAltBn128") testAltBn128 = await TestAltBn128.deploy() - await testAltBn128.deployed() + await testAltBn128.waitForDeployment() return testAltBn128 } diff --git a/solidity/random-beacon/test/BLS.test.ts b/solidity/random-beacon/test/BLS.test.ts index 9867b7b4d0..c5860a3866 100644 --- a/solidity/random-beacon/test/BLS.test.ts +++ b/solidity/random-beacon/test/BLS.test.ts @@ -37,13 +37,13 @@ describe("BLS", () => { it("should use reasonable amount of gas", async () => { // Corresponding test in Go library: bls_test.go TestThresholdBLS - const gasEstimate = await bls.estimateGas.verify( + const gasEstimate = await bls.verify.estimateGas( "0x1644bcbb604e3608225d1826bab0b926f2df4fb506e1aa3641d5ab350ebceb5825c7df94f3a87e9dd6e11865dfdbdd3db69eab4951c8bc2250fb51da5f813009131e0c9e6d90d91741458b522b57ca99b597dd922dd31f61a2f69412ce3220d31a1ec4b09ef2ea1d6ba7cad98386f6049b5eec5fb3a40408229dc75c5759f184", "0x15c30f4b6cf6dbbcbdcc10fe22f54c8170aea44e198139b776d512d8f027319a1b9e8bfaf1383978231ce98e42bafc8129f473fc993cf60ce327f7d223460663", "0x23cbfa4b2fcbf43a44d8a4b2a9aa1a9123f183794fa7b53c633c2de7ada5b5ca174f81900dc4ca5672768d51c12dfcb0eac2aafba0a66ac54b76f689dc1fe321", ) // make sure no change will make the verification more expensive than it is now - await expect(gasEstimate.toNumber()).to.be.lessThan( + await expect(Number(gasEstimate)).to.be.lessThan( 306682, "BLS verification is too expensive", ) diff --git a/solidity/random-beacon/test/BeaconDkgValidator.test.ts b/solidity/random-beacon/test/BeaconDkgValidator.test.ts index 7044fafa94..444c5ef089 100644 --- a/solidity/random-beacon/test/BeaconDkgValidator.test.ts +++ b/solidity/random-beacon/test/BeaconDkgValidator.test.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-expressions */ -import { BigNumber } from "ethers" import { ethers, helpers, getUnnamedAccounts, deployments } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" @@ -33,7 +32,7 @@ const fixture = async () => { const SortitionPool = await ethers.getContractFactory("SortitionPool") const sortitionPool = (await SortitionPool.deploy( - t.address, + await t.getAddress(), constants.poolWeightDivisor, )) as SortitionPool @@ -41,9 +40,9 @@ const fixture = async () => { const DKGValidator = await ethers.getContractFactory("BeaconDkgValidator") const dkgValidator = (await DKGValidator.deploy( - sortitionPool.address, + await sortitionPool.getAddress(), )) as DKGValidator - await dkgValidator.deployed() + await dkgValidator.waitForDeployment() return { sortitionPool, @@ -52,11 +51,11 @@ const fixture = async () => { } describe("BeaconDkgValidator", () => { - const dkgSeed: BigNumber = BigNumber.from( + const dkgSeed = BigInt( "31415926535897932384626433832795028841971693993751058209749445923078164062862", ) const dkgStartBlock = 1337 - const groupPublicKey: string = ethers.utils.hexValue(blsData.groupPubKey) + const groupPublicKey: string = ethers.toQuantity(blsData.groupPubKey) let selectedOperators: Operator[] @@ -693,8 +692,8 @@ describe("BeaconDkgValidator", () => { context("when signatures contain wrong result hash", () => { const signWithWrongResultHash = async (signingOperators: Operator[]) => { - const wrongResultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const wrongResultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( ["uint256", "bytes", "uint8[]", "uint256"], [ hardhatNetworkId, @@ -708,11 +707,11 @@ describe("BeaconDkgValidator", () => { for (let i = 0; i < signingOperators.length; i++) { const { signer: ethersSigner } = signingOperators[i] const signature = await ethersSigner.signMessage( - ethers.utils.arrayify(wrongResultHash), + ethers.getBytes(wrongResultHash), ) signatures.push(signature) } - const signaturesBytes = ethers.utils.hexConcat(signatures) + const signaturesBytes = ethers.concat(signatures) return signaturesBytes } diff --git a/solidity/random-beacon/test/Governable.test.ts b/solidity/random-beacon/test/Governable.test.ts index ac29fae847..6a829f5eda 100644 --- a/solidity/random-beacon/test/Governable.test.ts +++ b/solidity/random-beacon/test/Governable.test.ts @@ -2,8 +2,8 @@ import { expect } from "chai" import { ethers, helpers } from "hardhat" -import type { ContractTransaction } from "ethers" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { ContractTransactionResponse } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { GovernableImpl, GovernableImpl__factory } from "../typechain" const { createSnapshot, restoreSnapshot } = helpers.snapshot @@ -25,9 +25,7 @@ describe("Governable", () => { describe("constructor", () => { it("should set governance to default zero address", async () => { - expect(await governable.governance()).to.be.equal( - ethers.constants.AddressZero, - ) + expect(await governable.governance()).to.be.equal(ethers.ZeroAddress) }) }) @@ -81,7 +79,7 @@ describe("Governable", () => { describe("when called by the governance", () => { const newGovernance: string = ethers.Wallet.createRandom().address - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -121,7 +119,7 @@ describe("Governable", () => { await expect( governable .connect(governance) - .transferGovernance(ethers.constants.AddressZero), + .transferGovernance(ethers.ZeroAddress), ).to.be.revertedWith("New governance is the zero address") }) }) @@ -147,9 +145,9 @@ describe("Governable", () => { it("should not be exposed directly", async () => { expect( - governable.functions, + governable.interface.hasFunction("_transferGovernance"), "_transferGovernance function is exposed on the contract", - ).to.not.haveOwnProperty("_transferGovernance") + ).to.equal(false) }) }) }) diff --git a/solidity/random-beacon/test/Groups.Expiration.test.ts b/solidity/random-beacon/test/Groups.Expiration.test.ts index b6fb34e842..cecd295753 100644 --- a/solidity/random-beacon/test/Groups.Expiration.test.ts +++ b/solidity/random-beacon/test/Groups.Expiration.test.ts @@ -2,6 +2,7 @@ import { ethers, helpers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" +import requireResult from "./helpers/chain" import { noMisbehaved, hashDKGMembers } from "./utils/dkg" import type { BigNumberish } from "ethers" @@ -139,7 +140,9 @@ describe("Groups", () => { it("should revert group selection", async () => { await addGroups(1, 5) - const currentBlock = await ethers.provider.getBlock("latest") + const currentBlock = requireResult( + await ethers.provider.getBlock("latest"), + ) await mineBlocksTo(currentBlock.number + groupLifetime) await expect(groups.selectGroup(0)).to.be.revertedWith( @@ -149,15 +152,17 @@ describe("Groups", () => { it("should allow to add and select new group", async () => { await addGroups(1, 5) - const currentBlock = await ethers.provider.getBlock("latest") + const currentBlock = requireResult( + await ethers.provider.getBlock("latest"), + ) await mineBlocksTo(currentBlock.number + groupLifetime) await groups.addGroup( - ethers.utils.hexlify(6), + ethers.toBeHex(6), hashDKGMembers(members, noMisbehaved), ) - const selected = await groups.callStatic.selectGroup(0) + const selected = await groups.selectGroup.staticCall(0) await groups.selectGroup(0) const numberOfGroups = await groups.numberOfActiveGroups() @@ -181,7 +186,9 @@ describe("Groups", () => { await addTerminatedGroups(3, 2) // terminating [0x4, 0x5] // move blocks so terminated blocks qualify for expiration - const currentBlock = await ethers.provider.getBlock("latest") + const currentBlock = requireResult( + await ethers.provider.getBlock("latest"), + ) await mineBlocksTo(currentBlock.number + groupLifetime) // [0x1, 0x2, 0x3, 0x4, 0x5] @@ -189,7 +196,7 @@ describe("Groups", () => { await addGroups(6, 5) // First active index group that qualifies for selection - const selectedGroupId = await groups.callStatic.selectGroup(5) + const selectedGroupId = await groups.selectGroup.staticCall(5) expect(selectedGroupId).to.be.equal(5) }) @@ -203,7 +210,7 @@ describe("Groups", () => { await addGroups(4, 7) // [0x4,0x5,0x6,0x7,0x8,0x9,0xa] // First active index group that qualifies for selection - const selectedGroupId = await groups.callStatic.selectGroup(1) + const selectedGroupId = await groups.selectGroup.staticCall(1) // 1 expired + 2 terminated + selected index (1) expect(selectedGroupId).to.be.equal(4) }) @@ -213,7 +220,9 @@ describe("Groups", () => { await groups.terminateGroup(1) // [0x2] // move blocks so terminated blocks qualify for expiration - const currentBlock = await ethers.provider.getBlock("latest") + const currentBlock = requireResult( + await ethers.provider.getBlock("latest"), + ) await mineBlocksTo(currentBlock.number + groupLifetime) let activeTerminatedGroups = await groups.activeTerminatedGroups() @@ -239,7 +248,7 @@ describe("Groups", () => { expect(numberOfGroups).to.be.equal(5) // Second active index group that qualifies for selection - const selectedIndex = await groups.callStatic.selectGroup(2) + const selectedIndex = await groups.selectGroup.staticCall(2) // expired ids: [0, 1, 2] // terminated ids: [4, 6] @@ -269,7 +278,9 @@ describe("Groups", () => { await groups.terminateGroup(30) // move blocks so terminated blocks qualify for expiration - const currentBlock = await ethers.provider.getBlock("latest") + const currentBlock = requireResult( + await ethers.provider.getBlock("latest"), + ) await mineBlocksTo(currentBlock.number + groupLifetime) await groups.expireOldGroups() @@ -291,7 +302,7 @@ describe("Groups", () => { async function addGroups(firstGroup: number, numberOfGroups: number) { for (let i = firstGroup; i < firstGroup + numberOfGroups; i++) { await groups.addGroup( - ethers.utils.hexlify(i), + ethers.toBeHex(i), hashDKGMembers(members, noMisbehaved), ) } @@ -300,12 +311,12 @@ describe("Groups", () => { async function expireGroup(groupId: BigNumberish) { const group = await groups.getGroupById(groupId) const registrationBlock = group.registrationBlockNumber - const currentBlock = await ethers.provider.getBlock("latest") + const currentBlock = requireResult(await ethers.provider.getBlock("latest")) - if (currentBlock.number - registrationBlock.toNumber() <= groupLifetime) { + if (currentBlock.number - Number(registrationBlock) <= groupLifetime) { const minedBlocksToExpireGroup = currentBlock.number + - (groupLifetime - (currentBlock.number - registrationBlock.toNumber())) + + (groupLifetime - (currentBlock.number - Number(registrationBlock))) + 1 await mineBlocksTo(minedBlocksToExpireGroup) } @@ -335,6 +346,6 @@ describe("Groups", () => { // count since we index from 0. await expireGroup(expiredCount - 1) } - return groups.callStatic.selectGroup(beaconValue) + return groups.selectGroup.staticCall(beaconValue) } }) diff --git a/solidity/random-beacon/test/Groups.Termination.test.ts b/solidity/random-beacon/test/Groups.Termination.test.ts index c3b5de27fc..cfe60db9c0 100644 --- a/solidity/random-beacon/test/Groups.Termination.test.ts +++ b/solidity/random-beacon/test/Groups.Termination.test.ts @@ -2,6 +2,7 @@ import { ethers, helpers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" +import requireResult from "./helpers/chain" import { noMisbehaved, hashDKGMembers } from "./utils/dkg" import type { BigNumberish } from "ethers" @@ -243,7 +244,7 @@ describe("Groups", () => { async function addGroups(start: number, numberOfGroups: number) { for (let i = start; i <= numberOfGroups; i++) { await groups.addGroup( - ethers.utils.hexlify(i), + ethers.toBeHex(i), hashDKGMembers(members, noMisbehaved), ) } @@ -257,7 +258,9 @@ describe("Groups", () => { ) { await addGroups(1, expiredCount) - const currentBlock = await ethers.provider.getBlock("latest") + const currentBlock = requireResult( + await ethers.provider.getBlock("latest"), + ) await mineBlocksTo(currentBlock.number + groupLifetime) await addGroups(expiredCount + 1, groupsCount) @@ -266,7 +269,7 @@ describe("Groups", () => { await groups.terminateGroup(terminatedGroups[i]) } - return groups.callStatic.selectGroup(beaconValue) + return groups.selectGroup.staticCall(beaconValue) } }) }) diff --git a/solidity/random-beacon/test/Groups.test.ts b/solidity/random-beacon/test/Groups.test.ts index efa60bc603..6eca3444f4 100644 --- a/solidity/random-beacon/test/Groups.test.ts +++ b/solidity/random-beacon/test/Groups.test.ts @@ -2,16 +2,17 @@ import { ethers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" +import requireResult from "./helpers/chain" import blsData from "./data/bls" import { constants } from "./fixtures" import { noMisbehaved, hashDKGMembers } from "./utils/dkg" import { hashUint32Array } from "./utils/groups" import type { GroupsStub } from "../typechain" -import type { ContractTransaction } from "ethers" +import type { ContractTransactionResponse } from "ethers" import type { Groups } from "../typechain/contracts/test/GroupsStub" -const { keccak256 } = ethers.utils +const { keccak256 } = ethers const fixture = async () => { const GroupsStub = await ethers.getContractFactory("GroupsStub") @@ -21,7 +22,7 @@ const fixture = async () => { } describe("Groups", () => { - const groupPublicKey: string = ethers.utils.hexValue(blsData.groupPubKey) + const groupPublicKey: string = ethers.toQuantity(blsData.groupPubKey) const members: number[] = [] let groups: GroupsStub @@ -55,7 +56,7 @@ describe("Groups", () => { describe("addGroup", async () => { context("when no groups are registered", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse context("with no misbehaved members", async () => { beforeEach(async () => { @@ -83,7 +84,7 @@ describe("Groups", () => { expect(storedGroup.groupPubKey).to.be.equal(groupPublicKey) expect(storedGroup.registrationBlockNumber).to.be.equal( - (await tx.wait()).blockNumber, + requireResult(await tx.wait()).blockNumber, ) expect(storedGroup.membersHash).to.be.equal(hashUint32Array(members)) }) @@ -189,7 +190,7 @@ describe("Groups", () => { context("with unique group public key", async () => { const newGroupPublicKey = groupPublicKey - let tx: ContractTransaction + let tx: ContractTransactionResponse beforeEach(async () => { tx = await groups.addGroup( @@ -216,7 +217,7 @@ describe("Groups", () => { expect(storedGroup.groupPubKey).to.be.equal(newGroupPublicKey) expect(storedGroup.registrationBlockNumber).to.be.equal( - (await tx.wait()).blockNumber, + requireResult(await tx.wait()).blockNumber, ) expect(storedGroup.membersHash).to.be.equal( hashUint32Array(newGroupMembers), diff --git a/solidity/random-beacon/test/ModUtils.test.ts b/solidity/random-beacon/test/ModUtils.test.ts index 0a1c2dd8a9..7b2c5df855 100644 --- a/solidity/random-beacon/test/ModUtils.test.ts +++ b/solidity/random-beacon/test/ModUtils.test.ts @@ -9,7 +9,7 @@ describe("ModUtils", () => { const fixture = async () => { const TestModUtils = await ethers.getContractFactory("TestModUtils") testModUtils = await TestModUtils.deploy() - await testModUtils.deployed() + await testModUtils.waitForDeployment() return testModUtils } diff --git a/solidity/random-beacon/test/RandomBeacon.Authorization.test.ts b/solidity/random-beacon/test/RandomBeacon.Authorization.test.ts index 871163ebc3..6130f02842 100644 --- a/solidity/random-beacon/test/RandomBeacon.Authorization.test.ts +++ b/solidity/random-beacon/test/RandomBeacon.Authorization.test.ts @@ -7,8 +7,8 @@ import { constants, params, randomBeaconDeployment } from "./fixtures" import { legacyTokenStakingAt } from "./utils/operators" import type { Mock } from "./helpers/mock" -import type { BigNumber, BigNumberish, ContractTransaction } from "ethers" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { BigNumberish, ContractTransactionResponse } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { RandomBeacon, SortitionPool, @@ -23,8 +23,8 @@ const { mineBlocks } = helpers.time const { createSnapshot, restoreSnapshot } = helpers.snapshot -const ZERO_ADDRESS = ethers.constants.AddressZero -const MAX_UINT64 = ethers.BigNumber.from("18446744073709551615") // 2^64 - 1 +const ZERO_ADDRESS = ethers.ZeroAddress +const MAX_UINT64 = BigInt("18446744073709551615") // 2^64 - 1 describe("RandomBeacon - Authorization", () => { let t: T @@ -45,7 +45,7 @@ describe("RandomBeacon - Authorization", () => { let slasher: Mock const stakedAmount = to1e18(1_000_000) // 1MM T - let minimumAuthorization: BigNumber + let minimumAuthorization: bigint before("load test fixture", async () => { const contracts = await randomBeaconDeployment() @@ -61,7 +61,7 @@ describe("RandomBeacon - Authorization", () => { await helpers.signers.getUnnamedSigners() await t.connect(deployer).mint(owner.address, stakedAmount) - await t.connect(owner).approve(staking.address, stakedAmount) + await t.connect(owner).approve(await staking.getAddress(), stakedAmount) await legacyTokenStakingAt(staking, owner).stake( stakingProvider.address, beneficiary.address, @@ -88,7 +88,7 @@ describe("RandomBeacon - Authorization", () => { await ethers.getSigners() )[0].sendTransaction({ to: slasher.address, - value: ethers.utils.parseEther("100"), + value: ethers.parseEther("100"), }) }) @@ -164,7 +164,7 @@ describe("RandomBeacon - Authorization", () => { // the staking provider, and the staking provider is registering operator // for ECDSA application. context("when staking provider is registering new operator", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -217,7 +217,7 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) @@ -225,7 +225,11 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) }) after(async () => { @@ -249,14 +253,14 @@ describe("RandomBeacon - Authorization", () => { // approving that authorization decrease request, staking provider can // register an operator. context("when authorization decrease request was approved", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) @@ -264,7 +268,11 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) await randomBeacon.approveAuthorizationDecrease(stakingProvider.address) @@ -313,8 +321,8 @@ describe("RandomBeacon - Authorization", () => { await expect( legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, - minimumAuthorization.sub(1), + await randomBeacon.getAddress(), + minimumAuthorization - 1n, ), ).to.be.revertedWith("Authorization below the minimum") }) @@ -329,7 +337,7 @@ describe("RandomBeacon - Authorization", () => { // Minimum possible authorization - the minimum authorized amount for // ECDSA as set in `minimumAuthorization` parameter. context("when increasing to the minimum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -338,7 +346,7 @@ describe("RandomBeacon - Authorization", () => { authorizer, ).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), minimumAuthorization, ) }) @@ -362,7 +370,7 @@ describe("RandomBeacon - Authorization", () => { // Maximum possible authorization - the entire stake delegated to the // staking provider. context("when increasing to the maximum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -371,7 +379,7 @@ describe("RandomBeacon - Authorization", () => { authorizer, ).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) }) @@ -409,7 +417,7 @@ describe("RandomBeacon - Authorization", () => { // Minimum possible authorization - the minimum authorized amount for // ECDSA as set in `minimumAuthorization` parameter. context("when increasing to the minimum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -419,7 +427,7 @@ describe("RandomBeacon - Authorization", () => { authorizer, ).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), minimumAuthorization, ) }) @@ -443,7 +451,7 @@ describe("RandomBeacon - Authorization", () => { // Maximum possible authorization - the entire stake delegated to the // staking provider. context("when increasing to the maximum possible value", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -453,7 +461,7 @@ describe("RandomBeacon - Authorization", () => { authorizer, ).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) }) @@ -497,7 +505,7 @@ describe("RandomBeacon - Authorization", () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) }) @@ -510,13 +518,17 @@ describe("RandomBeacon - Authorization", () => { // to 0 or to some value above the minimum. context("when decreasing to a non-zero value below the minimum", () => { it("should revert", async () => { - const deauthorizingTo = minimumAuthorization.sub(1) - const deauthorizingBy = stakedAmount.sub(deauthorizingTo) + const deauthorizingTo = minimumAuthorization - 1n + const deauthorizingBy = stakedAmount - deauthorizingTo await expect( legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy), + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ), ).to.be.revertedWith( "Authorization amount should be 0 or above the minimum", ) @@ -526,17 +538,21 @@ describe("RandomBeacon - Authorization", () => { // Decreasing to zero when operator was not set up yet - authorization // decrease request is valid and can be approved context("when decreasing to zero", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse const decreasingTo = 0 - let decreasingBy: BigNumber + let decreasingBy: bigint before(async () => { await createSnapshot() - decreasingBy = stakedAmount.sub(decreasingTo) + decreasingBy = stakedAmount - BigInt(decreasingTo) tx = await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasingBy, + ) }) after(async () => { @@ -574,18 +590,22 @@ describe("RandomBeacon - Authorization", () => { }) context("when decreasing to the minimum", () => { - let tx: ContractTransaction - let decreasingTo: BigNumber - let decreasingBy: BigNumber + let tx: ContractTransactionResponse + let decreasingTo: bigint + let decreasingBy: bigint before(async () => { await createSnapshot() decreasingTo = minimumAuthorization - decreasingBy = stakedAmount.sub(decreasingTo) + decreasingBy = stakedAmount - decreasingTo tx = await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasingBy, + ) }) after(async () => { @@ -623,18 +643,22 @@ describe("RandomBeacon - Authorization", () => { }) context("when decreasing to a value above the minimum", () => { - let tx: ContractTransaction - let decreasingTo: BigNumber - let decreasingBy: BigNumber + let tx: ContractTransactionResponse + let decreasingTo: bigint + let decreasingBy: bigint before(async () => { await createSnapshot() - decreasingTo = minimumAuthorization.add(1) - decreasingBy = stakedAmount.sub(decreasingTo) + decreasingTo = minimumAuthorization + 1n + decreasingBy = stakedAmount - decreasingTo tx = await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasingBy, + ) }) after(async () => { @@ -680,7 +704,11 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingFirst) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingFirst, + ) }) after(async () => { @@ -709,7 +737,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -738,7 +766,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -773,7 +801,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -819,7 +847,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -848,7 +876,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -877,7 +905,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -905,7 +933,7 @@ describe("RandomBeacon - Authorization", () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) await randomBeacon @@ -919,13 +947,17 @@ describe("RandomBeacon - Authorization", () => { context("when decreasing to a non-zero value below the minimum", () => { it("should revert", async () => { - const deauthorizingTo = minimumAuthorization.sub(1) - const deauthorizingBy = stakedAmount.sub(deauthorizingTo) + const deauthorizingTo = minimumAuthorization - 1n + const deauthorizingBy = stakedAmount - deauthorizingTo await expect( legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy), + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ), ).to.be.revertedWith( "Authorization amount should be 0 or above the minimum", ) @@ -933,17 +965,21 @@ describe("RandomBeacon - Authorization", () => { }) context("when decreasing to zero", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse const decreasingTo = 0 - let decreasingBy: BigNumber + let decreasingBy: bigint before(async () => { await createSnapshot() - decreasingBy = stakedAmount.sub(decreasingTo) + decreasingBy = stakedAmount - BigInt(decreasingTo) tx = await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasingBy, + ) }) after(async () => { @@ -980,18 +1016,22 @@ describe("RandomBeacon - Authorization", () => { }) context("when decreasing to the minimum", () => { - let tx: ContractTransaction - let decreasingTo: BigNumber - let decreasingBy: BigNumber + let tx: ContractTransactionResponse + let decreasingTo: bigint + let decreasingBy: bigint before(async () => { await createSnapshot() decreasingTo = minimumAuthorization - decreasingBy = stakedAmount.sub(decreasingTo) + decreasingBy = stakedAmount - decreasingTo tx = await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasingBy, + ) }) after(async () => { @@ -1028,18 +1068,22 @@ describe("RandomBeacon - Authorization", () => { }) context("when decreasing to a value above the minimum", () => { - let tx: ContractTransaction - let decreasingTo: BigNumber - let decreasingBy: BigNumber + let tx: ContractTransactionResponse + let decreasingTo: bigint + let decreasingBy: bigint before(async () => { await createSnapshot() - decreasingTo = minimumAuthorization.add(1) - decreasingBy = stakedAmount.sub(decreasingTo) + decreasingTo = minimumAuthorization + 1n + decreasingBy = stakedAmount - decreasingTo tx = await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasingBy, + ) }) after(async () => { @@ -1086,7 +1130,11 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingFirst) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingFirst, + ) }) after(async () => { @@ -1114,7 +1162,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1169,7 +1217,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1207,7 +1255,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1260,7 +1308,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1304,7 +1352,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ), ).to.be.revertedWith( @@ -1324,7 +1372,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1379,7 +1427,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1434,7 +1482,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ), ).to.be.revertedWith( @@ -1454,7 +1502,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1491,7 +1539,7 @@ describe("RandomBeacon - Authorization", () => { "requestAuthorizationDecrease(address,address,uint96)" ]( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), deauthorizingSecond, ) }) @@ -1527,7 +1575,7 @@ describe("RandomBeacon - Authorization", () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) }) @@ -1553,7 +1601,11 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) }) after(async () => { @@ -1583,7 +1635,11 @@ describe("RandomBeacon - Authorization", () => { const deauthorizingBy = stakedAmount await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) }) after(async () => { @@ -1631,7 +1687,7 @@ describe("RandomBeacon - Authorization", () => { }) context("when the pool was updated and the delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1684,13 +1740,13 @@ describe("RandomBeacon - Authorization", () => { context("when the operator is unknown", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) @@ -1724,7 +1780,7 @@ describe("RandomBeacon - Authorization", () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) @@ -1739,7 +1795,7 @@ describe("RandomBeacon - Authorization", () => { context("when the operator is not in the sortition pool", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1783,7 +1839,7 @@ describe("RandomBeacon - Authorization", () => { context("when the sortition pool is locked", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1817,7 +1873,7 @@ describe("RandomBeacon - Authorization", () => { stakingProvider.address, operator.address, stakedAmount, - stakedAmount.sub(slashedAmount), + stakedAmount - slashedAmount, ) }) }) @@ -1825,7 +1881,7 @@ describe("RandomBeacon - Authorization", () => { context("when the sortition pool is not locked", () => { context("when the authorization drops to above the minimum", () => { const slashedAmount = to1e18(100) - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1861,8 +1917,8 @@ describe("RandomBeacon - Authorization", () => { "when the authorized amount drops to below the minimum", () => { before(async () => { - const slashingTo = minimumAuthorization.sub(1) - const slashingBy = stakedAmount.sub(slashingTo) + const slashingTo = minimumAuthorization - 1n + const slashingBy = stakedAmount - slashingTo await createSnapshot() @@ -1934,12 +1990,12 @@ describe("RandomBeacon - Authorization", () => { const authorizedAmount = minimumAuthorization await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedAmount, ) - const slashingTo = minimumAuthorization.sub(1) - const slashedAmount = authorizedAmount.sub(slashingTo) + const slashingTo = minimumAuthorization - 1n + const slashedAmount = authorizedAmount - slashingTo await staking .connect(slasher.wallet) @@ -1960,7 +2016,7 @@ describe("RandomBeacon - Authorization", () => { ) context("when the operator has the minimum stake authorized", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1971,7 +2027,7 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), minimumAuthorization, ) @@ -1988,7 +2044,7 @@ describe("RandomBeacon - Authorization", () => { it("should use a correct stake weight", async () => { expect(await sortitionPool.getPoolWeight(operator.address)).to.equal( - minimumAuthorization.div(constants.poolWeightDivisor), + minimumAuthorization / constants.poolWeightDivisor, ) }) @@ -2002,7 +2058,7 @@ describe("RandomBeacon - Authorization", () => { context( "when the operator has more than the minimum stake authorized", () => { - let authorizedStake: BigNumber + let authorizedStake: bigint before(async () => { await createSnapshot() @@ -2011,11 +2067,11 @@ describe("RandomBeacon - Authorization", () => { .connect(stakingProvider) .registerOperator(operator.address) - authorizedStake = minimumAuthorization.mul(2) + authorizedStake = minimumAuthorization * 2n await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedStake, ) @@ -2033,14 +2089,14 @@ describe("RandomBeacon - Authorization", () => { it("should use a correct stake weight", async () => { expect(await sortitionPool.getPoolWeight(operator.address)).to.equal( - authorizedStake.div(constants.poolWeightDivisor), + authorizedStake / constants.poolWeightDivisor, ) }) }, ) context("when operator is in the process of deauthorizing", () => { - let deauthorizingTo: BigNumber + let deauthorizingTo: bigint before(async () => { await createSnapshot() @@ -2053,16 +2109,20 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedStake, ) - deauthorizingTo = minimumAuthorization.add(to1e18(1337)) - const deauthorizingBy = authorizedStake.sub(deauthorizingTo) + deauthorizingTo = minimumAuthorization + to1e18(1337) + const deauthorizingBy = authorizedStake - deauthorizingTo await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) await randomBeacon.connect(operator).joinSortitionPool() }) @@ -2077,7 +2137,7 @@ describe("RandomBeacon - Authorization", () => { it("should use a correct stake weight", async () => { expect(await sortitionPool.getPoolWeight(operator.address)).to.equal( - deauthorizingTo.div(constants.poolWeightDivisor), + deauthorizingTo / constants.poolWeightDivisor, ) }) @@ -2093,7 +2153,7 @@ describe("RandomBeacon - Authorization", () => { context( "when operator is in the process of deauthorizing but also increased authorization in the meantime", () => { - let expectedAuthorizedStake: BigNumber + let expectedAuthorizedStake: bigint before(async () => { await createSnapshot() @@ -2102,29 +2162,33 @@ describe("RandomBeacon - Authorization", () => { .connect(stakingProvider) .registerOperator(operator.address) - const authorizedStake = minimumAuthorization.add(to1e18(100)) + const authorizedStake = minimumAuthorization + to1e18(100) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedStake, ) - const deauthorizingTo = minimumAuthorization.add(to1e18(50)) - const deauthorizingBy = authorizedStake.sub(deauthorizingTo) + const deauthorizingTo = minimumAuthorization + to1e18(50) + const deauthorizingBy = authorizedStake - deauthorizingTo await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) const increasingBy = to1e18(5000) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), increasingBy, ) - expectedAuthorizedStake = deauthorizingTo.add(increasingBy) + expectedAuthorizedStake = deauthorizingTo + increasingBy await randomBeacon.connect(operator).joinSortitionPool() }) @@ -2140,7 +2204,7 @@ describe("RandomBeacon - Authorization", () => { it("should use a correct stake weight", async () => { expect(await sortitionPool.getPoolWeight(operator.address)).to.equal( - expectedAuthorizedStake.div(constants.poolWeightDivisor), + expectedAuthorizedStake / constants.poolWeightDivisor, ) }) @@ -2178,14 +2242,14 @@ describe("RandomBeacon - Authorization", () => { }) context("when the authorization increased", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), minimumAuthorization, ) @@ -2211,21 +2275,25 @@ describe("RandomBeacon - Authorization", () => { }) context("when there was an authorization decrease request", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakedAmount, ) const deauthorizingBy = to1e18(100) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) tx = await randomBeacon .connect(thirdParty) @@ -2267,8 +2335,8 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, - minimumAuthorization.mul(2), + await randomBeacon.getAddress(), + minimumAuthorization * 2n, ) await randomBeacon.connect(operator).joinSortitionPool() @@ -2279,8 +2347,8 @@ describe("RandomBeacon - Authorization", () => { }) context("when the authorization increased", () => { - let tx: ContractTransaction - let expectedWeight: BigNumber + let tx: ContractTransactionResponse + let expectedWeight: bigint before(async () => { await createSnapshot() @@ -2288,17 +2356,15 @@ describe("RandomBeacon - Authorization", () => { const topUp = to1e18(1337) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), topUp, ) // initial authorization was 2 x minimum // it was increased by 1337 tokens // so the final authorization should be 2 x minimum + 1337 - expectedWeight = minimumAuthorization - .mul(2) - .add(topUp) - .div(constants.poolWeightDivisor) + expectedWeight = + (minimumAuthorization * 2n + topUp) / constants.poolWeightDivisor tx = await randomBeacon .connect(thirdParty) @@ -2325,23 +2391,25 @@ describe("RandomBeacon - Authorization", () => { context( "when there was an authorization decrease request to non-zero", () => { - let tx: ContractTransaction - let expectedWeight: BigNumber + let tx: ContractTransactionResponse + let expectedWeight: bigint before(async () => { await createSnapshot() // initial authorization was 2 x minimum // we want to decrease to minimum + 1337 - const deauthorizingTo = minimumAuthorization.add(to1e18(1337)) - const deauthorizingBy = minimumAuthorization - .mul(2) - .sub(deauthorizingTo) - expectedWeight = deauthorizingTo.div(constants.poolWeightDivisor) + const deauthorizingTo = minimumAuthorization + to1e18(1337) + const deauthorizingBy = minimumAuthorization * 2n - deauthorizingTo + expectedWeight = deauthorizingTo / constants.poolWeightDivisor await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) tx = await randomBeacon .connect(thirdParty) @@ -2377,18 +2445,22 @@ describe("RandomBeacon - Authorization", () => { context( "when there was an authorization decrease request to zero", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() // initial authorization was 2 x minimum // we want to decrease to zero - const deauthorizingBy = minimumAuthorization.mul(2) + const deauthorizingBy = minimumAuthorization * 2n await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) tx = await randomBeacon .connect(thirdParty) @@ -2423,8 +2495,8 @@ describe("RandomBeacon - Authorization", () => { context( "when operator is in the process of deauthorizing but also increased authorization in the meantime", () => { - let tx: ContractTransaction - let expectedWeight: BigNumber + let tx: ContractTransactionResponse + let expectedWeight: bigint before(async () => { await createSnapshot() @@ -2432,24 +2504,26 @@ describe("RandomBeacon - Authorization", () => { // initial authorization was 2 x minimum // we want to decrease to minimum + 1337 // and then decrease by 7331 - const deauthorizingTo = minimumAuthorization.add(to1e18(1337)) - const deauthorizingBy = minimumAuthorization - .mul(2) - .sub(deauthorizingTo) + const deauthorizingTo = minimumAuthorization + to1e18(1337) + const deauthorizingBy = minimumAuthorization * 2n - deauthorizingTo const increasingBy = to1e18(7331) - const increasingTo = deauthorizingTo.add(increasingBy) - expectedWeight = increasingTo.div(constants.poolWeightDivisor) + const increasingTo = deauthorizingTo + increasingBy + expectedWeight = increasingTo / constants.poolWeightDivisor await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) await legacyTokenStakingAt( staking, authorizer, ).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), increasingBy, ) @@ -2496,7 +2570,7 @@ describe("RandomBeacon - Authorization", () => { }) context("when staking provider has stake authorized", () => { - let authorizedAmount: BigNumber + let authorizedAmount: bigint before(async () => { await createSnapshot() @@ -2504,7 +2578,7 @@ describe("RandomBeacon - Authorization", () => { authorizedAmount = minimumAuthorization await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedAmount, ) }) @@ -2523,24 +2597,28 @@ describe("RandomBeacon - Authorization", () => { context( "when staking provider has some part of the stake deauthorizing", () => { - let authorizedAmount: BigNumber - let deauthorizingAmount: BigNumber + let authorizedAmount: bigint + let deauthorizingAmount: bigint before(async () => { await createSnapshot() - authorizedAmount = minimumAuthorization.add(to1e18(2000)) + authorizedAmount = minimumAuthorization + to1e18(2000) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedAmount, ) deauthorizingAmount = to1e18(1337) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingAmount) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingAmount, + ) }) after(async () => { @@ -2550,7 +2628,7 @@ describe("RandomBeacon - Authorization", () => { it("should return authorized amount minus deauthorizing amount", async () => { expect( await randomBeacon.eligibleStake(stakingProvider.address), - ).to.equal(authorizedAmount.sub(deauthorizingAmount)) + ).to.equal(authorizedAmount - deauthorizingAmount) }) }, ) @@ -2562,13 +2640,17 @@ describe("RandomBeacon - Authorization", () => { const authorizedAmount = minimumAuthorization await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedAmount, ) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, authorizedAmount) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + authorizedAmount, + ) }) after(async () => { @@ -2586,16 +2668,20 @@ describe("RandomBeacon - Authorization", () => { before(async () => { await createSnapshot() - const authorizedAmount = minimumAuthorization.add(1200) + const authorizedAmount = minimumAuthorization + 1200n await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedAmount, ) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, authorizedAmount) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + authorizedAmount, + ) await randomBeacon.approveAuthorizationDecrease(stakingProvider.address) }) @@ -2621,12 +2707,12 @@ describe("RandomBeacon - Authorization", () => { const authorizedAmount = minimumAuthorization await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedAmount, ) - const slashingTo = minimumAuthorization.sub(1) - const slashedAmount = authorizedAmount.sub(slashingTo) + const slashingTo = minimumAuthorization - 1n + const slashedAmount = authorizedAmount - slashingTo await staking .connect(slasher.wallet) @@ -2651,10 +2737,10 @@ describe("RandomBeacon - Authorization", () => { before(async () => { await createSnapshot() - const authorizedAmount = minimumAuthorization.add(1200) + const authorizedAmount = minimumAuthorization + 1200n await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), authorizedAmount, ) @@ -2665,7 +2751,11 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, authorizedAmount) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + authorizedAmount, + ) }) after(async () => { @@ -2701,7 +2791,7 @@ describe("RandomBeacon - Authorization", () => { stakingProvider.address, ), ).to.be.closeTo( - ethers.BigNumber.from(params.authorizationDecreaseDelay / 2), + BigInt(params.authorizationDecreaseDelay / 2), 5, // +- 5sec ) }) @@ -2762,7 +2852,7 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), minimumAuthorization, ) }) @@ -2788,8 +2878,8 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, - minimumAuthorization.mul(2), + await randomBeacon.getAddress(), + minimumAuthorization * 2n, ) await randomBeacon.connect(operator).joinSortitionPool() @@ -2812,7 +2902,7 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), to1e18(1337), ) }) @@ -2844,7 +2934,11 @@ describe("RandomBeacon - Authorization", () => { const deauthorizingBy = to1e18(1) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, deauthorizingBy) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + deauthorizingBy, + ) }) after(async () => { @@ -2876,12 +2970,12 @@ describe("RandomBeacon - Authorization", () => { // will affect authorized stake amount for RandomBeacon. const authorized = await staking.authorizedStake( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), ) - const increaseBy = stakedAmount.sub(authorized) + const increaseBy = stakedAmount - authorized await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), increaseBy, ) await randomBeacon.updateOperatorStatus(operator.address) @@ -2927,7 +3021,7 @@ describe("RandomBeacon - Authorization", () => { // Testing final states for scenarios when functions are invoked one after // another. Operator is known and registered in the sortition pool. context("mixed interactions", () => { - let initialIncrease: BigNumber + let initialIncrease: bigint before(async () => { await createSnapshot() @@ -2938,10 +3032,10 @@ describe("RandomBeacon - Authorization", () => { // Authorized almost the entire staked amount but leave some margin for // authorization increase. - initialIncrease = stakedAmount.sub(to1e18(20000)) + initialIncrease = stakedAmount - to1e18(20000) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), initialIncrease, ) await randomBeacon.connect(operator).joinSortitionPool() @@ -2961,7 +3055,7 @@ describe("RandomBeacon - Authorization", () => { secondIncrease = to1e18(11111) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), secondIncrease, ) @@ -2977,7 +3071,7 @@ describe("RandomBeacon - Authorization", () => { it("should have correct eligible stake", async () => { expect( await randomBeacon.eligibleStake(stakingProvider.address), - ).to.equal(initialIncrease.add(secondIncrease)) + ).to.equal(initialIncrease + BigInt(secondIncrease)) }) it("should have operator status updated", async () => { @@ -2998,7 +3092,11 @@ describe("RandomBeacon - Authorization", () => { firstDecrease = to1e18(111) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, firstDecrease) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + firstDecrease, + ) await randomBeacon .connect(operator) .updateOperatorStatus(operator.address) @@ -3006,7 +3104,7 @@ describe("RandomBeacon - Authorization", () => { secondIncrease = to1e18(11111) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), secondIncrease, ) await randomBeacon @@ -3021,7 +3119,9 @@ describe("RandomBeacon - Authorization", () => { it("should have correct eligible stake", async () => { expect( await randomBeacon.eligibleStake(stakingProvider.address), - ).to.equal(initialIncrease.sub(firstDecrease).add(secondIncrease)) + ).to.equal( + initialIncrease - BigInt(firstDecrease) + BigInt(secondIncrease), + ) }) it("should have operator status updated", async () => { @@ -3033,8 +3133,8 @@ describe("RandomBeacon - Authorization", () => { // Invoke `increaseAuthorization` after `approveAuthorizationDecrease`. // The decrease is approved when `increaseAuthorization` is called. describe("non-zero approveAuthorizationDecrease -> authorizationIncreased", () => { - let firstDecrease: BigNumber - let secondIncrease: BigNumber + let firstDecrease: bigint + let secondIncrease: bigint before(async () => { await createSnapshot() @@ -3042,7 +3142,11 @@ describe("RandomBeacon - Authorization", () => { firstDecrease = to1e18(222) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, firstDecrease) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + firstDecrease, + ) await randomBeacon .connect(operator) .updateOperatorStatus(operator.address) @@ -3053,7 +3157,7 @@ describe("RandomBeacon - Authorization", () => { secondIncrease = to1e18(7311) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), secondIncrease, ) await randomBeacon @@ -3068,7 +3172,7 @@ describe("RandomBeacon - Authorization", () => { it("should have correct eligible stake", async () => { expect( await randomBeacon.eligibleStake(stakingProvider.address), - ).to.equal(initialIncrease.sub(firstDecrease).add(secondIncrease)) + ).to.equal(initialIncrease - firstDecrease + secondIncrease) }) it("should have operator status updated", async () => { @@ -3086,7 +3190,11 @@ describe("RandomBeacon - Authorization", () => { await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, initialIncrease) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + initialIncrease, + ) await randomBeacon .connect(operator) .updateOperatorStatus(operator.address) @@ -3094,10 +3202,10 @@ describe("RandomBeacon - Authorization", () => { await helpers.time.increaseTime(params.authorizationDecreaseDelay) await randomBeacon.approveAuthorizationDecrease(stakingProvider.address) - secondIncrease = minimumAuthorization.add(to1e18(21)) + secondIncrease = minimumAuthorization + to1e18(21) await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), secondIncrease, ) await randomBeacon.connect(operator).joinSortitionPool() @@ -3122,14 +3230,14 @@ describe("RandomBeacon - Authorization", () => { // Invoke `increaseAuthorization` after `involuntaryAuthorizationDecrease` // when the authorization amount dropped below the minimum authorization. describe("below-minimum involuntaryAuthorizationDecrease -> authorizationIncreased", () => { - let slashingTo: BigNumber - let secondIncrease: BigNumber + let slashingTo: bigint + let secondIncrease: bigint before(async () => { await createSnapshot() - slashingTo = minimumAuthorization.sub(1) - const slashedAmount = initialIncrease.sub(slashingTo) + slashingTo = minimumAuthorization - 1n + const slashedAmount = initialIncrease - slashingTo await staking .connect(slasher.wallet) @@ -3140,7 +3248,9 @@ describe("RandomBeacon - Authorization", () => { // they increase the authorization again. secondIncrease = to1e18(10000) await t.connect(deployer).mint(owner.address, secondIncrease) - await t.connect(owner).approve(staking.address, secondIncrease) + await t + .connect(owner) + .approve(await staking.getAddress(), secondIncrease) await staking .connect(owner) .topUp(stakingProvider.address, secondIncrease) @@ -3148,7 +3258,7 @@ describe("RandomBeacon - Authorization", () => { // And finally increase! await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), secondIncrease, ) await randomBeacon.connect(operator).joinSortitionPool() @@ -3161,7 +3271,7 @@ describe("RandomBeacon - Authorization", () => { it("should have correct eligible stake", async () => { expect( await randomBeacon.eligibleStake(stakingProvider.address), - ).to.equal(slashingTo.add(secondIncrease)) + ).to.equal(slashingTo + secondIncrease) }) it("should have operator status updated", async () => { @@ -3171,8 +3281,8 @@ describe("RandomBeacon - Authorization", () => { }) describe("authorizationDecreaseRequested -> involuntaryAuthorizationDecrease", () => { - let decreasedAmount: BigNumber - let slashingTo: BigNumber + let decreasedAmount: bigint + let slashingTo: bigint before(async () => { await createSnapshot() @@ -3180,13 +3290,17 @@ describe("RandomBeacon - Authorization", () => { decreasedAmount = to1e18(20000) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasedAmount) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasedAmount, + ) await randomBeacon .connect(operator) .updateOperatorStatus(operator.address) - slashingTo = initialIncrease.sub(to1e18(100)) - const slashedAmount = initialIncrease.sub(slashingTo) + slashingTo = initialIncrease - to1e18(100) + const slashedAmount = initialIncrease - slashingTo await staking .connect(slasher.wallet) @@ -3201,7 +3315,7 @@ describe("RandomBeacon - Authorization", () => { it("should have correct eligible stake", async () => { expect( await randomBeacon.eligibleStake(stakingProvider.address), - ).to.equal(slashingTo.sub(decreasedAmount)) + ).to.equal(slashingTo - decreasedAmount) }) it("should have operator status updated", async () => { @@ -3211,8 +3325,8 @@ describe("RandomBeacon - Authorization", () => { }) describe("authorizationDecreaseRequested -> involuntaryAuthorizationDecrease -> approveAuthorizationDecrease", () => { - let decreasedAmount: BigNumber - let slashingTo: BigNumber + let decreasedAmount: bigint + let slashingTo: bigint before(async () => { await createSnapshot() @@ -3220,13 +3334,17 @@ describe("RandomBeacon - Authorization", () => { decreasedAmount = to1e18(20000) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasedAmount) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasedAmount, + ) await randomBeacon .connect(operator) .updateOperatorStatus(operator.address) - slashingTo = initialIncrease.sub(to1e18(100)) - const slashedAmount = initialIncrease.sub(slashingTo) + slashingTo = initialIncrease - to1e18(100) + const slashedAmount = initialIncrease - slashingTo await staking .connect(slasher.wallet) @@ -3244,7 +3362,7 @@ describe("RandomBeacon - Authorization", () => { it("should have correct eligible stake", async () => { expect( await randomBeacon.eligibleStake(stakingProvider.address), - ).to.equal(slashingTo.sub(decreasedAmount)) + ).to.equal(slashingTo - decreasedAmount) }) it("should have operator status updated", async () => { @@ -3263,7 +3381,11 @@ describe("RandomBeacon - Authorization", () => { decreasedAmount = to1e18(1000) await legacyTokenStakingAt(staking, authorizer)[ "requestAuthorizationDecrease(address,address,uint96)" - ](stakingProvider.address, randomBeacon.address, decreasedAmount) + ]( + stakingProvider.address, + await randomBeacon.getAddress(), + decreasedAmount, + ) await randomBeacon .connect(operator) .updateOperatorStatus(operator.address) @@ -3271,10 +3393,8 @@ describe("RandomBeacon - Authorization", () => { await helpers.time.increaseTime(params.authorizationDecreaseDelay) await randomBeacon.approveAuthorizationDecrease(stakingProvider.address) - slashingTo = initialIncrease.sub(to1e18(2500)) - const slashedAmount = initialIncrease - .sub(decreasedAmount) - .sub(slashingTo) + slashingTo = initialIncrease - to1e18(2500) + const slashedAmount = initialIncrease - decreasedAmount - slashingTo await staking .connect(slasher.wallet) diff --git a/solidity/random-beacon/test/RandomBeacon.Callback.test.ts b/solidity/random-beacon/test/RandomBeacon.Callback.test.ts index f8dcf74f12..e07d240789 100644 --- a/solidity/random-beacon/test/RandomBeacon.Callback.test.ts +++ b/solidity/random-beacon/test/RandomBeacon.Callback.test.ts @@ -2,6 +2,7 @@ import { ethers, helpers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" +import requireResult from "./helpers/chain" import blsData from "./data/bls" import { constants, params, randomBeaconDeployment } from "./fixtures" import { createGroup } from "./utils/groups" @@ -15,9 +16,9 @@ import type { RandomBeacon, RandomBeaconGovernance, } from "../typechain" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress const { createSnapshot, restoreSnapshot } = helpers.snapshot const fixture = async () => { @@ -93,10 +94,10 @@ describe("RandomBeacon - Callback", () => { await randomBeacon .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) await expect(await randomBeacon.getCallbackContract()).to.equal( - callbackContract.address, + await callbackContract.getAddress(), ) await restoreSnapshot() @@ -107,7 +108,7 @@ describe("RandomBeacon - Callback", () => { await randomBeacon .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) await randomBeacon .connect(submitter) @@ -127,7 +128,7 @@ describe("RandomBeacon - Callback", () => { await randomBeacon .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) await randomBeacon .connect(submitter) @@ -135,10 +136,10 @@ describe("RandomBeacon - Callback", () => { await randomBeacon .connect(requester) - .requestRelayEntry(callbackContract1.address) + .requestRelayEntry(await callbackContract1.getAddress()) await expect(await randomBeacon.getCallbackContract()).to.equal( - callbackContract1.address, + await callbackContract1.getAddress(), ) await restoreSnapshot() @@ -162,7 +163,7 @@ describe("RandomBeacon - Callback", () => { await randomBeacon .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) await randomBeacon .connect(submitter) @@ -172,7 +173,9 @@ describe("RandomBeacon - Callback", () => { await expect(lastEntry).to.equal(blsData.groupSignatureUint256) const blockNumber = await callbackContract.blockNumber() - const latestBlock = await ethers.provider.getBlock("latest") + const latestBlock = requireResult( + await ethers.provider.getBlock("latest"), + ) await expect(blockNumber).to.equal(latestBlock.number) @@ -194,7 +197,7 @@ describe("RandomBeacon - Callback", () => { await randomBeacon .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) const tx = await randomBeacon .connect(submitter) @@ -204,7 +207,7 @@ describe("RandomBeacon - Callback", () => { .to.emit(randomBeacon, "CallbackFailed") .withArgs( blsData.groupSignatureUint256, - (await tx.wait()).blockNumber, + requireResult(await tx.wait()).blockNumber, ) await restoreSnapshot() @@ -215,7 +218,7 @@ describe("RandomBeacon - Callback", () => { await randomBeacon .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) await callbackContract.setFailureFlag(true) @@ -227,7 +230,7 @@ describe("RandomBeacon - Callback", () => { .to.emit(randomBeacon, "CallbackFailed") .withArgs( blsData.groupSignatureUint256, - (await tx.wait()).blockNumber, + requireResult(await tx.wait()).blockNumber, ) await restoreSnapshot() diff --git a/solidity/random-beacon/test/RandomBeacon.Constructor.test.ts b/solidity/random-beacon/test/RandomBeacon.Constructor.test.ts index e0d26fd1a7..00d0ba805d 100644 --- a/solidity/random-beacon/test/RandomBeacon.Constructor.test.ts +++ b/solidity/random-beacon/test/RandomBeacon.Constructor.test.ts @@ -3,7 +3,7 @@ import { expect } from "chai" import type { RandomBeacon__factory, SortitionPool } from "../typechain" -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress const { to1e18 } = helpers.number @@ -31,26 +31,26 @@ describe("RandomBeacon - Constructor", () => { const BLS = await ethers.getContractFactory("BLS") const bls = await BLS.deploy() - await bls.deployed() + await bls.waitForDeployment() const Authorization = await ethers.getContractFactory("BeaconAuthorization") const authorization = await Authorization.deploy() - await authorization.deployed() + await authorization.waitForDeployment() const BeaconDkg = await ethers.getContractFactory("BeaconDkg") const dkg = await BeaconDkg.deploy() - await dkg.deployed() + await dkg.waitForDeployment() const BeaconInactivity = await ethers.getContractFactory("BeaconInactivity") const inactivity = await BeaconInactivity.deploy() - await inactivity.deployed() + await inactivity.waitForDeployment() RandomBeacon = await ethers.getContractFactory("RandomBeacon", { libraries: { - BLS: bls.address, - BeaconAuthorization: authorization.address, - BeaconDkg: dkg.address, - BeaconInactivity: inactivity.address, + BLS: await bls.getAddress(), + BeaconAuthorization: await authorization.getAddress(), + BeaconDkg: await dkg.getAddress(), + BeaconInactivity: await inactivity.getAddress(), }, }) }) @@ -60,7 +60,7 @@ describe("RandomBeacon - Constructor", () => { it("should work", async () => { await expect( RandomBeacon.deploy( - sortitionPool.address, + await sortitionPool.getAddress(), tToken, staking, dkgValidator, @@ -88,7 +88,7 @@ describe("RandomBeacon - Constructor", () => { it("should revert", async () => { await expect( RandomBeacon.deploy( - sortitionPool.address, + await sortitionPool.getAddress(), ZERO_ADDRESS, staking, dkgValidator, @@ -102,7 +102,7 @@ describe("RandomBeacon - Constructor", () => { it("should revert", async () => { await expect( RandomBeacon.deploy( - sortitionPool.address, + await sortitionPool.getAddress(), tToken, ZERO_ADDRESS, dkgValidator, @@ -116,7 +116,7 @@ describe("RandomBeacon - Constructor", () => { it("should revert", async () => { await expect( RandomBeacon.deploy( - sortitionPool.address, + await sortitionPool.getAddress(), tToken, staking, ZERO_ADDRESS, @@ -130,7 +130,7 @@ describe("RandomBeacon - Constructor", () => { it("should revert", async () => { await expect( RandomBeacon.deploy( - sortitionPool.address, + await sortitionPool.getAddress(), tToken, staking, dkgValidator, diff --git a/solidity/random-beacon/test/RandomBeacon.GroupCreation.test.ts b/solidity/random-beacon/test/RandomBeacon.GroupCreation.test.ts index 169101fe4e..2799bf9da2 100644 --- a/solidity/random-beacon/test/RandomBeacon.GroupCreation.test.ts +++ b/solidity/random-beacon/test/RandomBeacon.GroupCreation.test.ts @@ -1,9 +1,11 @@ +import { toBeHex } from "ethers" /* eslint-disable @typescript-eslint/no-unused-expressions */ import { ethers, helpers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" +import requireResult from "./helpers/chain" import blsData from "./data/bls" import { constants, dkgState, params, randomBeaconDeployment } from "./fixtures" import { @@ -20,15 +22,15 @@ import { registerOperators } from "./utils/operators" import { selectGroup, createGroup, hashUint32Array } from "./utils/groups" import { fakeTokenStaking } from "./mocks/staking" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { BigNumber, BytesLike, ContractTransaction } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { BytesLike, ContractTransactionResponse } from "ethers" import type { Operator } from "./utils/operators" import type { BeaconDkg as DKG } from "../typechain/contracts/test/RandomBeaconStub" import type { Mock } from "./helpers/mock" import type { RandomBeacon, SortitionPool, T, TokenStaking } from "../typechain" const { mineBlocks, mineBlocksTo } = helpers.time -const { keccak256 } = ethers.utils +const { keccak256 } = ethers const { provider } = ethers const { createSnapshot, restoreSnapshot } = helpers.snapshot @@ -39,7 +41,7 @@ type RandomBeaconTest = RandomBeacon & { roughlyAddGroup: ( groupPubKey: BytesLike, groupMembersHash: BytesLike, - ) => Promise + ) => Promise } const fixture = async () => { @@ -73,7 +75,7 @@ const fixture = async () => { describe("RandomBeacon - Group Creation", () => { const dkgTimeout: number = constants.offchainDkgTime + params.dkgResultSubmissionTimeout - const groupPublicKey: string = ethers.utils.hexValue(blsData.groupPubKey) + const groupPublicKey: string = ethers.toQuantity(blsData.groupPubKey) let thirdParty: SignerWithAddress let signers: Operator[] @@ -99,7 +101,7 @@ describe("RandomBeacon - Group Creation", () => { describe("genesis", async () => { context("when called by a third party", async () => { - let tx: Promise + let tx: Promise before("run genesis", async () => { await createSnapshot() @@ -117,8 +119,8 @@ describe("RandomBeacon - Group Creation", () => { }) context("with initial contract state", async () => { - let tx: ContractTransaction - let expectedSeed: BigNumber + let tx: ContractTransactionResponse + let expectedSeed: bigint before("run genesis", async () => { await createSnapshot() @@ -147,13 +149,13 @@ describe("RandomBeacon - Group Creation", () => { context("with no registered groups", async () => { context("with genesis in progress", async () => { let startBlock: number - let genesisSeed: BigNumber + let genesisSeed: bigint before("run genesis", async () => { await createSnapshot() const [genesisTx, seed] = await genesis(randomBeacon) - startBlock = (await genesisTx.wait()).blockNumber + startBlock = requireResult(await genesisTx.wait()).blockNumber genesisSeed = seed }) @@ -299,13 +301,13 @@ describe("RandomBeacon - Group Creation", () => { context("when genesis dkg started", async () => { let startBlock: number - let genesisSeed: BigNumber + let genesisSeed: bigint before("run genesis", async () => { await createSnapshot() const [genesisTx, seed] = await genesis(randomBeacon) - startBlock = (await genesisTx.wait()).blockNumber + startBlock = requireResult(await genesisTx.wait()).blockNumber genesisSeed = seed }) @@ -474,13 +476,13 @@ describe("RandomBeacon - Group Creation", () => { context("when genesis dkg started", async () => { let startBlock: number - let genesisSeed: BigNumber + let genesisSeed: bigint before("run genesis", async () => { await createSnapshot() const [genesisTx, seed] = await genesis(randomBeacon) - startBlock = (await genesisTx.wait()).blockNumber + startBlock = requireResult(await genesisTx.wait()).blockNumber genesisSeed = seed }) @@ -551,7 +553,7 @@ describe("RandomBeacon - Group Creation", () => { before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -564,7 +566,7 @@ describe("RandomBeacon - Group Creation", () => { noMisbehaved, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -690,7 +692,7 @@ describe("RandomBeacon - Group Creation", () => { await createSnapshot() const tx = await randomBeacon.challengeDkgResult(dkgResult) - challengeBlockNumber = (await tx.wait()).blockNumber + challengeBlockNumber = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -755,14 +757,14 @@ describe("RandomBeacon - Group Creation", () => { context("with group creation in progress", async () => { let startBlock: number - let genesisSeed: BigNumber + let genesisSeed: bigint before("run genesis", async () => { await createSnapshot() const [genesisTx, seed] = await genesis(randomBeacon) - startBlock = (await genesisTx.wait()).blockNumber + startBlock = requireResult(await genesisTx.wait()).blockNumber genesisSeed = seed }) @@ -807,7 +809,7 @@ describe("RandomBeacon - Group Creation", () => { }) context("with enough signatures on the result", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DKG.ResultStruct let dkgResultHash: string @@ -857,7 +859,7 @@ describe("RandomBeacon - Group Creation", () => { }) context("with not enough signatures on the result", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DKG.ResultStruct let dkgResultHash: string @@ -998,7 +1000,7 @@ describe("RandomBeacon - Group Creation", () => { before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -1011,7 +1013,7 @@ describe("RandomBeacon - Group Creation", () => { noMisbehaved, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -1077,7 +1079,7 @@ describe("RandomBeacon - Group Creation", () => { ) const tx = await randomBeacon.challengeDkgResult(dkgResult) - challengeBlockNumber = (await tx.wait()).blockNumber + challengeBlockNumber = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -1085,7 +1087,7 @@ describe("RandomBeacon - Group Creation", () => { }) describe("group registration", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1197,7 +1199,7 @@ describe("RandomBeacon - Group Creation", () => { }) context("with misbehaved members", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DKG.ResultStruct let dkgResultHash: string @@ -1411,14 +1413,14 @@ describe("RandomBeacon - Group Creation", () => { context("with group creation in progress", async () => { let startBlock: number - let genesisSeed: BigNumber + let genesisSeed: bigint before("run genesis", async () => { await createSnapshot() const [genesisTx, seed] = await genesis(randomBeacon) - startBlock = (await genesisTx.wait()).blockNumber + startBlock = requireResult(await genesisTx.wait()).blockNumber genesisSeed = seed }) @@ -1456,14 +1458,14 @@ describe("RandomBeacon - Group Creation", () => { let dkgResultHash: string let dkgResult: DKG.ResultStruct let submitter: SignerWithAddress - let submitterInitialBalance: BigNumber + let submitterInitialBalance: bigint const submitterIndex = 1 before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -1479,7 +1481,7 @@ describe("RandomBeacon - Group Creation", () => { submitterIndex, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -1522,7 +1524,7 @@ describe("RandomBeacon - Group Creation", () => { }) context("when called by a DKG result submitter", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1559,7 +1561,7 @@ describe("RandomBeacon - Group Creation", () => { expect(storedGroup.groupPubKey).to.be.equal(groupPublicKey) expect(storedGroup.registrationBlockNumber).to.be.equal( - (await tx.wait()).blockNumber, + requireResult(await tx.wait()).blockNumber, ) expect(storedGroup.membersHash).to.be.equal( hashUint32Array(dkgResult.members), @@ -1578,11 +1580,11 @@ describe("RandomBeacon - Group Creation", () => { it("should refund ETH", async () => { const postBalance = await provider.getBalance(submitter.address) - const diff = postBalance.sub(submitterInitialBalance) + const diff = postBalance - submitterInitialBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("2000000", "gwei"), // 0,002 ETH + ethers.parseUnits("2000000", "gwei"), // 0,002 ETH ) }) }) @@ -1613,8 +1615,8 @@ describe("RandomBeacon - Group Creation", () => { }) context("when the third party is eligible", async () => { - let tx: Promise - let initApproverBalance: BigNumber + let tx: Promise + let initApproverBalance: bigint before(async () => { await createSnapshot() @@ -1640,7 +1642,7 @@ describe("RandomBeacon - Group Creation", () => { const postBalance = await provider.getBalance( thirdParty.address, ) - const diff = postBalance.sub(initApproverBalance) + const diff = postBalance - initApproverBalance expect(diff).to.be.gt(0) // The third party did not submit the result so we are not @@ -1662,7 +1664,7 @@ describe("RandomBeacon - Group Creation", () => { // Submit a second result by another submitter const anotherSubmitterIndex = 6 let anotherSubmitter: SignerWithAddress - let anotherSubmitterInitialBalance: BigNumber + let anotherSubmitterInitialBalance: bigint before(async () => { await createSnapshot() @@ -1680,7 +1682,7 @@ describe("RandomBeacon - Group Creation", () => { await randomBeacon.challengeDkgResult(maliciousDkgResult) - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -1696,7 +1698,7 @@ describe("RandomBeacon - Group Creation", () => { anotherSubmitterIndex, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -1728,7 +1730,7 @@ describe("RandomBeacon - Group Creation", () => { }) context("with challenge period passed", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1763,7 +1765,7 @@ describe("RandomBeacon - Group Creation", () => { expect(storedGroup.groupPubKey).to.be.equal(groupPublicKey) expect(storedGroup.registrationBlockNumber).to.be.equal( - (await tx.wait()).blockNumber, + requireResult(await tx.wait()).blockNumber, ) expect(storedGroup.membersHash).to.be.equal( hashUint32Array(dkgResult.members), @@ -1784,11 +1786,11 @@ describe("RandomBeacon - Group Creation", () => { const postBalance = await provider.getBalance( anotherSubmitter.address, ) - const diff = postBalance.sub(anotherSubmitterInitialBalance) + const diff = postBalance - anotherSubmitterInitialBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("2400000", "gwei"), // 0,0024 ETH + ethers.parseUnits("2400000", "gwei"), // 0,0024 ETH ) }) }) @@ -1796,7 +1798,7 @@ describe("RandomBeacon - Group Creation", () => { }) context("with max periods duration", async () => { - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -1834,10 +1836,10 @@ describe("RandomBeacon - Group Creation", () => { context("with misbehaved operators", async () => { const misbehavedIndices: number[] = [2, 9, 11, 30, 60, 64] let misbehavedIds: number[] - let tx: ContractTransaction + let tx: ContractTransactionResponse let dkgResult: DKG.ResultStruct let submitter: SignerWithAddress - let submitterInitialBalance: BigNumber + let submitterInitialBalance: bigint before(async () => { await createSnapshot() @@ -1896,11 +1898,11 @@ describe("RandomBeacon - Group Creation", () => { it("should refund ETH", async () => { const postBalance = await provider.getBalance(submitter.address) - const diff = postBalance.sub(submitterInitialBalance) + const diff = postBalance - submitterInitialBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1000000", "gwei"), // 0,001 ETH + ethers.parseUnits("1000000", "gwei"), // 0,001 ETH ) }) }) @@ -1914,8 +1916,8 @@ describe("RandomBeacon - Group Creation", () => { let dkgResult: DKG.ResultStruct let submitter: SignerWithAddress - let submitterInitialBalance: BigNumber - let tx: Promise + let submitterInitialBalance: bigint + let tx: Promise before(async () => { await createSnapshot() @@ -1944,11 +1946,11 @@ describe("RandomBeacon - Group Creation", () => { it("should refund ETH", async () => { const postBalance = await provider.getBalance(submitter.address) - const diff = postBalance.sub(submitterInitialBalance) + const diff = postBalance - submitterInitialBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1000000", "gwei"), // 0,001 ETH + ethers.parseUnits("1000000", "gwei"), // 0,001 ETH ) }) }, @@ -1959,8 +1961,8 @@ describe("RandomBeacon - Group Creation", () => { let dkgResult: DKG.ResultStruct let submitter: SignerWithAddress - let tx: Promise - let submitterInitialBalance: BigNumber + let tx: Promise + let submitterInitialBalance: bigint before(async () => { await createSnapshot() @@ -1989,11 +1991,11 @@ describe("RandomBeacon - Group Creation", () => { it("should refund ETH", async () => { const postBalance = await provider.getBalance(submitter.address) - const diff = postBalance.sub(submitterInitialBalance) + const diff = postBalance - submitterInitialBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("2000000", "gwei"), // 0,002 ETH + ethers.parseUnits("2000000", "gwei"), // 0,002 ETH ) }) }) @@ -2017,7 +2019,7 @@ describe("RandomBeacon - Group Creation", () => { const [genesisTx] = await genesis(randomBeacon) - startBlock = (await genesisTx.wait()).blockNumber + startBlock = requireResult(await genesisTx.wait()).blockNumber }) after(async () => { @@ -2092,8 +2094,8 @@ describe("RandomBeacon - Group Creation", () => { }) context("called by a third party", async () => { - let tx: ContractTransaction - let initialThirdPartyBalance: BigNumber + let tx: ContractTransactionResponse + let initialThirdPartyBalance: bigint before(async () => { await createSnapshot() @@ -2122,10 +2124,10 @@ describe("RandomBeacon - Group Creation", () => { it("should refund ETH", async () => { const postBalance = await provider.getBalance(thirdParty.address) - const diff = postBalance.sub(initialThirdPartyBalance) + const diff = postBalance - initialThirdPartyBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("2000000", "gwei"), // 0,002 ETH + ethers.parseUnits("2000000", "gwei"), // 0,002 ETH ) }) }) @@ -2155,14 +2157,14 @@ describe("RandomBeacon - Group Creation", () => { context("with group creation in progress", async () => { let startBlock: number - let genesisSeed: BigNumber + let genesisSeed: bigint before("run genesis", async () => { await createSnapshot() const [genesisTx, seed] = await genesis(randomBeacon) - startBlock = (await genesisTx.wait()).blockNumber + startBlock = requireResult(await genesisTx.wait()).blockNumber genesisSeed = seed }) @@ -2289,7 +2291,7 @@ describe("RandomBeacon - Group Creation", () => { before(async () => { await createSnapshot() - let tx: ContractTransaction + let tx: ContractTransactionResponse ;({ transaction: tx, dkgResult, @@ -2304,7 +2306,7 @@ describe("RandomBeacon - Group Creation", () => { noMisbehaved, )) - resultSubmissionBlock = (await tx.wait()).blockNumber + resultSubmissionBlock = requireResult(await tx.wait()).blockNumber }) after(async () => { @@ -2313,8 +2315,8 @@ describe("RandomBeacon - Group Creation", () => { context("at the beginning of challenge period", async () => { context("called by a third party", async () => { - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2366,11 +2368,11 @@ describe("RandomBeacon - Group Creation", () => { .to.emit(staking, "NotifierRewarded") .withArgs( thirdParty.address, - constants.tokenStakingNotificationReward - .mul( + (constants.tokenStakingNotificationReward * + BigInt( params.dkgMaliciousResultNotificationRewardMultiplier, - ) - .div(100), + )) / + 100n, ) }) @@ -2407,8 +2409,8 @@ describe("RandomBeacon - Group Creation", () => { }) context("called by a third party", async () => { - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2460,11 +2462,11 @@ describe("RandomBeacon - Group Creation", () => { .to.emit(staking, "NotifierRewarded") .withArgs( thirdParty.address, - constants.tokenStakingNotificationReward - .mul( + (constants.tokenStakingNotificationReward * + BigInt( params.dkgMaliciousResultNotificationRewardMultiplier, - ) - .div(100), + )) / + 100n, ) }) @@ -2507,7 +2509,7 @@ describe("RandomBeacon - Group Creation", () => { context("with token staking seize call failure", async () => { let tokenStakingFake: Mock - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -2565,8 +2567,8 @@ describe("RandomBeacon - Group Creation", () => { let dkgResultHash: string let dkgResult: DKG.ResultStruct let submitter: SignerWithAddress - let challengeTx: ContractTransaction - let slashingTx: ContractTransaction + let challengeTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2626,9 +2628,11 @@ describe("RandomBeacon - Group Creation", () => { .to.emit(staking, "NotifierRewarded") .withArgs( thirdParty.address, - constants.tokenStakingNotificationReward - .mul(params.dkgMaliciousResultNotificationRewardMultiplier) - .div(100), + (constants.tokenStakingNotificationReward * + BigInt( + params.dkgMaliciousResultNotificationRewardMultiplier, + )) / + 100n, ) }) @@ -2683,7 +2687,7 @@ describe("RandomBeacon - Group Creation", () => { let dkgResult: DKG.ResultStruct const [genesisTx] = await genesis(randomBeacon) - const startBlock = (await genesisTx.wait()).blockNumber + const startBlock = requireResult(await genesisTx.wait()).blockNumber await mineBlocks(constants.offchainDkgTime) @@ -2765,7 +2769,7 @@ describe("RandomBeacon - Group Creation", () => { expectedSubmissionOffset += blocksToMine await expect( - randomBeacon.callStatic.notifyDkgTimeout(), + randomBeacon.notifyDkgTimeout.staticCall(), ).to.be.revertedWith("DKG has not timed out") await randomBeacon.challengeDkgResult(dkgResult) @@ -2813,7 +2817,7 @@ describe("RandomBeacon - Group Creation", () => { }) context("when dkg was triggered", async () => { - let genesisSeed: BigNumber + let genesisSeed: bigint before(async () => { await createSnapshot() @@ -2834,7 +2838,7 @@ describe("RandomBeacon - Group Creation", () => { it("should be the same group as if called the sortition pool directly", async () => { const exectedGroup = await sortitionPool.selectGroup( constants.groupSize, - ethers.utils.hexZeroPad(genesisSeed.toHexString(), 32), + ethers.zeroPadValue(toBeHex(genesisSeed), 32), ) const actualGroup = await randomBeacon.selectGroup() expect(exectedGroup).to.be.deep.equal(actualGroup) @@ -2871,7 +2875,7 @@ async function assertDkgResultCleanData(randomBeacon: { ).to.eq(0) expect(dkgData.submittedResultHash, "unexpected submittedResultHash").to.eq( - ethers.constants.HashZero, + ethers.ZeroHash, ) expect(dkgData.submittedResultBlock, "unexpected submittedResultBlock").to.eq( diff --git a/solidity/random-beacon/test/RandomBeacon.Parameters.test.ts b/solidity/random-beacon/test/RandomBeacon.Parameters.test.ts index c0698afe43..cb72fd0675 100644 --- a/solidity/random-beacon/test/RandomBeacon.Parameters.test.ts +++ b/solidity/random-beacon/test/RandomBeacon.Parameters.test.ts @@ -5,9 +5,9 @@ import { expect } from "chai" import { randomBeaconDeployment, params } from "./fixtures" -import type { ContractTransaction, Signer } from "ethers" +import type { ContractTransactionResponse, Signer } from "ethers" import type { RandomBeaconStub, RandomBeaconGovernance } from "../typechain" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" const { createSnapshot, restoreSnapshot } = helpers.snapshot @@ -62,7 +62,7 @@ describe("RandomBeacon - Parameters", () => { }) context("when the caller is the governance", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -129,7 +129,7 @@ describe("RandomBeacon - Parameters", () => { }) context("when the caller is the governance", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -207,7 +207,7 @@ describe("RandomBeacon - Parameters", () => { }) context("when the caller is the governance", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -360,7 +360,7 @@ describe("RandomBeacon - Parameters", () => { }) context("when the caller is the governance", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -444,7 +444,7 @@ describe("RandomBeacon - Parameters", () => { }) context("when the caller is the governance", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -520,7 +520,7 @@ describe("RandomBeacon - Parameters", () => { context("when the caller is the governance", () => { context("when authorizing a contract", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -549,7 +549,7 @@ describe("RandomBeacon - Parameters", () => { }) context("when deauthorizing the contract", async () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() diff --git a/solidity/random-beacon/test/RandomBeacon.Relay.test.ts b/solidity/random-beacon/test/RandomBeacon.Relay.test.ts index c4e198853e..0406e72437 100644 --- a/solidity/random-beacon/test/RandomBeacon.Relay.test.ts +++ b/solidity/random-beacon/test/RandomBeacon.Relay.test.ts @@ -3,7 +3,6 @@ import { ethers, helpers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" -import { BigNumber } from "ethers" import blsData from "./data/bls" import { @@ -32,19 +31,19 @@ import type { RandomBeaconGovernance, } from "../typechain" import type { Address } from "hardhat-deploy/types" -import type { ContractTransaction, BigNumberish } from "ethers" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { ContractTransactionResponse, BigNumberish } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" const { mineBlocks, mineBlocksTo } = helpers.time const { to1e18 } = helpers.number -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress const { createSnapshot, restoreSnapshot } = helpers.snapshot const { provider } = ethers // FIXME: As a workaround for a bug https://github.com/dethcrypto/TypeChain/issues/601 // we declare a new type instead of using `RandomBeaconStub & RandomBeacon` intersection. type RandomBeaconTest = RandomBeacon & { - dkgLockState: () => Promise + dkgLockState: () => Promise } async function fixture() { @@ -140,7 +139,7 @@ describe("RandomBeacon - Relay", () => { }) context("when there is no other relay entry in progress", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -280,8 +279,8 @@ describe("RandomBeacon - Relay", () => { context("when relay entry has not timed out", () => { context("when entry is valid", () => { context("when result is submitted before the soft timeout", () => { - let tx: ContractTransaction - let initialSubmitterBalance: BigNumber + let tx: ContractTransactionResponse + let initialSubmitterBalance: bigint before(async () => { await createSnapshot() @@ -322,10 +321,10 @@ describe("RandomBeacon - Relay", () => { const postNotifierBalance = await provider.getBalance( submitter.address, ) - const diff = postNotifierBalance.sub(initialSubmitterBalance) + const diff = postNotifierBalance - initialSubmitterBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("2000000", "gwei"), // 0,002 ETH + ethers.parseUnits("2000000", "gwei"), // 0,002 ETH ) }) }) @@ -350,7 +349,7 @@ describe("RandomBeacon - Relay", () => { }) context("when DKG is awaiting a seed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -412,8 +411,8 @@ describe("RandomBeacon - Relay", () => { context("when the input params are valid", () => { context("when result is submitted before the soft timeout", () => { - let tx: ContractTransaction - let initialSubmitterBalance: BigNumber + let tx: ContractTransactionResponse + let initialSubmitterBalance: bigint before(async () => { await createSnapshot() @@ -459,24 +458,24 @@ describe("RandomBeacon - Relay", () => { const postNotifierBalance = await provider.getBalance( submitter.address, ) - const diff = postNotifierBalance.sub(initialSubmitterBalance) + const diff = postNotifierBalance - initialSubmitterBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1000000", "gwei"), // 0,001 ETH + ethers.parseUnits("1000000", "gwei"), // 0,001 ETH ) }) }) context("when result is submitted after the soft timeout", () => { - let initialSubmitterBalance: BigNumber + let initialSubmitterBalance: bigint // `relayEntrySubmissionFailureSlashingAmount = 1000e18`. // 75% of the soft timeout period elapsed so we expect // `750e18` to be slashed. const slashingAmount = to1e18(750) - let submissionTx: ContractTransaction - let slashingTx: ContractTransaction + let submissionTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -550,10 +549,10 @@ describe("RandomBeacon - Relay", () => { const postNotifierBalance = await provider.getBalance( submitter.address, ) - const diff = postNotifierBalance.sub(initialSubmitterBalance) + const diff = postNotifierBalance - initialSubmitterBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1000000", "gwei"), // 0,001 ETH + ethers.parseUnits("1000000", "gwei"), // 0,001 ETH ) }) }) @@ -644,8 +643,8 @@ describe("RandomBeacon - Relay", () => { context( "when other active groups exist after timeout is reported", () => { - let reportTx: ContractTransaction - let slashingTx: ContractTransaction + let reportTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -671,10 +670,12 @@ describe("RandomBeacon - Relay", () => { .to.emit(staking, "NotifierRewarded") .withArgs( notifier.address, - constants.tokenStakingNotificationReward - .mul(params.relayEntryTimeoutNotificationRewardMultiplier) - .div(100) - .mul(membersIDs.length), + ((constants.tokenStakingNotificationReward * + BigInt( + params.relayEntryTimeoutNotificationRewardMultiplier, + )) / + 100n) * + BigInt(membersIDs.length), ) }) @@ -738,7 +739,7 @@ describe("RandomBeacon - Relay", () => { context( "when a group that was supposed to submit a relay request is terminated and another group expires", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -768,7 +769,7 @@ describe("RandomBeacon - Relay", () => { const secondGroupLifetime = await groupLifetimeOf(1) // Expire second group - await mineBlocksTo(secondGroupLifetime.toNumber() + 1) + await mineBlocksTo(Number(secondGroupLifetime) + 1) tx = await randomBeacon.reportRelayEntryTimeout(membersIDs) }) @@ -792,8 +793,8 @@ describe("RandomBeacon - Relay", () => { ) context("when no active groups exist after timeout is reported", () => { - let reportTx: ContractTransaction - let slashingTx: ContractTransaction + let reportTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -814,10 +815,10 @@ describe("RandomBeacon - Relay", () => { .to.emit(staking, "NotifierRewarded") .withArgs( notifier.address, - constants.tokenStakingNotificationReward - .mul(params.relayEntryTimeoutNotificationRewardMultiplier) - .div(100) - .mul(membersIDs.length), + ((constants.tokenStakingNotificationReward * + BigInt(params.relayEntryTimeoutNotificationRewardMultiplier)) / + 100n) * + BigInt(membersIDs.length), ) }) @@ -875,7 +876,7 @@ describe("RandomBeacon - Relay", () => { context( "when no active groups exist after timeout is reported and DKG is awaiting seed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -907,7 +908,7 @@ describe("RandomBeacon - Relay", () => { context("when token staking seize call fails", async () => { let tokenStakingFake: Mock - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -970,8 +971,8 @@ describe("RandomBeacon - Relay", () => { context("when a group is active", () => { context("when provided signature is valid", () => { - let reportTx: ContractTransaction - let slashingTx: ContractTransaction + let reportTx: ContractTransactionResponse + let slashingTx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1000,10 +1001,12 @@ describe("RandomBeacon - Relay", () => { .to.emit(staking, "NotifierRewarded") .withArgs( notifier.address, - constants.tokenStakingNotificationReward - .mul(params.unauthorizedSigningNotificationRewardMultiplier) - .div(100) - .mul(membersIDs.length), + ((constants.tokenStakingNotificationReward * + BigInt( + params.unauthorizedSigningNotificationRewardMultiplier, + )) / + 100n) * + BigInt(membersIDs.length), ) }) @@ -1042,7 +1045,7 @@ describe("RandomBeacon - Relay", () => { context("when token staking seize call fails", async () => { let tokenStakingFake: Mock - let tx: Promise + let tx: Promise before(async () => { await createSnapshot() @@ -1158,8 +1161,8 @@ describe("RandomBeacon - Relay", () => { // We exceeded the soft timeout by `1` // slashing amount: 1 * 1000e18 / 100 = 10e18 expect( - await relayStub.callStatic.calculateSlashingAmount(), - ).to.be.equal(BigNumber.from("10000000000000000000")) + await relayStub.calculateSlashingAmount.staticCall(), + ).to.be.equal(BigInt("10000000000000000000")) }) }) @@ -1174,8 +1177,8 @@ describe("RandomBeacon - Relay", () => { // We exceeded the soft timeout by `100` // slashing amount: 100 * 1000e18 / 100 = 1000e18 expect( - await relayStub.callStatic.calculateSlashingAmount(), - ).to.be.equal(BigNumber.from("1000000000000000000000")) + await relayStub.calculateSlashingAmount.staticCall(), + ).to.be.equal(BigInt("1000000000000000000000")) }) }, ) @@ -1192,8 +1195,8 @@ describe("RandomBeacon - Relay", () => { // hard timeout. In that case the maximum value (100%) of the slashing // amount should be returned. expect( - await relayStub.callStatic.calculateSlashingAmount(), - ).to.be.equal(BigNumber.from("1000000000000000000000")) + await relayStub.calculateSlashingAmount.staticCall(), + ).to.be.equal(BigInt("1000000000000000000000")) }) }, ) @@ -1242,9 +1245,9 @@ describe("RandomBeacon - Relay", () => { signingMemberIndices: number[], ) => number[], ) => { - let tx: ContractTransaction - let initialNonce: BigNumber - let initialNotifierBalance: BigNumber + let tx: ContractTransactionResponse + let initialNonce: bigint + let initialNotifierBalance: bigint let claimSender: SignerWithAddress before(async () => { @@ -1292,7 +1295,7 @@ describe("RandomBeacon - Relay", () => { it("should increment inactivity claim nonce for the group", async () => { expect( await randomBeacon.inactivityClaimNonce(groupId), - ).to.be.equal(initialNonce.add(1)) + ).to.be.equal(initialNonce + 1n) }) it("should emit InactivityClaimed event", async () => { @@ -1300,7 +1303,7 @@ describe("RandomBeacon - Relay", () => { .to.emit(randomBeacon, "InactivityClaimed") .withArgs( groupId, - initialNonce.toNumber(), + Number(initialNonce), claimSender.address, ) }) @@ -1322,12 +1325,10 @@ describe("RandomBeacon - Relay", () => { const postNotifierBalance = await provider.getBalance( await claimSender.getAddress(), ) - const diff = postNotifierBalance.sub( - initialNotifierBalance, - ) + const diff = postNotifierBalance - initialNotifierBalance expect(diff).to.be.gt(0) expect(diff).to.be.lt( - ethers.utils.parseUnits("1000000", "gwei"), // 0,001 ETH + ethers.parseUnits("1000000", "gwei"), // 0,001 ETH ) }) } @@ -2024,16 +2025,16 @@ describe("RandomBeacon - Relay", () => { }) }) - async function groupLifetimeOf(groupID: BigNumberish): Promise { - const groupData = await randomBeacon.callStatic["getGroup(uint64)"](groupID) + async function groupLifetimeOf(groupID: BigNumberish): Promise { + const groupData = await randomBeacon["getGroup(uint64)"].staticCall(groupID) const { groupLifetime } = await randomBeacon.groupCreationParameters() - return groupData.registrationBlockNumber.add(groupLifetime) + return groupData.registrationBlockNumber + groupLifetime } async function isGroupTerminated(groupID: BigNumberish): Promise { - const groupData = await randomBeacon.callStatic["getGroup(uint64)"](groupID) + const groupData = await randomBeacon["getGroup(uint64)"].staticCall(groupID) return groupData.terminated === true } diff --git a/solidity/random-beacon/test/RandomBeacon.Rewards.test.ts b/solidity/random-beacon/test/RandomBeacon.Rewards.test.ts index b290c16172..a7003d5c3d 100644 --- a/solidity/random-beacon/test/RandomBeacon.Rewards.test.ts +++ b/solidity/random-beacon/test/RandomBeacon.Rewards.test.ts @@ -7,7 +7,7 @@ import { registerOperators } from "./utils/operators" import { createGroup } from "./utils/groups" import { signOperatorInactivityClaim } from "./utils/inactivity" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { Operator } from "./utils/operators" import type { RandomBeacon, @@ -101,7 +101,7 @@ describe("RandomBeacon - Rewards", () => { await t.connect(deployer).mint(deployer.address, rewardAmount) await t .connect(deployer) - .approveAndCall(sortitionPool.address, rewardAmount, []) + .approveAndCall(await sortitionPool.getAddress(), rewardAmount, "0x") }) after(async () => { @@ -118,7 +118,7 @@ describe("RandomBeacon - Rewards", () => { const balanceBefore = await t.balanceOf(beneficiary) const tx = await randomBeacon.withdrawRewards(stakingProvider) const balanceAfter = await t.balanceOf(beneficiary) - const received = balanceAfter.sub(balanceBefore) + const received = balanceAfter - balanceBefore await expect(tx) .to.emit(randomBeacon, "RewardsWithdrawn") @@ -152,7 +152,7 @@ describe("RandomBeacon - Rewards", () => { await t.connect(deployer).mint(deployer.address, rewardAmount) await t .connect(deployer) - .approveAndCall(sortitionPool.address, rewardAmount, []) + .approveAndCall(await sortitionPool.getAddress(), rewardAmount, "0x") }) after(async () => { @@ -167,7 +167,7 @@ describe("RandomBeacon - Rewards", () => { await randomBeacon.withdrawRewards(stakingProvider) const balanceAfter = await t.balanceOf(beneficiary) - expect(availableAmount).to.equal(balanceAfter.sub(balanceBefore)) + expect(availableAmount).to.equal(balanceAfter - balanceBefore) availableAmount = await randomBeacon.availableRewards(stakingProvider) expect(availableAmount).to.equal(0) @@ -221,7 +221,7 @@ describe("RandomBeacon - Rewards", () => { await t.connect(deployer).mint(deployer.address, rewardAmount) await t .connect(deployer) - .approveAndCall(sortitionPool.address, rewardAmount, []) + .approveAndCall(await sortitionPool.getAddress(), rewardAmount, "0x") }) after(async () => { diff --git a/solidity/random-beacon/test/RandomBeaconChaosnet.test.ts b/solidity/random-beacon/test/RandomBeaconChaosnet.test.ts index 037a836ae1..5aac4f8ada 100644 --- a/solidity/random-beacon/test/RandomBeaconChaosnet.test.ts +++ b/solidity/random-beacon/test/RandomBeaconChaosnet.test.ts @@ -1,10 +1,9 @@ import { ethers, helpers } from "hardhat" import { expect } from "chai" -import { BigNumber } from "ethers" -import type { ContractTransaction } from "ethers" +import type { ContractTransactionResponse } from "ethers" import type { RandomBeaconChaosnet, CallbackContractStub } from "../typechain" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" const { createSnapshot, restoreSnapshot } = helpers.snapshot @@ -46,7 +45,7 @@ describe("RandomBeaconChaosnet", () => { context("when called by the owner", () => { context("when requester authorization set to true", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -74,7 +73,7 @@ describe("RandomBeaconChaosnet", () => { }) context("when requester authorization set to false", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -114,7 +113,7 @@ describe("RandomBeaconChaosnet", () => { await expect( randomBeaconChaosnet .connect(thirdParty) - .requestRelayEntry(callbackContract.address), + .requestRelayEntry(await callbackContract.getAddress()), ).to.be.revertedWith("Requester must be authorized") }) }) @@ -130,7 +129,7 @@ describe("RandomBeaconChaosnet", () => { await randomBeaconChaosnet .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) }) after(async () => { @@ -141,7 +140,7 @@ describe("RandomBeaconChaosnet", () => { expect(await callbackContract.lastEntry()).to.equal( // The entry is keccak-256 of the initial value stored in // the RandomBeaconChaosnet contract - BigNumber.from( + BigInt( "86322480231844907215266847458792959757192550318770676212332984" + "332154459033029", ), @@ -161,11 +160,11 @@ describe("RandomBeaconChaosnet", () => { // by requesting a relay entry twice. await randomBeaconChaosnet .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) await randomBeaconChaosnet .connect(requester) - .requestRelayEntry(callbackContract.address) + .requestRelayEntry(await callbackContract.getAddress()) }) after(async () => { @@ -176,7 +175,7 @@ describe("RandomBeaconChaosnet", () => { // The entry is keccak-256 calculated twice on the initial value // stored in the RandomBeaconChaosnet contract expect(await callbackContract.lastEntry()).to.equal( - BigNumber.from( + BigInt( "45055825411044151981109535788320043556123542984485670123474642" + "322436340913380", ), diff --git a/solidity/random-beacon/test/RandomBeaconGovernance.test.ts b/solidity/random-beacon/test/RandomBeaconGovernance.test.ts index 9fd4f661af..f485aa9a95 100644 --- a/solidity/random-beacon/test/RandomBeaconGovernance.test.ts +++ b/solidity/random-beacon/test/RandomBeaconGovernance.test.ts @@ -2,10 +2,11 @@ import { ethers, helpers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" +import requireResult from "./helpers/chain" import { randomBeaconDeployment, params } from "./fixtures" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { ContractTransaction, Signer } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { ContractTransactionResponse, Signer } from "ethers" import type { RandomBeacon, RandomBeaconGovernance, @@ -16,7 +17,7 @@ const { createSnapshot, restoreSnapshot } = helpers.snapshot const governanceDelay = 604800 // 1 week -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress const fixture = async () => { const { governance } = await helpers.signers.getNamedSigners() @@ -30,9 +31,6 @@ const fixture = async () => { return { governance, randomBeaconGovernance, randomBeacon } } -const minedBlockTimestamp = async (tx: ContractTransaction): Promise => - (await ethers.provider.getBlock((await tx.wait()).blockNumber)).timestamp - describe("RandomBeaconGovernance", () => { let governance: Signer let thirdParty: SignerWithAddress @@ -67,7 +65,7 @@ describe("RandomBeaconGovernance", () => { context("when governance delay is 0", () => { it("should revert", async () => { await expect( - RandomBeaconGovernance.deploy(randomBeacon.address, 0), + RandomBeaconGovernance.deploy(await randomBeacon.getAddress(), 0), ).to.be.revertedWith("No governance delay") }) }) @@ -85,7 +83,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -112,7 +110,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit GovernanceDelayUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(randomBeaconGovernance, "GovernanceDelayUpdateStarted") .withArgs(1337, blockTimestamp) @@ -168,7 +170,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -223,7 +225,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -244,9 +246,7 @@ describe("RandomBeaconGovernance", () => { await expect( randomBeaconGovernance .connect(governance) - .beginRandomBeaconGovernanceTransfer( - ethers.constants.AddressZero, - ), + .beginRandomBeaconGovernanceTransfer(ethers.ZeroAddress), ).to.be.revertedWith( "New random beacon governance address cannot be zero", ) @@ -255,7 +255,7 @@ describe("RandomBeaconGovernance", () => { it("should not transfer the governance", async () => { expect(await randomBeacon.governance()).to.be.equal( - randomBeaconGovernance.address, + await randomBeaconGovernance.getAddress(), ) }) @@ -266,7 +266,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit RandomBeaconGovernanceTransferStarted", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -330,7 +334,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -415,7 +419,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -442,7 +446,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the RelayEntrySoftTimeoutUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(randomBeaconGovernance, "RelayEntrySoftTimeoutUpdateStarted") .withArgs(1, blockTimestamp) @@ -494,7 +502,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -547,7 +555,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -574,7 +582,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the RelayEntryHardTimeoutUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(randomBeaconGovernance, "RelayEntryHardTimeoutUpdateStarted") .withArgs(123, blockTimestamp) @@ -626,7 +638,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -730,7 +742,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -756,7 +768,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the CallbackGasLimitUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(randomBeaconGovernance, "CallbackGasLimitUpdateStarted") .withArgs(123, blockTimestamp) @@ -808,7 +824,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -887,7 +903,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -916,7 +932,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the GroupCreationFrequencyUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -971,7 +991,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1036,7 +1056,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1062,7 +1082,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the GroupLifetimeUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(randomBeaconGovernance, "GroupLifetimeUpdateStarted") .withArgs(newGroupLifetime, blockTimestamp) @@ -1116,7 +1140,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1195,7 +1219,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1224,7 +1248,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the DkgResultChallengePeriodLengthUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -1279,7 +1307,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1335,7 +1363,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1364,7 +1392,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the DkgResultChallengeExtraGasUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -1419,7 +1451,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1502,7 +1534,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1531,7 +1563,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the DkgResultSubmissionTimeoutUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -1587,7 +1623,7 @@ describe("RandomBeaconGovernance", () => { "when the update process is initialized and governance delay passed", () => { const newValue = 234 - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1675,7 +1711,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1704,7 +1740,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the DkgSubmitterPrecedencePeriodLengthUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -1759,7 +1799,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1815,7 +1855,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1844,7 +1884,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the RelayEntrySubmissionFailureSlashingAmountUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -1899,7 +1943,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1955,7 +1999,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -1984,7 +2028,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the UnauthorizedSigningSlashingAmountUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -2039,7 +2087,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2095,7 +2143,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2124,7 +2172,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the MaliciousDkgResultSlashingAmountUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -2179,7 +2231,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2235,7 +2287,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2264,7 +2316,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the SortitionPoolRewardsBanDurationUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -2319,7 +2375,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2385,7 +2441,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner and value is correct", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2414,7 +2470,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the UnauthorizedSigningNotificationRewardMultiplierUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -2469,7 +2529,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2537,7 +2597,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner and value is correct", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2566,7 +2626,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the RelayEntryTimeoutNotificationRewardMultiplierUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -2621,7 +2685,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2678,7 +2742,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2705,7 +2769,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the MinimumAuthorizationUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit(randomBeaconGovernance, "MinimumAuthorizationUpdateStarted") .withArgs(123, blockTimestamp) @@ -2757,7 +2825,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2808,7 +2876,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2837,7 +2905,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the AuthorizationDecreaseDelayUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -2890,7 +2962,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2946,7 +3018,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -2975,7 +3047,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the AuthorizationDecreaseChangePeriodUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -3028,7 +3104,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3139,7 +3215,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner and value is correct", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3169,7 +3245,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the DkgMaliciousResultNotificationRewardMultiplierUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -3224,7 +3304,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3282,7 +3362,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3310,7 +3390,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit DkgResultSubmissionGasUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -3365,7 +3449,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3417,7 +3501,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3446,7 +3530,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the DkgResultApprovalGasOffsetUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -3501,7 +3589,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3557,7 +3645,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3586,7 +3674,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the NotifyOperatorInactivityGasOffsetUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -3641,7 +3733,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3697,7 +3789,7 @@ describe("RandomBeaconGovernance", () => { }) context("when the caller is the owner", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() @@ -3726,7 +3818,11 @@ describe("RandomBeaconGovernance", () => { }) it("should emit the RelayEntrySubmissionGasOffsetUpdateStarted event", async () => { - const blockTimestamp = await minedBlockTimestamp(tx) + const blockTimestamp = requireResult( + await ethers.provider.getBlock( + requireResult(await tx.wait()).blockNumber, + ), + ).timestamp await expect(tx) .to.emit( randomBeaconGovernance, @@ -3781,7 +3877,7 @@ describe("RandomBeaconGovernance", () => { context( "when the update process is initialized and governance delay passed", () => { - let tx: ContractTransaction + let tx: ContractTransactionResponse before(async () => { await createSnapshot() diff --git a/solidity/random-beacon/test/Reimbursable.test.ts b/solidity/random-beacon/test/Reimbursable.test.ts index 32b1330383..4486e094c1 100644 --- a/solidity/random-beacon/test/Reimbursable.test.ts +++ b/solidity/random-beacon/test/Reimbursable.test.ts @@ -1,7 +1,7 @@ import { ethers, helpers } from "hardhat" import { expect } from "chai" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { ReimbursableImplStub } from "../typechain" describe("Reimbursable", () => { diff --git a/solidity/random-beacon/test/ReimbursementPool.test.ts b/solidity/random-beacon/test/ReimbursementPool.test.ts index a2a5a99164..577537eb10 100644 --- a/solidity/random-beacon/test/ReimbursementPool.test.ts +++ b/solidity/random-beacon/test/ReimbursementPool.test.ts @@ -3,13 +3,14 @@ import { ethers, helpers, deployments } from "hardhat" import { expect } from "chai" +import requireResult from "./helpers/chain" import { params } from "./fixtures" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { ContractTransaction } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { ContractTransactionResponse } from "ethers" import type { ReimbursementPool } from "../typechain" -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress const { createSnapshot, restoreSnapshot } = helpers.snapshot const { provider } = ethers @@ -35,44 +36,40 @@ describe("ReimbursementPool", () => { context("when a third party funds a reimbursment pool", () => { it("should send ETH to the Reimbursment Pool", async () => { let reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, + await reimbursementPool.getAddress(), ) expect(reimbursementPoolBalance).to.be.equal(0) await thirdParty.sendTransaction({ - to: reimbursementPool.address, - value: ethers.utils.parseEther("1.0"), // Send 1.0 ETH + to: await reimbursementPool.getAddress(), + value: ethers.parseEther("1.0"), }) reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, + await reimbursementPool.getAddress(), ) - expect(reimbursementPoolBalance).to.be.equal( - ethers.utils.parseEther("1.0"), - ) + expect(reimbursementPoolBalance).to.be.equal(ethers.parseEther("1.0")) }) }) context("when the owner funds a reimbursment pool", () => { it("should send ETH to the Reimbursment Pool", async () => { let reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, + await reimbursementPool.getAddress(), ) expect(reimbursementPoolBalance).to.be.equal(0) await owner.sendTransaction({ - to: reimbursementPool.address, - value: ethers.utils.parseEther("1.0"), // Send 1.0 ETH + to: await reimbursementPool.getAddress(), + value: ethers.parseEther("1.0"), }) reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, + await reimbursementPool.getAddress(), ) - expect(reimbursementPoolBalance).to.be.equal( - ethers.utils.parseEther("1.0"), - ) + expect(reimbursementPoolBalance).to.be.equal(ethers.parseEther("1.0")) }) }) }) @@ -80,8 +77,8 @@ describe("ReimbursementPool", () => { describe("withdrawAll", () => { beforeEach(async () => { await thirdParty.sendTransaction({ - to: reimbursementPool.address, - value: ethers.utils.parseEther("10.0"), // Send 10.0 ETH + to: await reimbursementPool.getAddress(), + value: ethers.parseEther("10.0"), }) }) @@ -98,11 +95,9 @@ describe("ReimbursementPool", () => { context("when widhrawing all the funds as an owner", () => { it("should withdraw entire ETH balance", async () => { let reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, - ) - expect(reimbursementPoolBalance).to.be.equal( - ethers.utils.parseEther("10.0"), + await reimbursementPool.getAddress(), ) + expect(reimbursementPoolBalance).to.be.equal(ethers.parseEther("10.0")) const thirdPartyBalanceBefore = await provider.getBalance( thirdParty.address, @@ -111,19 +106,16 @@ describe("ReimbursementPool", () => { await reimbursementPool.connect(owner).withdrawAll(thirdParty.address) reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, + await reimbursementPool.getAddress(), ) expect(reimbursementPoolBalance).to.be.equal(0) const thirdPartyBalanceAfter = await provider.getBalance( thirdParty.address, ) - const thirdPartyBalanceDiff = thirdPartyBalanceAfter.sub( - thirdPartyBalanceBefore, - ) - expect(thirdPartyBalanceDiff).to.be.equal( - ethers.utils.parseEther("10.0"), - ) + const thirdPartyBalanceDiff = + thirdPartyBalanceAfter - thirdPartyBalanceBefore + expect(thirdPartyBalanceDiff).to.be.equal(ethers.parseEther("10.0")) }) it("should emit FundsWithdrawn event", async () => { @@ -131,7 +123,7 @@ describe("ReimbursementPool", () => { reimbursementPool.connect(owner).withdrawAll(thirdParty.address), ) .to.emit(reimbursementPool, "FundsWithdrawn") - .withArgs(ethers.utils.parseEther("10.0"), thirdParty.address) + .withArgs(ethers.parseEther("10.0"), thirdParty.address) }) }) @@ -149,8 +141,8 @@ describe("ReimbursementPool", () => { await createSnapshot() await thirdParty.sendTransaction({ - to: reimbursementPool.address, - value: ethers.utils.parseEther("10.0"), // Send 10.0 ETH + to: await reimbursementPool.getAddress(), + value: ethers.parseEther("10.0"), }) }) @@ -163,10 +155,7 @@ describe("ReimbursementPool", () => { await expect( reimbursementPool .connect(thirdParty) - .withdraw( - ethers.utils.parseEther("2.0"), - thirdPartyContract.address, - ), + .withdraw(ethers.parseEther("2.0"), thirdPartyContract.address), ).to.be.revertedWith("Ownable: caller is not the owner") }) }) @@ -174,11 +163,9 @@ describe("ReimbursementPool", () => { context("when widhrawing funds as an owner", () => { it("should withdraw ETH balance", async () => { let reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, - ) - expect(reimbursementPoolBalance).to.be.equal( - ethers.utils.parseEther("10.0"), + await reimbursementPool.getAddress(), ) + expect(reimbursementPoolBalance).to.be.equal(ethers.parseEther("10.0")) const thirdPartyBalanceBefore = await provider.getBalance( thirdParty.address, @@ -186,34 +173,29 @@ describe("ReimbursementPool", () => { await reimbursementPool .connect(owner) - .withdraw(ethers.utils.parseEther("2.0"), thirdParty.address) + .withdraw(ethers.parseEther("2.0"), thirdParty.address) reimbursementPoolBalance = await provider.getBalance( - reimbursementPool.address, - ) - expect(reimbursementPoolBalance).to.be.equal( - ethers.utils.parseEther("8.0"), + await reimbursementPool.getAddress(), ) + expect(reimbursementPoolBalance).to.be.equal(ethers.parseEther("8.0")) const thirdPartyBalanceAfter = await provider.getBalance( thirdParty.address, ) - const thirdPartyBalanceDiff = thirdPartyBalanceAfter.sub( - thirdPartyBalanceBefore, - ) - expect(thirdPartyBalanceDiff).to.be.equal( - ethers.utils.parseEther("2.0"), - ) + const thirdPartyBalanceDiff = + thirdPartyBalanceAfter - thirdPartyBalanceBefore + expect(thirdPartyBalanceDiff).to.be.equal(ethers.parseEther("2.0")) }) it("should emit FundsWithdrawn event", async () => { await expect( reimbursementPool .connect(owner) - .withdraw(ethers.utils.parseEther("2.0"), thirdParty.address), + .withdraw(ethers.parseEther("2.0"), thirdParty.address), ) .to.emit(reimbursementPool, "FundsWithdrawn") - .withArgs(ethers.utils.parseEther("2.0"), thirdParty.address) + .withArgs(ethers.parseEther("2.0"), thirdParty.address) }) }) @@ -230,7 +212,7 @@ describe("ReimbursementPool", () => { await expect( reimbursementPool .connect(owner) - .withdraw(ethers.utils.parseEther("42.0"), ZERO_ADDRESS), + .withdraw(ethers.parseEther("42.0"), ZERO_ADDRESS), ).to.be.revertedWith("Insufficient contract balance") }) }) @@ -241,8 +223,8 @@ describe("ReimbursementPool", () => { await createSnapshot() await thirdParty.sendTransaction({ - to: reimbursementPool.address, - value: ethers.utils.parseEther("10.0"), // Send 10.0 ETH + to: await reimbursementPool.getAddress(), + value: ethers.parseEther("10.0"), }) }) @@ -255,7 +237,7 @@ describe("ReimbursementPool", () => { await expect( reimbursementPool .connect(thirdParty) - .refund(ethers.utils.parseEther("2.0"), thirdParty.address), + .refund(ethers.parseEther("2.0"), thirdParty.address), ).to.be.revertedWith("Contract is not authorized for a refund") }) }) @@ -286,14 +268,12 @@ describe("ReimbursementPool", () => { const refundeeBalanceAfter = await provider.getBalance( refundee.address, ) - const refundeeBalanceDiff = refundeeBalanceAfter.sub( - refundeeBalanceBefore, - ) + const refundeeBalanceDiff = + refundeeBalanceAfter - refundeeBalanceBefore // consumed gas: 50k + 40.8k = 90.8k // refund: 90.8k * tx.gasPrice - const expectedRefund = ethers.BigNumber.from(90800).mul( - (await tx.wait()).effectiveGasPrice, - ) + const expectedRefund = + 90800n * requireResult(await tx.wait()).gasPrice expect(refundeeBalanceDiff).to.be.equal(expectedRefund) }) @@ -314,7 +294,7 @@ describe("ReimbursementPool", () => { await reimbursementPool .connect(owner) - .setMaxGasPrice(ethers.utils.parseUnits("1.0", "gwei")) + .setMaxGasPrice(ethers.parseUnits("1.0", "gwei")) const refundeeBalanceBefore = await provider.getBalance( refundee.address, @@ -327,12 +307,11 @@ describe("ReimbursementPool", () => { const refundeeBalanceAfter = await provider.getBalance( refundee.address, ) - const refundeeBalanceDiff = refundeeBalanceAfter.sub( - refundeeBalanceBefore, - ) + const refundeeBalanceDiff = + refundeeBalanceAfter - refundeeBalanceBefore // gas spent + static gas => 50k + 40.8k expect(refundeeBalanceDiff).to.be.eq( - ethers.utils.parseUnits("90800", "gwei"), + ethers.parseUnits("90800", "gwei"), ) }) }) @@ -348,14 +327,14 @@ describe("ReimbursementPool", () => { }) context("when no funds available in the pool", () => { - let tx: Promise + let tx: Promise beforeEach(async () => { await createSnapshot() await reimbursementPool .connect(owner) - .setMaxGasPrice(ethers.utils.parseUnits("1.0", "gwei")) + .setMaxGasPrice(ethers.parseUnits("1.0", "gwei")) await reimbursementPool.connect(owner).withdrawAll(thirdParty.address) @@ -376,10 +355,7 @@ describe("ReimbursementPool", () => { // gas spent + static gas => 50k + 40.8k await expect(tx) .to.emit(reimbursementPool, "SendingEtherFailed") - .withArgs( - ethers.utils.parseUnits("90800", "gwei"), - refundee.address, - ) + .withArgs(ethers.parseUnits("90800", "gwei"), refundee.address) }) }) }) @@ -491,7 +467,7 @@ describe("ReimbursementPool", () => { expect(await reimbursementPool.maxGasPrice()).to.be.equal( params.reimbursementPoolMaxGasPrice, ) - const newMaxGasPrice = ethers.utils.parseUnits("21", "gwei") + const newMaxGasPrice = ethers.parseUnits("21", "gwei") const tx = await reimbursementPool .connect(owner) diff --git a/solidity/random-beacon/test/fixtures/index.ts b/solidity/random-beacon/test/fixtures/index.ts index 76f8483283..04f9276117 100644 --- a/solidity/random-beacon/test/fixtures/index.ts +++ b/solidity/random-beacon/test/fixtures/index.ts @@ -1,7 +1,7 @@ import { ethers, helpers, deployments } from "hardhat" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { Contract } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { BaseContract } from "ethers" import type { SortitionPool, BeaconDkgValidator as DKGValidator, @@ -52,7 +52,7 @@ export const params = { authorizationDecreaseDelay: 403_200, authorizationDecreaseChangePeriod: 403_200, reimbursementPoolStaticGas: 40_800, - reimbursementPoolMaxGasPrice: ethers.utils.parseUnits("500", "gwei"), + reimbursementPoolMaxGasPrice: ethers.parseUnits("500", "gwei"), dkgResultSubmissionGas: 237_650, dkgResultApprovalGasOffset: 41_500, notifyOperatorInactivityGasOffset: 54_500, @@ -60,13 +60,13 @@ export const params = { } export interface DeployedContracts { - [key: string]: Contract + [key: string]: BaseContract } export async function blsDeployment(): Promise { const BLS = await ethers.getContractFactory("BLS") const bls = await BLS.deploy() - await bls.deployed() + await bls.waitForDeployment() const contracts: DeployedContracts = { bls } @@ -92,8 +92,8 @@ export async function randomBeaconDeployment(): Promise { await helpers.contracts.getContract("ReimbursementPool") await deployer.sendTransaction({ - to: reimbursementPool.address, - value: ethers.utils.parseEther("100.0"), // Send 100.0 ETH + to: await reimbursementPool.getAddress(), + value: ethers.parseEther("100.0"), }) const randomBeacon: RandomBeaconStub = @@ -124,7 +124,9 @@ async function updateTokenStakingParams( // initialNotifierTreasury should be configured high enough to execute all the // slashing in test suites. const initialNotifierTreasury = to1e18(9_000_000) // 9MM T - await t.connect(deployer).approve(staking.address, initialNotifierTreasury) + await t + .connect(deployer) + .approve(await staking.getAddress(), initialNotifierTreasury) // Compatibility: Threshold TokenStaking variant may not expose these methods. const stakingAsRecord = staking.connect(deployer) as unknown as Record< @@ -132,10 +134,10 @@ async function updateTokenStakingParams( (...args: unknown[]) => Promise > - if (typeof stakingAsRecord.pushNotificationReward === "function") { + if (staking.interface.getFunction("pushNotificationReward") !== null) { await stakingAsRecord.pushNotificationReward(initialNotifierTreasury) } - if (typeof stakingAsRecord.setNotificationReward === "function") { + if (staking.interface.getFunction("setNotificationReward") !== null) { await stakingAsRecord.setNotificationReward( constants.tokenStakingNotificationReward, ) diff --git a/solidity/random-beacon/test/helpers/chain.ts b/solidity/random-beacon/test/helpers/chain.ts new file mode 100644 index 0000000000..4c71d8e6e4 --- /dev/null +++ b/solidity/random-beacon/test/helpers/chain.ts @@ -0,0 +1,5 @@ +/** Fail explicitly when a local test's block or mined receipt is unavailable. */ +export default function requireResult(result: T | null): T { + if (result === null) throw new Error("Expected a non-null chain response") + return result +} diff --git a/solidity/random-beacon/test/helpers/mock.test.ts b/solidity/random-beacon/test/helpers/mock.test.ts index b56c702583..4066c9d8d5 100644 --- a/solidity/random-beacon/test/helpers/mock.test.ts +++ b/solidity/random-beacon/test/helpers/mock.test.ts @@ -1,6 +1,7 @@ import { ethers } from "hardhat" import { expect } from "chai" +import requireResult from "./chain" import { createMock, expectCalledWith } from "./mock" import type { Mock } from "./mock" @@ -15,7 +16,7 @@ describe("MockContract", () => { const factory = await ethers.getContractFactory("MockTargetConsumer") consumer = (await factory.deploy(target.address)) as MockTargetConsumer - await consumer.deployed() + await consumer.waitForDeployment() }) describe("view functions reached by STATICCALL", () => { @@ -92,9 +93,9 @@ describe("MockContract", () => { it("reverts every call to the function", async () => { await target.doThing.reverts("nope") - await expect( - consumer.doThing(ethers.constants.AddressZero, 1), - ).to.be.revertedWith("nope") + await expect(consumer.doThing(ethers.ZeroAddress, 1)).to.be.revertedWith( + "nope", + ) }) it("reverts only the matching arguments", async () => { @@ -150,7 +151,7 @@ describe("MockContract", () => { it("counts each function separately", async () => { await target.doThing.returns(true) - await consumer.doThing(ethers.constants.AddressZero, 1) + await consumer.doThing(ethers.ZeroAddress, 1) await consumer.noReturn(1) expect(await target.doThing.callCount()).to.equal(1) @@ -161,13 +162,13 @@ describe("MockContract", () => { describe("reset", () => { it("clears recorded calls and configured responses for one function", async () => { await target.doThing.returns(true) - await consumer.doThing(ethers.constants.AddressZero, 1) + await consumer.doThing(ethers.ZeroAddress, 1) await target.doThing.reset() expect(await target.doThing.callCount()).to.equal(0) // The configured `true` is gone, so the call answers with empty data. - await consumer.doThing(ethers.constants.AddressZero, 1) + await consumer.doThing(ethers.ZeroAddress, 1) expect(await consumer.lastResult()).to.equal(false) }) @@ -215,10 +216,10 @@ describe("MockContract", () => { // `msg.sender == someContract`. const factory = await ethers.getContractFactory("MockTargetConsumer") const other = await factory.deploy(target.address) - await other.deployed() + await other.waitForDeployment() const tx = await other.connect(target.wallet).noReturn(1) - const receipt = await tx.wait() + const receipt = requireResult(await tx.wait()) expect(receipt.from).to.equal(target.address) }) @@ -226,9 +227,7 @@ describe("MockContract", () => { describe("address option", () => { it("deploys at a requested address", async () => { - const address = ethers.utils.getAddress( - `0x${"ab".repeat(20)}`.toLowerCase(), - ) + const address = ethers.getAddress(`0x${"ab".repeat(20)}`.toLowerCase()) const pinned = await createMock("IMockTarget", { address }) @@ -237,7 +236,7 @@ describe("MockContract", () => { const factory = await ethers.getContractFactory("MockTargetConsumer") const pinnedConsumer = await factory.deploy(address) - await pinnedConsumer.deployed() + await pinnedConsumer.waitForDeployment() expect(await pinnedConsumer.readValueThroughStaticCall(1)).to.equal(7) }) @@ -250,7 +249,7 @@ describe("MockContract", () => { // real ecdsaWalletRegistry and relay. `hardhat_setCode` replaces the code // and leaves the storage, so a mock keeping its state at slots 0, 1, 2... // would read that leftover as its own. - const address = ethers.utils.getAddress(`0x${"cd".repeat(20)}`) + const address = ethers.getAddress(`0x${"cd".repeat(20)}`) const garbage = "0xdeadbeef00000000000000000000000000000000000000000000000000000001" @@ -258,7 +257,7 @@ describe("MockContract", () => { Array.from({ length: 8 }, (_, slot) => ethers.provider.send("hardhat_setStorageAt", [ address, - ethers.utils.hexValue(slot), + ethers.toQuantity(slot), garbage, ]), ), @@ -272,7 +271,7 @@ describe("MockContract", () => { const factory = await ethers.getContractFactory("MockTargetConsumer") const pinnedConsumer = await factory.deploy(address) - await pinnedConsumer.deployed() + await pinnedConsumer.waitForDeployment() expect(await pinnedConsumer.readValueThroughStaticCall(1)).to.equal(7) }) diff --git a/solidity/random-beacon/test/helpers/mock.ts b/solidity/random-beacon/test/helpers/mock.ts index 6efa167eff..2bd11a450b 100644 --- a/solidity/random-beacon/test/helpers/mock.ts +++ b/solidity/random-beacon/test/helpers/mock.ts @@ -7,10 +7,18 @@ /* eslint-disable no-underscore-dangle */ import { ethers, artifacts } from "hardhat" import { expect } from "chai" -import { BigNumber } from "ethers" -import type { BigNumberish, Contract, Signer } from "ethers" -import type { FunctionFragment, Interface, ParamType } from "ethers/lib/utils" +import requireResult from "./chain" + +import type { + BaseContract, + BigNumberish, + Signer, + FunctionFragment, + Interface, + ParamType, +} from "ethers" +import type { MockContract } from "../../typechain" /** * Programmable contract mock, replacing `@defi-wonderland/smock`. @@ -57,7 +65,8 @@ import type { FunctionFragment, Interface, ParamType } from "ethers/lib/utils" * the machine happens to be. */ async function withoutAdvancingTime(write: () => Promise): Promise { - const { timestamp } = await ethers.provider.getBlock("latest") + const block = requireResult(await ethers.provider.getBlock("latest")) + const { timestamp } = block await ethers.provider.send("evm_setNextBlockTimestamp", [timestamp]) return write() } @@ -67,7 +76,7 @@ export interface MockCall { /** Decoded arguments, in declaration order. */ args: unknown[] /** `msg.value` the call carried, as smock's `getCall(n).value` did. */ - value: BigNumber + value: bigint } /** Configuration and inspection handle for one function of a mock. */ @@ -95,8 +104,10 @@ export interface MockedFunction { getCalls(): Promise } -export type Mock = { - [K in keyof T]: T[K] extends (...args: never[]) => unknown +export type Mock = { + [K in keyof Omit]: T[K] extends ( + ...args: never[] + ) => unknown ? T[K] & MockedFunction : T[K] } & { @@ -104,14 +115,14 @@ export type Mock = { /** Signer that sends from the mock's own address, as smock's `fake.wallet` did. */ wallet: Signer /** Underlying deployed `MockContract`, for anything this helper does not wrap. */ - mockContract: Contract + mockContract: MockContract /** * The mocked interface bound to `signer`, as smock's `FakeContract.connect` * was. smock's fake extended `ethers.Contract` and inherited this; the proxy * here resolves only the mocked ABI and the keys above, so without it * `mock.connect(someone)` is `undefined`. */ - connect(signer: Signer): Contract + connect(signer: Signer): T /** Drops all configured responses and all recorded calls. */ reset(): Promise /** @@ -125,11 +136,17 @@ export type Mock = { } /** Selectors of `MockContract`'s own administrative entry points. */ +function functionFragments(iface: Interface): FunctionFragment[] { + const fragments: FunctionFragment[] = [] + iface.forEachFunction((fragment) => fragments.push(fragment)) + return fragments +} + function adminSelectors(mockInterface: Interface): Set { return new Set( - Object.keys(mockInterface.functions) - .filter((signature) => signature.startsWith("__mock__")) - .map((signature) => mockInterface.getSighash(signature)), + functionFragments(mockInterface) + .filter((fragment) => fragment.name.startsWith("__mock__")) + .map((fragment) => fragment.selector), ) } @@ -147,8 +164,9 @@ function assertNoSelectorCollision( ): void { const reserved = adminSelectors(mockInterface) - Object.keys(target.functions).forEach((signature) => { - const selector = target.getSighash(signature) + functionFragments(target).forEach((fragment) => { + const signature = fragment.format() + const { selector } = fragment if (reserved.has(selector)) { throw new Error( `${targetName}.${signature} has selector ${selector}, which collides ` + @@ -162,7 +180,7 @@ function assertNoSelectorCollision( function fragmentsByName(target: Interface): Map { const byName = new Map() - Object.values(target.functions).forEach((fragment) => { + functionFragments(target).forEach((fragment) => { const existing = byName.get(fragment.name) if (existing) { existing.push(fragment) @@ -202,7 +220,7 @@ function resolveFragment( * layout. */ function zeroValueFor(type: ParamType): unknown { - if (type.baseType === "array") { + if (type.isArray()) { if (type.arrayLength === -1) { return [] } @@ -211,12 +229,12 @@ function zeroValueFor(type: ParamType): unknown { ) } - if (type.baseType === "tuple") { + if (type.isTuple()) { return type.components.map((component) => zeroValueFor(component)) } if (type.baseType === "address") { - return ethers.constants.AddressZero + return ethers.ZeroAddress } if (type.baseType === "bool") { @@ -249,7 +267,10 @@ function zeroValueFor(type: ParamType): unknown { * those positionally, so they are mapped back by output name. A single-output * function is different: an object there is a struct, and the coder handles it. */ -function toPositional(outputs: ParamType[], value: unknown): unknown[] { +function toPositional( + outputs: readonly ParamType[], + value: unknown, +): unknown[] { if (outputs.length === 1) { return [value] } @@ -273,7 +294,7 @@ function encodeReturn(fragment: FunctionFragment, value: unknown): string { return "0x" } - return ethers.utils.defaultAbiCoder.encode( + return ethers.AbiCoder.defaultAbiCoder().encode( fragment.outputs, toPositional(fragment.outputs, value), ) @@ -285,8 +306,8 @@ function encodeRevert(reason?: string): string { } return ( - ethers.utils.id("Error(string)").slice(0, 10) + - ethers.utils.defaultAbiCoder.encode(["string"], [reason]).slice(2) + ethers.id("Error(string)").slice(0, 10) + + ethers.AbiCoder.defaultAbiCoder().encode(["string"], [reason]).slice(2) ) } @@ -300,18 +321,20 @@ function encodeRevert(reason?: string): string { * @returns A handle exposing each of `target`'s functions with `returns`, * `whenCalledWith`, `reverts`, `reset`, `callCount` and `getCall`. */ -export async function createMock( +export async function createMock( target: string, options: { address?: string } = {}, ): Promise> { const targetArtifact = await artifacts.readArtifact(target) - const targetInterface = new ethers.utils.Interface(targetArtifact.abi) + const targetInterface = new ethers.Interface(targetArtifact.abi) const mockFactory = await ethers.getContractFactory("MockContract") // Deploying is a transaction too, and a mock is routinely created inside a // `before` hook after the test has already captured a baseline timestamp. - let mockContract = await withoutAdvancingTime(() => mockFactory.deploy()) - await mockContract.deployed() + let mockContract: MockContract = await withoutAdvancingTime(() => + mockFactory.deploy(), + ) + await mockContract.waitForDeployment() assertNoSelectorCollision(targetInterface, mockContract.interface, target) @@ -321,21 +344,19 @@ export async function createMock( // configuration below — the base returns, the non-recording flags, and // later every `returns`/`whenCalledWith` — is storage. Configuring first // and relocating afterwards left a pinned mock with none of it. - const code = await ethers.provider.getCode(mockContract.address) + const code = await ethers.provider.getCode(await mockContract.getAddress()) await ethers.provider.send("hardhat_setCode", [options.address, code]) - mockContract = mockContract.attach(options.address) + mockContract = await ethers.getContractAt("MockContract", options.address) } // Install the response of last resort for every function, so an unstubbed // one answers with a correctly sized zero instead of reverting the caller. - const baseFragments = Object.values(targetInterface.functions) - const baseSelectors = baseFragments.map((fragment) => - targetInterface.getSighash(fragment), - ) + const baseFragments = functionFragments(targetInterface) + const baseSelectors = baseFragments.map((fragment) => fragment.selector) const baseReturns = baseFragments.map((fragment) => fragment.outputs == null || fragment.outputs.length === 0 ? "0x" - : ethers.utils.defaultAbiCoder.encode( + : ethers.AbiCoder.defaultAbiCoder().encode( fragment.outputs, fragment.outputs.map((output) => zeroValueFor(output)), ), @@ -354,27 +375,26 @@ export async function createMock( fragment.stateMutability === "view" || fragment.stateMutability === "pure", ) - .map((fragment) => targetInterface.getSighash(fragment)) + .map((fragment) => fragment.selector) if (nonRecordingSelectors.length > 0) { await withoutAdvancingTime(() => mockContract.__mock__setNonRecordingSelectors(nonRecordingSelectors), ) } - await ethers.provider.send("hardhat_impersonateAccount", [ - mockContract.address, - ]) + const address = await mockContract.getAddress() + await ethers.provider.send("hardhat_impersonateAccount", [address]) await ethers.provider.send("hardhat_setBalance", [ - mockContract.address, + address, "0x21e19e0c9bab2400000", // 10_000 ETH, so the mock can pay for its own sends ]) - const wallet = await ethers.getSigner(mockContract.address) + const wallet = await ethers.getSigner(address) const byName = fragmentsByName(targetInterface) function buildFunction(name: string): MockedFunction { const fragment = resolveFragment(byName.get(name) ?? [], name, target) - const selector = targetInterface.getSighash(fragment) + const { selector } = fragment const readOnly = fragment.stateMutability === "view" || fragment.stateMutability === "pure" @@ -433,7 +453,7 @@ export async function createMock( ) } - const decodeCall = (callData: string, value: BigNumber): MockCall => ({ + const decodeCall = (callData: string, value: bigint): MockCall => ({ args: Array.from( targetInterface.decodeFunctionData(fragment, callData), ) as unknown[], @@ -487,7 +507,7 @@ export async function createMock( mockContract.__mock__callForSelectorAt(selector, index), mockContract.__mock__callValueForSelectorAt(selector, index), ]) - return decodeCall(callData as string, value as BigNumber) + return decodeCall(callData as string, value as bigint) }, async getCalls(): Promise { @@ -504,7 +524,7 @@ export async function createMock( mockContract.__mock__callForSelectorAt(selector, i), mockContract.__mock__callValueForSelectorAt(selector, i), ]) - calls.push(decodeCall(callData as string, value as BigNumber)) + calls.push(decodeCall(callData as string, value as bigint)) } return calls @@ -514,21 +534,21 @@ export async function createMock( const functions = new Map() const readContract = new ethers.Contract( - mockContract.address, + address, targetArtifact.abi, ethers.provider, ) const handle = { - address: mockContract.address, + address, wallet, mockContract, - connect(signer: Signer): Contract { + connect(signer: Signer): T { return new ethers.Contract( - mockContract.address, + address, targetArtifact.abi, signer, - ) + ) as unknown as T }, async reset(): Promise { await withoutAdvancingTime(() => mockContract.__mock__reset()) @@ -613,13 +633,9 @@ export async function expectCalledTwice(fn: MockedFunction): Promise { /** * Puts one recorded or expected argument into a comparable form. * - * The two sides never arrive in the same representation. ethers decodes an ABI - * integer to a `BigNumber` above 48 bits and to a plain `number` at or below - * it, so a `uint256` argument reaches this as a `BigNumber` while the - * `uint32` getter the test compared it against yields a `number`; and a struct - * or dynamic array puts both one level down, where the previous top-level-only - * check never looked. smock compared `BigNumberish` values numerically at any - * depth, so both shapes used to pass. + * ethers v6 decodes every ABI integer as a bigint, while test expectations + * can contain ordinary numbers. Arrays and structs can nest those values, + * so numeric comparison is normalized recursively. * * Numerics are wrapped rather than rendered bare, so that a genuine string * argument of `"100"` still fails against a numeric `100`. Everything else — @@ -628,9 +644,6 @@ export async function expectCalledTwice(fn: MockedFunction): Promise { * real mismatch. */ function normalizeForComparison(value: unknown): unknown { - if (BigNumber.isBigNumber(value)) { - return { numeric: value.toString() } - } if (typeof value === "number" || typeof value === "bigint") { return { numeric: value.toString() } } diff --git a/solidity/random-beacon/test/mocks/staking.ts b/solidity/random-beacon/test/mocks/staking.ts index 30edc665d9..e1ff72d4a3 100644 --- a/solidity/random-beacon/test/mocks/staking.ts +++ b/solidity/random-beacon/test/mocks/staking.ts @@ -8,7 +8,7 @@ export async function fakeTokenStaking( randomBeacon: RandomBeacon, ): Promise> { const tokenStaking = await createMock("TokenStaking", { - address: await randomBeacon.callStatic.staking(), + address: await randomBeacon.staking.staticCall(), }) return tokenStaking diff --git a/solidity/random-beacon/test/system/e2e.test.ts b/solidity/random-beacon/test/system/e2e.test.ts index 25b768a43d..39b905141a 100644 --- a/solidity/random-beacon/test/system/e2e.test.ts +++ b/solidity/random-beacon/test/system/e2e.test.ts @@ -2,6 +2,7 @@ import { ethers, helpers } from "hardhat" import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" import { expect } from "chai" +import requireResult from "../helpers/chain" import { constants, dkgState, @@ -16,7 +17,7 @@ import { import blsData from "../data/bls" import { registerOperators } from "../utils/operators" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { RandomBeacon, RandomBeaconStub, @@ -24,10 +25,10 @@ import type { RandomBeaconGovernance, } from "../../typechain" -const ZERO_ADDRESS = ethers.constants.AddressZero +const ZERO_ADDRESS = ethers.ZeroAddress const { mineBlocks, mineBlocksTo } = helpers.time -const { keccak256 } = ethers.utils +const { keccak256 } = ethers const fixture = async () => { const contracts = await randomBeaconDeployment() @@ -118,7 +119,9 @@ describe("System -- e2e", () => { // pass key generation state and transition to awaiting result state await mineBlocksTo( - (await genesisTx.wait()).blockNumber + constants.offchainDkgTime + 1, + requireResult(await genesisTx.wait()).blockNumber + + constants.offchainDkgTime + + 1, ) expect(await randomBeacon.getGroupCreationState()).to.be.equal( @@ -129,7 +132,7 @@ describe("System -- e2e", () => { randomBeacon, groupPubKeys[groupPubKeyCounter], genesisSeed, - (await genesisTx.wait()).blockNumber, + requireResult(await genesisTx.wait()).blockNumber, noMisbehaved, ) groupMembers.push(dkgResult.members) @@ -159,7 +162,7 @@ describe("System -- e2e", () => { ) await mineBlocksTo( - (await txSubmitRelayEntry.wait()).blockNumber + + requireResult(await txSubmitRelayEntry.wait()).blockNumber + constants.offchainDkgTime + 1, ) @@ -171,10 +174,8 @@ describe("System -- e2e", () => { dkgResult = await signAndSubmitCorrectDkgResult( randomBeacon, groupPubKeys[groupPubKeyCounter], - ethers.BigNumber.from( - ethers.utils.keccak256(blsData.groupSignatures[i - 1]), - ), - (await txSubmitRelayEntry.wait()).blockNumber, + BigInt(ethers.keccak256(blsData.groupSignatures[i - 1])), + requireResult(await txSubmitRelayEntry.wait()).blockNumber, noMisbehaved, ) groupMembers.push(dkgResult.members) diff --git a/solidity/random-beacon/test/tasks/initialize.test.ts b/solidity/random-beacon/test/tasks/initialize.test.ts new file mode 100644 index 0000000000..4381e75428 --- /dev/null +++ b/solidity/random-beacon/test/tasks/initialize.test.ts @@ -0,0 +1,92 @@ +import hre, { deployments, ethers, helpers } from "hardhat" +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" +import { expect } from "chai" + +import type { RandomBeacon, TokenStaking, T } from "../../typechain" + +async function initializedOperator() { + await deployments.fixture() + const [owner, provider, operator] = (await ethers.getSigners()).slice(10) + const args = { + owner: owner.address, + provider: provider.address, + operator: operator.address, + amount: 1_000_000, + authorization: 500_000, + } + await hre.run("initialize", args) + return { + args, + staking: await helpers.contracts.getContract("TokenStaking"), + beacon: await helpers.contracts.getContract("RandomBeacon"), + token: await helpers.contracts.getContract("T"), + } +} + +async function operatorWithDefaultAuthorization() { + await deployments.fixture() + const [owner, provider, operator] = (await ethers.getSigners()).slice(10) + const args = { + owner: owner.address, + provider: provider.address, + operator: operator.address, + amount: 1_000_000, + } + await hre.run("initialize", args) + return { + args, + staking: await helpers.contracts.getContract("TokenStaking"), + beacon: await helpers.contracts.getContract("RandomBeacon"), + } +} + +describe("Initialization tasks", () => { + it("mints, stakes, authorizes and registers an operator", async () => { + const { args, staking, beacon, token } = + await loadFixture(initializedOperator) + expect((await staking.stakes(args.provider)).tStake).to.equal( + ethers.parseEther("1000000"), + ) + expect( + await staking.authorizedStake(args.provider, await beacon.getAddress()), + ).to.equal(ethers.parseEther("500000")) + expect(await beacon.operatorToStakingProvider(args.operator)).to.equal( + args.provider, + ) + expect(await token.balanceOf(args.owner)).to.equal(0n) + }) + + it("does not send another transaction when stake and registration already match", async () => { + const { args } = await loadFixture(initializedOperator) + const before = await ethers.provider.getBlockNumber() + await hre.run("initialize:staking", args) + await hre.run("authorize:beacon", args) + await hre.run("register:beacon", args) + // Re-run the full initialize task, exercising add_beta_operator too. + await hre.run("initialize", args) + expect(await ethers.provider.getBlockNumber()).to.equal(before) + }) + + it("tops up an existing stake and increases authorization", async () => { + const { args, staking, beacon, token } = + await loadFixture(initializedOperator) + await hre.run("initialize:staking", { ...args, amount: 1_200_000 }) + await hre.run("authorize:beacon", { ...args, authorization: 700_000 }) + expect((await staking.stakes(args.provider)).tStake).to.equal( + ethers.parseEther("1200000"), + ) + expect( + await staking.authorizedStake(args.provider, await beacon.getAddress()), + ).to.equal(ethers.parseEther("700000")) + expect(await token.balanceOf(args.owner)).to.equal(0n) + }) + + it("defaults authorization to the beacon's minimumAuthorization", async () => { + const { args, staking, beacon } = await loadFixture( + operatorWithDefaultAuthorization, + ) + expect( + await staking.authorizedStake(args.provider, await beacon.getAddress()), + ).to.equal(await beacon.minimumAuthorization()) + }) +}) diff --git a/solidity/random-beacon/test/utils/dkg.test.ts b/solidity/random-beacon/test/utils/dkg.test.ts index 85eea5bf3c..0e85221b09 100644 --- a/solidity/random-beacon/test/utils/dkg.test.ts +++ b/solidity/random-beacon/test/utils/dkg.test.ts @@ -12,8 +12,11 @@ describe("hashDKGMembers", () => { const expectedMembers = members const actualHash = hashDKGMembers(members, misbehavedMembers) - const expectedHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [expectedMembers]), + const expectedHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint32[]"], + [expectedMembers], + ), ) expect(expectedHash).to.be.equal(actualHash) @@ -28,8 +31,11 @@ describe("hashDKGMembers", () => { const expectedMembers = [101, 102, 103, 104, 105, 106, 107, 108, 109] const actualHash = hashDKGMembers(members, misbehavedMembers) - const expectedHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [expectedMembers]), + const expectedHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint32[]"], + [expectedMembers], + ), ) expect(expectedHash).to.be.equal(actualHash) @@ -44,8 +50,11 @@ describe("hashDKGMembers", () => { const expectedMembers = [100, 101, 102, 103, 104, 105, 106, 107, 108] const actualHash = hashDKGMembers(members, misbehavedMembers) - const expectedHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [expectedMembers]), + const expectedHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint32[]"], + [expectedMembers], + ), ) expect(expectedHash).to.be.equal(actualHash) @@ -60,8 +69,11 @@ describe("hashDKGMembers", () => { const expectedMembers = [100, 102, 103, 104, 106, 108, 109] const actualHash = hashDKGMembers(members, misbehavedMembers) - const expectedHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [expectedMembers]), + const expectedHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint32[]"], + [expectedMembers], + ), ) expect(expectedHash).to.be.equal(actualHash) @@ -76,8 +88,11 @@ describe("hashDKGMembers", () => { const expectedMembers = members const actualHash = hashDKGMembers(members, misbehavedMembers) - const expectedHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [expectedMembers]), + const expectedHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint32[]"], + [expectedMembers], + ), ) expect(expectedHash).to.be.equal(actualHash) diff --git a/solidity/random-beacon/test/utils/dkg.ts b/solidity/random-beacon/test/utils/dkg.ts index 0674e14790..fc736b7972 100644 --- a/solidity/random-beacon/test/utils/dkg.ts +++ b/solidity/random-beacon/test/utils/dkg.ts @@ -1,14 +1,15 @@ import { ethers } from "hardhat" import { expect } from "chai" -import { BigNumber } from "ethers" + +import requireResult from "../helpers/chain" // eslint-disable-next-line import/no-cycle import { selectGroup } from "./groups" import type { Operator } from "./operators" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" import type { RandomBeacon, SortitionPool } from "../../typechain" -import type { ContractTransaction } from "ethers" +import type { ContractTransactionResponse } from "ethers" import type { BeaconDkg as DKG, DkgResultSubmittedEvent, @@ -23,12 +24,14 @@ export const noMisbehaved: number[] = [] export async function genesis( randomBeacon: RandomBeacon, -): Promise<[ContractTransaction, BigNumber]> { +): Promise<[ContractTransactionResponse, bigint]> { const tx = await randomBeacon.genesis() - const receipt = await tx.wait() - const expectedSeed = ethers.BigNumber.from( - ethers.utils.keccak256( - ethers.utils.solidityPack( + + const receipt = requireResult(await tx.wait()) + + const expectedSeed = BigInt( + ethers.keccak256( + ethers.solidityPacked( ["uint256", "uint256"], [ "31415926535897932384626433832795028841971693993751058209749445923078164062862", @@ -47,19 +50,19 @@ export async function genesis( export async function signAndSubmitCorrectDkgResult( randomBeacon: RandomBeacon, groupPublicKey: string, - seed: BigNumber, + seed: bigint, startBlock: number, misbehavedIndices: number[], submitterIndex = 1, membersHash?: string, numberOfSignatures = 33, ): Promise<{ - transaction: ContractTransaction + transaction: ContractTransactionResponse dkgResult: DKG.ResultStruct dkgResultHash: string members: number[] submitter: SignerWithAddress - submitterInitialBalance: BigNumber + submitterInitialBalance: bigint }> { const sortitionPool = (await ethers.getContractAt( "SortitionPool", @@ -91,12 +94,12 @@ export async function signAndSubmitArbitraryDkgResult( groupMembersHash?: string, numberOfSignatures = 33, ): Promise<{ - transaction: ContractTransaction + transaction: ContractTransactionResponse dkgResult: DKG.ResultStruct dkgResultHash: string members: number[] submitter: SignerWithAddress - submitterInitialBalance: BigNumber + submitterInitialBalance: bigint }> { const { members, signingMembersIndices, signaturesBytes } = await signDkgResult( @@ -122,8 +125,8 @@ export async function signAndSubmitArbitraryDkgResult( membersHash, } - const dkgResultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const dkgResultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( [ "(uint256 submitterMemberIndex, bytes groupPubKey, uint8[] misbehavedMembersIndices, bytes signatures, uint256[] signingMembersIndices, uint32[] members, bytes32 membersHash)", ], @@ -162,7 +165,7 @@ export async function signAndSubmitUnrecoverableDkgResult( submitterIndex = 1, numberOfSignatures = 33, ): Promise<{ - transaction: ContractTransaction + transaction: ContractTransactionResponse dkgResult: DKG.ResultStruct dkgResultHash: string members: number[] @@ -193,8 +196,8 @@ export async function signAndSubmitUnrecoverableDkgResult( membersHash, } - const dkgResultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const dkgResultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( [ "(uint256 submitterMemberIndex, bytes groupPubKey, uint8[] misbehavedMembersIndices, bytes signatures, uint256[] signingMembersIndices, uint32[] members, bytes32 membersHash)", ], @@ -222,8 +225,8 @@ export async function signDkgResult( signingMembersIndices: number[] signaturesBytes: string }> { - const resultHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const resultHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( ["uint256", "bytes", "uint8[]", "uint256"], [hardhatNetworkId, groupPublicKey, misbehavedMembersIndices, startBlock], ), @@ -246,13 +249,13 @@ export async function signDkgResult( signingMembersIndices.push(signerIndex) const signature = await ethersSigner.signMessage( - ethers.utils.arrayify(resultHash), + ethers.getBytes(resultHash), ) signatures.push(signature) } - const signaturesBytes: string = ethers.utils.hexConcat(signatures) + const signaturesBytes: string = ethers.concat(signatures) return { members, signingMembersIndices, signaturesBytes } } @@ -270,32 +273,37 @@ export function hashDKGMembers( } } - return ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [activeDkgMembers]), + return ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint32[]"], + [activeDkgMembers], + ), ) } - return ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode(["uint32[]"], [members]), + return ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode(["uint32[]"], [members]), ) } export interface DkgResultSubmittedEventArgs { resultHash: string - seed: BigNumber + seed: bigint result: DKG.ResultStruct } // Compare each field explicitly so nested arrays in the result struct produce // useful assertion failures. export async function expectDkgResultSubmittedEvent( - tx: ContractTransaction, + tx: ContractTransactionResponse, expectedArgs: DkgResultSubmittedEventArgs, ): Promise { const eventName = "DkgResultSubmitted" - const event = (await tx.wait()).events?.find((e) => e.event === eventName) as - DkgResultSubmittedEvent | undefined + const event = requireResult(await tx.wait()).logs.find( + (log): log is DkgResultSubmittedEvent.Log => + log instanceof ethers.EventLog && log.eventName === eventName, + ) if (!event) { throw new Error(`Event ${eventName} not emitted`) @@ -331,7 +339,7 @@ export async function expectDkgResultSubmittedEvent( await expect( actualArgs.result.misbehavedMembersIndices, "invalid misbehavedMembersIndices", - ).to.be.deep.equal(expectedArgs.result.misbehavedMembersIndices) + ).to.be.deep.equal(expectedArgs.result.misbehavedMembersIndices.map(BigInt)) await expect(actualArgs.result.signatures, "invalid signatures").to.be.equal( expectedArgs.result.signatures, @@ -340,12 +348,10 @@ export async function expectDkgResultSubmittedEvent( await expect( actualArgs.result.signingMembersIndices, "invalid signingMembersIndices", - ).to.be.deep.equal( - expectedArgs.result.signingMembersIndices.map(BigNumber.from), - ) + ).to.be.deep.equal(expectedArgs.result.signingMembersIndices.map(BigInt)) await expect(actualArgs.result.members, "invalid members").to.be.deep.equal( - expectedArgs.result.members, + expectedArgs.result.members.map(BigInt), ) await expect( diff --git a/solidity/random-beacon/test/utils/groups.ts b/solidity/random-beacon/test/utils/groups.ts index 19c84e95b7..ed5774d6c3 100644 --- a/solidity/random-beacon/test/utils/groups.ts +++ b/solidity/random-beacon/test/utils/groups.ts @@ -1,25 +1,28 @@ +import { toBeHex } from "ethers" import { helpers, ethers } from "hardhat" +import requireResult from "../helpers/chain" import { constants, params } from "../fixtures" import blsData from "../data/bls" // eslint-disable-next-line import/no-cycle import { noMisbehaved, signAndSubmitArbitraryDkgResult } from "./dkg" -import type { BigNumber, BigNumberish } from "ethers" +import type { BigNumberish } from "ethers" import type { Operator } from "./operators" import type { RandomBeacon, SortitionPool } from "../../typechain" -const { keccak256, defaultAbiCoder } = ethers.utils +const { keccak256 } = ethers +const defaultAbiCoder = ethers.AbiCoder.defaultAbiCoder() const { mineBlocks } = helpers.time export async function createGroup( randomBeacon: RandomBeacon, signers: Operator[], ): Promise { - const { blockNumber: startBlock } = await ( - await randomBeacon.genesis() - ).wait() + const { blockNumber: startBlock } = requireResult( + await (await randomBeacon.genesis()).wait(), + ) await mineBlocks(constants.offchainDkgTime) @@ -38,17 +41,20 @@ export async function createGroup( export async function selectGroup( sortitionPool: SortitionPool, - seed: BigNumber, + seed: bigint, ): Promise { - const identifiers = await sortitionPool.selectGroup( - constants.groupSize, - ethers.utils.hexZeroPad(seed.toHexString(), 32), + // Copy the immutable ethers Result before passing these IDs to another call. + const identifiers = Array.from( + await sortitionPool.selectGroup( + constants.groupSize, + ethers.zeroPadValue(toBeHex(seed), 32), + ), ) const addresses = await sortitionPool.getIDOperators(identifiers) return Promise.all( identifiers.map(async (identifier, i): Promise => ({ - id: identifier, + id: Number(identifier), signer: await ethers.getSigner(addresses[i]), })), ) diff --git a/solidity/random-beacon/test/utils/inactivity.ts b/solidity/random-beacon/test/utils/inactivity.ts index 18d17d2033..055e1d3aa2 100644 --- a/solidity/random-beacon/test/utils/inactivity.ts +++ b/solidity/random-beacon/test/utils/inactivity.ts @@ -16,8 +16,8 @@ export async function signOperatorInactivityClaim( signatures: string signingMembersIndices: number[] }> { - const messageHash = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( + const messageHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( ["uint256", "uint256", "bytes", "uint8[]"], [hardhatNetworkId, nonce, groupPubKey, inactiveMembersIndices], ), @@ -39,14 +39,14 @@ export async function signOperatorInactivityClaim( const ethersSigner = signers[i].signer const signature = await ethersSigner.signMessage( - ethers.utils.arrayify(messageHash), + ethers.getBytes(messageHash), ) signatures.push(signature) } return { - signatures: ethers.utils.hexConcat(signatures), + signatures: ethers.concat(signatures), signingMembersIndices, } } diff --git a/solidity/random-beacon/test/utils/operators.ts b/solidity/random-beacon/test/utils/operators.ts index 5151cfd86d..ea695b4dda 100644 --- a/solidity/random-beacon/test/utils/operators.ts +++ b/solidity/random-beacon/test/utils/operators.ts @@ -3,8 +3,8 @@ import { ethers, helpers } from "hardhat" import { params } from "../fixtures" import { testConfig } from "../../hardhat.config" -import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" -import type { BigNumber, BigNumberish, Contract } from "ethers" +import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" +import type { BigNumberish, Contract } from "ethers" import type { RandomBeacon, RandomBeaconStub, @@ -14,7 +14,7 @@ import type { } from "../../typechain" /** Minimal ABI for TokenStaking methods omitted from the generated Typechain ABI. */ -const legacyTokenStakingIface = new ethers.utils.Interface([ +const legacyTokenStakingIface = new ethers.Interface([ "function stake(address,address,address,uint96)", "function increaseAuthorization(address,address,uint96)", "function approveApplication(address)", @@ -23,10 +23,10 @@ const legacyTokenStakingIface = new ethers.utils.Interface([ ]) export function legacyTokenStakingAt( - staking: Pick, + staking: Pick, signer: SignerWithAddress, ): Contract { - return new ethers.Contract(staking.address, legacyTokenStakingIface, signer) + return new ethers.Contract(staking, legacyTokenStakingIface, signer) } export type OperatorID = number @@ -37,7 +37,7 @@ export async function registerOperators( t: T, numberOfOperators = testConfig.operatorsCount, unnamedSignersOffset = testConfig.nonStakingAccountsCount, - stakeAmount: BigNumber = params.minimumAuthorization, + stakeAmount: bigint = params.minimumAuthorization, ): Promise { const operators: Operator[] = [] @@ -87,7 +87,7 @@ export async function registerOperators( await randomBeacon.connect(operator).joinSortitionPool() - const id = await sortitionPool.getOperatorID(operator.address) + const id = Number(await sortitionPool.getOperatorID(operator.address)) operators.push({ id, signer: operator }) } @@ -108,7 +108,7 @@ export async function stake( const { deployer } = await helpers.signers.getNamedSigners() await t.connect(deployer).mint(owner.address, stakeAmount) - await t.connect(owner).approve(staking.address, stakeAmount) + await t.connect(owner).approve(await staking.getAddress(), stakeAmount) await legacyTokenStakingAt(staking, owner).stake( stakingProvider.address, @@ -119,7 +119,7 @@ export async function stake( await legacyTokenStakingAt(staking, authorizer).increaseAuthorization( stakingProvider.address, - randomBeacon.address, + await randomBeacon.getAddress(), stakeAmount, ) } diff --git a/solidity/random-beacon/test/utils/submission.ts b/solidity/random-beacon/test/utils/submission.ts index cff640be87..db5df03c0f 100644 --- a/solidity/random-beacon/test/utils/submission.ts +++ b/solidity/random-beacon/test/utils/submission.ts @@ -1,5 +1,3 @@ -import { BigNumber } from "ethers" - import { constants } from "../fixtures" import type { BigNumberish } from "ethers" @@ -11,7 +9,7 @@ export function firstEligibleIndex( // eslint-disable-next-line no-param-reassign if (!groupSize) groupSize = constants.groupSize - return BigNumber.from(seed).mod(groupSize).add(1).toNumber() + return Number((BigInt(seed) % BigInt(groupSize)) + 1n) } export function shiftEligibleIndex( diff --git a/solidity/random-beacon/test/utils/wait-for-confirmations.test.ts b/solidity/random-beacon/test/utils/wait-for-confirmations.test.ts new file mode 100644 index 0000000000..060aff4d3b --- /dev/null +++ b/solidity/random-beacon/test/utils/wait-for-confirmations.test.ts @@ -0,0 +1,53 @@ +import assert from "assert/strict" +import { ethers } from "hardhat" +import { expect } from "chai" +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers" + +import waitForConfirmations from "../../utils/wait-for-confirmations" + +async function sentTransaction() { + const [signer] = await ethers.getSigners() + return signer.sendTransaction({ to: signer.address, value: 0 }) +} + +describe("deployment confirmations", () => { + it("retrieves a confirmed transaction through the Hardhat ethers v6 provider", async () => { + const transaction = await loadFixture(sentTransaction) + const receipt = await waitForConfirmations( + ethers.provider, + transaction.hash, + 1, + 5_000, + ) + expect(receipt.hash).to.equal(transaction.hash) + expect(receipt.status).to.equal(1) + }) + + it("waits for the requested number of confirmations", async () => { + const transaction = await loadFixture(sentTransaction) + const pending = waitForConfirmations( + ethers.provider, + transaction.hash, + 2, + 5_000, + ) + await ethers.provider.send("evm_mine", []) + const receipt = await pending + expect(await receipt.confirmations()).to.be.at.least(2) + }) + + it("fails if the additional confirmation does not arrive before the timeout", async () => { + const transaction = await loadFixture(sentTransaction) + await assert.rejects( + waitForConfirmations(ethers.provider, transaction.hash, 2, 50), + (error: unknown) => ethers.isError(error, "TIMEOUT"), + ) + }) + + it("fails if the saved deployment transaction cannot be found", async () => { + await assert.rejects( + waitForConfirmations(ethers.provider, ethers.ZeroHash, 1, 5_000), + /Deployment transaction .* was not found/, + ) + }) +}) diff --git a/solidity/random-beacon/utils/wait-for-confirmations.ts b/solidity/random-beacon/utils/wait-for-confirmations.ts new file mode 100644 index 0000000000..b3a939c588 --- /dev/null +++ b/solidity/random-beacon/utils/wait-for-confirmations.ts @@ -0,0 +1,35 @@ +import type { Provider, TransactionReceipt } from "ethers" + +/** Wait through the transaction response; Hardhat's ethers v6 provider does not implement waitForTransaction. */ +export default async function waitForConfirmations( + provider: Pick, + transactionHash: string, + confirmations = 2, + timeout = 300_000, +): Promise { + const pollInterval = 2_000 + const deadline = Date.now() + timeout + // ethers v5 waitForTransaction polled, so a load-balanced endpoint that does + // not see the just-mined transaction yet must not fail the deployment. + let transaction = await provider.getTransaction(transactionHash) + while (!transaction) { + const remaining = deadline - Date.now() + if (remaining <= 0) { + throw new Error(`Deployment transaction ${transactionHash} was not found`) + } + await new Promise((resolve) => { + setTimeout(resolve, Math.min(pollInterval, remaining)) + }) + transaction = await provider.getTransaction(transactionHash) + } + const receipt = await transaction.wait( + confirmations, + Math.max(deadline - Date.now(), 1), + ) + if (!receipt) { + throw new Error( + `Deployment transaction ${transactionHash} is not confirmed`, + ) + } + return receipt +} diff --git a/solidity/random-beacon/yarn.lock b/solidity/random-beacon/yarn.lock index 27a30de19c..ab38f785cf 100644 --- a/solidity/random-beacon/yarn.lock +++ b/solidity/random-beacon/yarn.lock @@ -5,13 +5,54 @@ __metadata: version: 8 cacheKey: 10c0 -"@adraffy/ens-normalize@npm:^1.11.0": +"@adraffy/ens-normalize@npm:1.11.1, @adraffy/ens-normalize@npm:^1.11.0": version: 1.11.1 resolution: "@adraffy/ens-normalize@npm:1.11.1" checksum: 10c0/b364e2a57131db278ebf2f22d1a1ac6d8aea95c49dd2bbbc1825870b38aa91fd8816aba580a1f84edc50a45eb6389213dacfd1889f32893afc8549a82d304767 languageName: node linkType: hard +"@aws-crypto/sha256-js@npm:1.2.2": + version: 1.2.2 + resolution: "@aws-crypto/sha256-js@npm:1.2.2" + dependencies: + "@aws-crypto/util": "npm:^1.2.2" + "@aws-sdk/types": "npm:^3.1.0" + tslib: "npm:^1.11.1" + checksum: 10c0/f4e8593cfbc48591413f00c744569b21e5ed5fab0e27fa4b59c517f2024ca4f46fab7b3874f2a207ceeef8feefc22d143a82d6c6bfe5303ea717f579d8d7ad0a + languageName: node + linkType: hard + +"@aws-crypto/util@npm:^1.2.2": + version: 1.2.2 + resolution: "@aws-crypto/util@npm:1.2.2" + dependencies: + "@aws-sdk/types": "npm:^3.1.0" + "@aws-sdk/util-utf8-browser": "npm:^3.0.0" + tslib: "npm:^1.11.1" + checksum: 10c0/ade8843bf13529b1854f64d6bbb23f30b46330743c8866adfd2105d830e30ce837a868eaaf41c4c2381d27e9d225d3a0a7558ee1eee022f0192916e33bfb654c + languageName: node + linkType: hard + +"@aws-sdk/types@npm:^3.1.0": + version: 3.974.5 + resolution: "@aws-sdk/types@npm:3.974.5" + dependencies: + "@smithy/types": "npm:^4.17.2" + tslib: "npm:^2.6.2" + checksum: 10c0/803aaaa1c0675dcb564803993f3c47d96302fad461af8af80e75afc40c72228ebf669593c18e44ca09fc5acf0d1bd25966261de07844d8f11ad82aa2650252d0 + languageName: node + linkType: hard + +"@aws-sdk/util-utf8-browser@npm:^3.0.0": + version: 3.259.0 + resolution: "@aws-sdk/util-utf8-browser@npm:3.259.0" + dependencies: + tslib: "npm:^2.3.1" + checksum: 10c0/ff56ff252c0ea22b760b909ba5bbe9ca59a447066097e73b1e2ae50a6d366631ba560c373ec4e83b3e225d16238eeaf8def210fdbf135070b3dd3ceb1cc2ef9a + languageName: node + linkType: hard + "@babel/code-frame@npm:^7.0.0": version: 7.14.5 resolution: "@babel/code-frame@npm:7.14.5" @@ -57,6 +98,13 @@ __metadata: languageName: node linkType: hard +"@bytecodealliance/preview2-shim@npm:0.17.0": + version: 0.17.0 + resolution: "@bytecodealliance/preview2-shim@npm:0.17.0" + checksum: 10c0/a2cb46dd0e14319ec4c6b89cc6e629884a98120c70fc831131bc0941e03b8a40b35cd7d5bf4440653ac3658a73484a0be0a7066bfb4d2c43adc122488279c10b + languageName: node + linkType: hard + "@bytecodealliance/preview2-shim@npm:^0.19.0": version: 0.19.0 resolution: "@bytecodealliance/preview2-shim@npm:0.19.0" @@ -109,6 +157,15 @@ __metadata: languageName: node linkType: hard +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": "npm:0.3.9" + checksum: 10c0/05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 + languageName: node + linkType: hard + "@emnapi/core@npm:1.10.0": version: 1.10.0 resolution: "@emnapi/core@npm:1.10.0" @@ -220,23 +277,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.4.1, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.4.0": - version: 5.4.1 - resolution: "@ethersproject/abi@npm:5.4.1" - dependencies: - "@ethersproject/address": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/constants": "npm:^5.4.0" - "@ethersproject/hash": "npm:^5.4.0" - "@ethersproject/keccak256": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - checksum: 10c0/22a01c2fabbc01941e317c98eedc23abb58a63a78d190754799de2a6aa862118aab5350846c599800bfcb90a3271aa68d3ebc5b06beb0a4c2f764dadb6af2085 - languageName: node - linkType: hard - "@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abi@npm:5.7.0" @@ -254,7 +294,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.8.0, @ethersproject/abi@npm:^5.8.0": +"@ethersproject/abi@npm:5.8.0, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abi@npm:5.8.0" dependencies: @@ -286,19 +326,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:5.4.1, @ethersproject/abstract-signer@npm:^5.4.0": - version: 5.4.1 - resolution: "@ethersproject/abstract-signer@npm:5.4.1" - dependencies: - "@ethersproject/abstract-provider": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - checksum: 10c0/4012070ffa6277aedb34717a61ed40e839323240f14aa0a9546fd048e2ec0c73c47d12be9c9b37113fa2bb96f49336a58bb51c359191c897f74a1bbb7a026b4f - languageName: node - linkType: hard - "@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abstract-signer@npm:5.7.0" @@ -325,19 +352,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/address@npm:5.4.0, @ethersproject/address@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/address@npm:5.4.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/keccak256": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/rlp": "npm:^5.4.0" - checksum: 10c0/c383ecc2f895cd512a6eec52a3c740de0188a08318f57359eaa90e1166a95cb2fba4bdb2e00468e118bb2949faf830713a93d0338340185d438b08fa10d9ea1c - languageName: node - linkType: hard - "@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" @@ -377,15 +391,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:5.4.0, @ethersproject/base64@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/base64@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - checksum: 10c0/3c9092ae873a6fd88239ef808448720544e88aade1b549e97d19b8a1f4f0c0bc05870fd0cc03c312413f395d432a59f5a6228be0204528ed5865fc521093bbfa - languageName: node - linkType: hard - "@ethersproject/base64@npm:5.7.0, @ethersproject/base64@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/base64@npm:5.7.0" @@ -404,16 +409,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/basex@npm:5.4.0, @ethersproject/basex@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/basex@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - checksum: 10c0/6827e049777b36bbeb33554b028de58b90bcdcb98dad7e619767545ce98d9b2e0207368627b09c294c5d364d4ffd49f99635ca4a47d8d3574d1b86a9a307e498 - languageName: node - linkType: hard - "@ethersproject/basex@npm:5.7.0, @ethersproject/basex@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/basex@npm:5.7.0" @@ -434,17 +429,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.4.2, @ethersproject/bignumber@npm:^5.4.0": - version: 5.4.2 - resolution: "@ethersproject/bignumber@npm:5.4.2" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - bn.js: "npm:^4.11.9" - checksum: 10c0/335a149c91e7f5bf706375b095f48e4691f62979fdcdf4116026b3a27895c97d6d729c44b87818935520895a8a31fc41582546e47f4ce80fe80766e4676f9570 - languageName: node - linkType: hard - "@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.6.2, @ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" @@ -467,15 +451,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:5.4.0, @ethersproject/bytes@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/bytes@npm:5.4.0" - dependencies: - "@ethersproject/logger": "npm:^5.4.0" - checksum: 10c0/757d90a9dc068e9624f7beb3907c8cb1a9ba9b34e2012e541c4e6ee0f8d06e9a4b7dd5bb09546ed050557666ae63bb2afa422fb5498bc73b83c0add48d466549 - languageName: node - linkType: hard - "@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.6.1, @ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" @@ -494,15 +469,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/constants@npm:5.4.0, @ethersproject/constants@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/constants@npm:5.4.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.4.0" - checksum: 10c0/ee4522f518c3f9a997e501a54454015e8a5ae6ec866e7b5c57a689770c12c20c0baf282a35e2ca1cc6621e52639c6ae021154220a824b97a09228dde42cdc9b5 - languageName: node - linkType: hard - "@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/constants@npm:5.7.0" @@ -521,24 +487,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/contracts@npm:5.4.1": - version: 5.4.1 - resolution: "@ethersproject/contracts@npm:5.4.1" - dependencies: - "@ethersproject/abi": "npm:^5.4.0" - "@ethersproject/abstract-provider": "npm:^5.4.0" - "@ethersproject/abstract-signer": "npm:^5.4.0" - "@ethersproject/address": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/constants": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/transactions": "npm:^5.4.0" - checksum: 10c0/8bdd8a8f46b44d971971d2b11c3a64ab02a79082e78550b98f145f9d4347056642fe74b179b5243d1a7fef4e57c2167f531d255920065eea41ffc042eca82685 - languageName: node - linkType: hard - "@ethersproject/contracts@npm:5.7.0": version: 5.7.0 resolution: "@ethersproject/contracts@npm:5.7.0" @@ -575,22 +523,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/hash@npm:5.4.0, @ethersproject/hash@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/hash@npm:5.4.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.4.0" - "@ethersproject/address": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/keccak256": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - checksum: 10c0/5adc1e3cbf734ab541e25042ce1d29e46b198c0f2d0cbfc1cfc85f57ecfea6d7f12ac9d60fccd94da8fce5cafe31526b32a5769ff95d5b3773b6531cfc762698 - languageName: node - linkType: hard - "@ethersproject/hash@npm:5.7.0, @ethersproject/hash@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/hash@npm:5.7.0" @@ -625,26 +557,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/hdnode@npm:5.4.0, @ethersproject/hdnode@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/hdnode@npm:5.4.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.4.0" - "@ethersproject/basex": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/pbkdf2": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/sha2": "npm:^5.4.0" - "@ethersproject/signing-key": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - "@ethersproject/transactions": "npm:^5.4.0" - "@ethersproject/wordlists": "npm:^5.4.0" - checksum: 10c0/9b04638f507e9e7ae7be86948054904036ab497b33ae9e44f51294854e1850532130687332d1c5c91d7748c27b453080f7c672efa6fcd4460e947117db29babd - languageName: node - linkType: hard - "@ethersproject/hdnode@npm:5.7.0, @ethersproject/hdnode@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/hdnode@npm:5.7.0" @@ -685,27 +597,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/json-wallets@npm:5.4.0, @ethersproject/json-wallets@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/json-wallets@npm:5.4.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.4.0" - "@ethersproject/address": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/hdnode": "npm:^5.4.0" - "@ethersproject/keccak256": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/pbkdf2": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/random": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - "@ethersproject/transactions": "npm:^5.4.0" - aes-js: "npm:3.0.0" - scrypt-js: "npm:3.0.1" - checksum: 10c0/abda169f5097ff0a30fed60db46759e31f416c434616547358cced6126d4f5c330f815a01572615f9a75e3101289e5457a820fb715abe82eabcd5fafc29cec74 - languageName: node - linkType: hard - "@ethersproject/json-wallets@npm:5.7.0, @ethersproject/json-wallets@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/json-wallets@npm:5.7.0" @@ -748,16 +639,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/keccak256@npm:5.4.0, @ethersproject/keccak256@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/keccak256@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - js-sha3: "npm:0.5.7" - checksum: 10c0/61c9bd5037e10f56475c16325e4652338f0002f69d30902a8a5ed09a2eeccf7aa5c2de144828ae077def84c5d74ede73778d7d947d0bc68592a7934540549ff2 - languageName: node - linkType: hard - "@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:^5.6.1, @ethersproject/keccak256@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/keccak256@npm:5.7.0" @@ -778,13 +659,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/logger@npm:5.4.1, @ethersproject/logger@npm:^5.4.0": - version: 5.4.1 - resolution: "@ethersproject/logger@npm:5.4.1" - checksum: 10c0/614c3fe834bebd03d723f3b05a8ce106560733b1758a7b3bc3b6e5a777e6aaebf9608974ecc2cd96f42e2b521e343ec01ad0df48c78e011f4656caaccec8f151 - languageName: node - linkType: hard - "@ethersproject/logger@npm:5.7.0, @ethersproject/logger@npm:^5.6.0, @ethersproject/logger@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/logger@npm:5.7.0" @@ -799,15 +673,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/networks@npm:5.4.2, @ethersproject/networks@npm:^5.4.0": - version: 5.4.2 - resolution: "@ethersproject/networks@npm:5.4.2" - dependencies: - "@ethersproject/logger": "npm:^5.4.0" - checksum: 10c0/02ee9fbbe08a1766a43ac46b4f0cbf941f723475ebf91e3d17974d94cf4893616caf3005d7703bf25522431286d663d80f341ee913e08945c31345bb710da4ce - languageName: node - linkType: hard - "@ethersproject/networks@npm:5.7.1, @ethersproject/networks@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/networks@npm:5.7.1" @@ -826,16 +691,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/pbkdf2@npm:5.4.0, @ethersproject/pbkdf2@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/pbkdf2@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/sha2": "npm:^5.4.0" - checksum: 10c0/06f217e7925cbd5aa52330a535998e183a03a39563f53d19e7ef71e58f41d898a1e8ca2e93d24d23524a5f80aeec00b6a43845357259a152effc35b16090e07f - languageName: node - linkType: hard - "@ethersproject/pbkdf2@npm:5.7.0, @ethersproject/pbkdf2@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/pbkdf2@npm:5.7.0" @@ -856,15 +711,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/properties@npm:5.4.1, @ethersproject/properties@npm:^5.4.0": - version: 5.4.1 - resolution: "@ethersproject/properties@npm:5.4.1" - dependencies: - "@ethersproject/logger": "npm:^5.4.0" - checksum: 10c0/ebd147c5755c0464e671976fb6c9cc748bf85d5f5f41cc23b89e286a4c17831b5bd4c0bae21a82ddbdd6756409fc174b298c06a2c97fb7cfd31f48e915bc8285 - languageName: node - linkType: hard - "@ethersproject/properties@npm:5.7.0, @ethersproject/properties@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/properties@npm:5.7.0" @@ -883,33 +729,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.4.5": - version: 5.4.5 - resolution: "@ethersproject/providers@npm:5.4.5" - dependencies: - "@ethersproject/abstract-provider": "npm:^5.4.0" - "@ethersproject/abstract-signer": "npm:^5.4.0" - "@ethersproject/address": "npm:^5.4.0" - "@ethersproject/basex": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/constants": "npm:^5.4.0" - "@ethersproject/hash": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/networks": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/random": "npm:^5.4.0" - "@ethersproject/rlp": "npm:^5.4.0" - "@ethersproject/sha2": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - "@ethersproject/transactions": "npm:^5.4.0" - "@ethersproject/web": "npm:^5.4.0" - bech32: "npm:1.1.4" - ws: "npm:7.4.6" - checksum: 10c0/e4b9d4e56d9f098bf769e5e64c36919fe47fe1715cbe8d72d6ceb41b8af68455e4f0818dacd7837c6be76cc9c58f91cbfc4cc3298f7ced16c2edfdb54e8dbce5 - languageName: node - linkType: hard - "@ethersproject/providers@npm:5.7.2": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" @@ -966,16 +785,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/random@npm:5.4.0, @ethersproject/random@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/random@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - checksum: 10c0/5c38194ba4606ee6420386c889f035130b214f381ad3c18dba3c644fc873fb95bfb2153bac37a7918058443e678c6b67f87a92fa36bb4a8c46f5be790546122d - languageName: node - linkType: hard - "@ethersproject/random@npm:5.7.0, @ethersproject/random@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/random@npm:5.7.0" @@ -996,16 +805,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:5.4.0, @ethersproject/rlp@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/rlp@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - checksum: 10c0/e7b410e248f13d5d9a9f55e8043021940fdff726546a4d091a60cfabee2826d59115a3e610aa520440b0c4bbee7e9cc21f1fc07814a94669a17cf375efd87098 - languageName: node - linkType: hard - "@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.6.1, @ethersproject/rlp@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/rlp@npm:5.7.0" @@ -1026,17 +825,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:5.4.0, @ethersproject/sha2@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/sha2@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - hash.js: "npm:1.1.7" - checksum: 10c0/7bab0d64f0b7fda6822800f938da0a278d7f71c3240744b56a11e943a19ff8f393c2e274b88e931fd7ade49113f19f758d607e04fc94ffd42177ade101d34fdd - languageName: node - linkType: hard - "@ethersproject/sha2@npm:5.7.0, @ethersproject/sha2@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/sha2@npm:5.7.0" @@ -1059,20 +847,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/signing-key@npm:5.4.0, @ethersproject/signing-key@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/signing-key@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - bn.js: "npm:^4.11.9" - elliptic: "npm:6.5.4" - hash.js: "npm:1.1.7" - checksum: 10c0/de76689633a6eb1feb43f518255596b4da9ff0f9888fffd1f3b08e69f6f24b673c2aa571e1050b5bba61c68b07c7976237c36a1e29ab25f79de610dd15ba3c51 - languageName: node - linkType: hard - "@ethersproject/signing-key@npm:5.7.0, @ethersproject/signing-key@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/signing-key@npm:5.7.0" @@ -1101,19 +875,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/solidity@npm:5.4.0": - version: 5.4.0 - resolution: "@ethersproject/solidity@npm:5.4.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/keccak256": "npm:^5.4.0" - "@ethersproject/sha2": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - checksum: 10c0/30f99181988f13ffacdace47356ac336b556125aa9790983d6d65895fb3908edfac917db3dc63600af4c56e64b3052870b86608c678b337040cbe81648a1c434 - languageName: node - linkType: hard - "@ethersproject/solidity@npm:5.7.0": version: 5.7.0 resolution: "@ethersproject/solidity@npm:5.7.0" @@ -1142,17 +903,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/strings@npm:5.4.0, @ethersproject/strings@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/strings@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/constants": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - checksum: 10c0/24c41487fbbf767e798c46462ef25be1cf379bc79477595ad364ce599e8c968aab73a9a8b6dedcaeffc4fbe2a1a418260124b384e57f7b46a17d7ed10266bf82 - languageName: node - linkType: hard - "@ethersproject/strings@npm:5.7.0, @ethersproject/strings@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/strings@npm:5.7.0" @@ -1175,23 +925,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:5.4.0, @ethersproject/transactions@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/transactions@npm:5.4.0" - dependencies: - "@ethersproject/address": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/constants": "npm:^5.4.0" - "@ethersproject/keccak256": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/rlp": "npm:^5.4.0" - "@ethersproject/signing-key": "npm:^5.4.0" - checksum: 10c0/28fe783d4e9344407621f2f1b887147888b624cc6cee9ebb3c51c876570ea77fa24e5be37a3313d85ccda8d186a3fa1259dd871c708fae71a0c50ceeb512ba74 - languageName: node - linkType: hard - "@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/transactions@npm:5.7.0" @@ -1226,17 +959,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/units@npm:5.4.0": - version: 5.4.0 - resolution: "@ethersproject/units@npm:5.4.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/constants": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - checksum: 10c0/f376fad78c99c13ac51924b28f415651b9af40f9eeb336a5cfd8f5654f2ad4f62b57ab8d22cddb68d14a14deb3921dbccb8bb2ea4e9b7a8f5f4a5838a3eb38b9 - languageName: node - linkType: hard - "@ethersproject/units@npm:5.7.0": version: 5.7.0 resolution: "@ethersproject/units@npm:5.7.0" @@ -1259,29 +981,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wallet@npm:5.4.0": - version: 5.4.0 - resolution: "@ethersproject/wallet@npm:5.4.0" - dependencies: - "@ethersproject/abstract-provider": "npm:^5.4.0" - "@ethersproject/abstract-signer": "npm:^5.4.0" - "@ethersproject/address": "npm:^5.4.0" - "@ethersproject/bignumber": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/hash": "npm:^5.4.0" - "@ethersproject/hdnode": "npm:^5.4.0" - "@ethersproject/json-wallets": "npm:^5.4.0" - "@ethersproject/keccak256": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/random": "npm:^5.4.0" - "@ethersproject/signing-key": "npm:^5.4.0" - "@ethersproject/transactions": "npm:^5.4.0" - "@ethersproject/wordlists": "npm:^5.4.0" - checksum: 10c0/c188ed407ef191d7b1f857cc5d8388b10911164658ed8b798f5f5d6787fbe96cc471eb701965ddb59d1d6ec57493aea042f93319c2c08920a4f771f4a2470a8d - languageName: node - linkType: hard - "@ethersproject/wallet@npm:5.7.0": version: 5.7.0 resolution: "@ethersproject/wallet@npm:5.7.0" @@ -1328,19 +1027,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/web@npm:5.4.0, @ethersproject/web@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/web@npm:5.4.0" - dependencies: - "@ethersproject/base64": "npm:^5.4.0" - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - checksum: 10c0/b71caefbe4fd851d2b6fa7008e3f81074d718f6829e98d0d4046b8fe32fa0543fa77c7fa49e5efc3304b4b46c691cdeb550f2e1a1a3cca3a821a40a07866a5a1 - languageName: node - linkType: hard - "@ethersproject/web@npm:5.7.1, @ethersproject/web@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/web@npm:5.7.1" @@ -1367,19 +1053,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wordlists@npm:5.4.0, @ethersproject/wordlists@npm:^5.4.0": - version: 5.4.0 - resolution: "@ethersproject/wordlists@npm:5.4.0" - dependencies: - "@ethersproject/bytes": "npm:^5.4.0" - "@ethersproject/hash": "npm:^5.4.0" - "@ethersproject/logger": "npm:^5.4.0" - "@ethersproject/properties": "npm:^5.4.0" - "@ethersproject/strings": "npm:^5.4.0" - checksum: 10c0/ad3c1c2f60bf7914c7beaf0a9d3731eaafc2d630d2e247d385aa52c8c4795e73549f0eca04428113df8a2238b38ba5837687fbb92522a2423fb5fef613252f6c - languageName: node - linkType: hard - "@ethersproject/wordlists@npm:5.7.0, @ethersproject/wordlists@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/wordlists@npm:5.7.0" @@ -1491,17 +1164,55 @@ __metadata: languageName: node linkType: hard -"@keep-network/hardhat-helpers@github:threshold-network/hardhat-helpers#v0.6.0-pre.21": - version: 0.6.0-pre.21 - resolution: "@keep-network/hardhat-helpers@https://github.com/threshold-network/hardhat-helpers.git#commit=beeec4afb3f41f6c46e1499e899d814248771a8e" +"@jridgewell/resolve-uri@npm:^3.0.3": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10": + version: 1.6.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.6.0" + checksum: 10c0/b5be700e45a775f218589c3466c4ffea630582b4988657652da464e5ab8a7d18bf928ee4fd2363fb346ede4bea9c6ff0bae05a538358c4565ece6199531b5f72 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.0.3" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + checksum: 10c0/fa425b606d7c7ee5bfa6a31a7b050dd5814b4082f318e0e4190f991902181b4330f43f4805db1dd4f2433fd0ed9cc7a7b9c2683f1deeab1df1b0a98b1e24055b + languageName: node + linkType: hard + +"@keep-network/hardhat-helpers@npm:0.7.2": + version: 0.7.2 + resolution: "@keep-network/hardhat-helpers@npm:0.7.2" peerDependencies: - "@nomiclabs/hardhat-ethers": ^2.1.0 - "@nomiclabs/hardhat-etherscan": ^3.1.0 - "@openzeppelin/hardhat-upgrades": ^1.22.0 - ethers: ^5.6.9 - hardhat: ^2.10.0 - hardhat-deploy: ^0.11.11 - checksum: 10c0/2c7828b30ae4a824a0f31a9ed9fbed323af82ac4daea06480143e7b4265b9a95982b4967cfb2276e2c1437ce2482f3fe04737de79f9103457e62a74c6edba095 + "@nomicfoundation/hardhat-ethers": ^3.0.5 + "@nomicfoundation/hardhat-verify": ^2.0.3 + "@openzeppelin/hardhat-upgrades": ^3.0.2 + ethers: ^6.10.0 + hardhat: ^2.19.4 + hardhat-deploy: ^0.11.45 + checksum: 10c0/55949a24dd5425629cd914d17c60aaced658c84820f5eb6cfb27ab8e1e231afc17d3a360b03700ebde11c10013e7eee8fe3f45bc7866121c80ffbdaf1f6d9185 + languageName: node + linkType: hard + +"@keep-network/hardhat-helpers@patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch": + version: 0.7.2 + resolution: "@keep-network/hardhat-helpers@patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch::version=0.7.2&hash=b77b8f" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.5 + "@nomicfoundation/hardhat-verify": ^2.0.3 + "@openzeppelin/hardhat-upgrades": ^3.0.2 + ethers: ^6.10.0 + hardhat: ^2.19.4 + hardhat-deploy: ^0.11.45 + checksum: 10c0/5705dad93a94d9f571853a325c7134bf2bddcb2fd9811e330e1744033449628175adc2b9e60c0987622b9a465b2744fa8f766ef7114ffee8370b920b4ad5d4c0 languageName: node linkType: hard @@ -1521,21 +1232,21 @@ __metadata: version: 0.0.0-use.local resolution: "@keep-network/random-beacon@workspace:." dependencies: - "@keep-network/hardhat-helpers": "github:threshold-network/hardhat-helpers#v0.6.0-pre.21" + "@keep-network/hardhat-helpers": "patch:@keep-network/hardhat-helpers@npm%3A0.7.2#~/.yarn/patches/@keep-network-hardhat-helpers-npm-0.7.2-086cf3da54.patch" "@keep-network/hardhat-local-networks-config": "github:threshold-network/hardhat-local-networks-config#6dff5bc8648127ca5d8696c321076bddb6d4142a" "@keep-network/sortition-pools": "npm:^2.0.0-pre.16" - "@nomicfoundation/hardhat-chai-matchers": "npm:^1.0.6" + "@nomicfoundation/hardhat-chai-matchers": "npm:^2.1.2" + "@nomicfoundation/hardhat-ethers": "npm:^3.1.3" "@nomicfoundation/hardhat-network-helpers": "npm:^1.1.2" "@nomicfoundation/hardhat-verify": "npm:^2.1.3" - "@nomiclabs/hardhat-ethers": "npm:^2.0.6" "@openzeppelin/contracts": "npm:4.7.3" - "@openzeppelin/hardhat-upgrades": "npm:^1.20.0" + "@openzeppelin/hardhat-upgrades": "patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch" "@stylistic/eslint-plugin": "npm:^5.10.0" - "@tenderly/hardhat-tenderly": "npm:1.0.12" + "@tenderly/hardhat-tenderly": "npm:2.1.1" "@thesis/solidity-contracts": "github:thesis/solidity-contracts#4985bcf" "@threshold-network/solidity-contracts": "npm:1.3.0-dev.14" - "@typechain/ethers-v5": "npm:^11.1.2" - "@typechain/hardhat": "npm:^7.0.0" + "@typechain/ethers-v6": "patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch" + "@typechain/hardhat": "npm:^9.1.0" "@types/chai": "npm:^4.3.20" "@types/mocha": "npm:^10.0.10" "@types/node": "npm:^24.13.3" @@ -1544,7 +1255,7 @@ __metadata: eslint-import-resolver-typescript: "npm:^4.4.5" eslint-plugin-import-x: "npm:^4.17.1" eslint-plugin-no-only-tests: "npm:^3.4.0" - ethers: "npm:^5.4.7" + ethers: "npm:^6.17.0" fs-extra: "npm:^11.2.0" globals: "npm:^17.12.0" hardhat: "npm:2.29.0" @@ -1611,6 +1322,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" + dependencies: + "@noble/hashes": "npm:1.3.2" + checksum: 10c0/0bac7d1bbfb3c2286910b02598addd33243cb97c3f36f987ecc927a4be8d7d88e0fcb12b0f0ef8a044e7307d1844dd5c49bb724bfa0a79c8ec50ba60768c97f6 + languageName: node + linkType: hard + "@noble/curves@npm:1.4.2, @noble/curves@npm:~1.4.0": version: 1.4.2 resolution: "@noble/curves@npm:1.4.2" @@ -1654,6 +1374,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.3.2": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: 10c0/2482cce3bce6a596626f94ca296e21378e7a5d4c09597cbc46e65ffacc3d64c8df73111f2265444e36a3168208628258bbbaccba2ef24f65f58b2417638a20e7 + languageName: node + linkType: hard + "@noble/hashes@npm:1.4.0, @noble/hashes@npm:~1.4.0": version: 1.4.0 resolution: "@noble/hashes@npm:1.4.0" @@ -1746,21 +1473,33 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/hardhat-chai-matchers@npm:^1.0.6": - version: 1.0.6 - resolution: "@nomicfoundation/hardhat-chai-matchers@npm:1.0.6" +"@nomicfoundation/hardhat-chai-matchers@npm:^2.1.2": + version: 2.1.2 + resolution: "@nomicfoundation/hardhat-chai-matchers@npm:2.1.2" dependencies: - "@ethersproject/abi": "npm:^5.1.2" "@types/chai-as-promised": "npm:^7.1.3" chai-as-promised: "npm:^7.1.1" deep-eql: "npm:^4.0.1" ordinal: "npm:^1.0.3" peerDependencies: - "@nomiclabs/hardhat-ethers": ^2.0.0 + "@nomicfoundation/hardhat-ethers": ^3.1.0 chai: ^4.2.0 - ethers: ^5.0.0 - hardhat: ^2.9.4 - checksum: 10c0/d5e0327aee476ddd1ff25ab6d0fb47af0ccf081a9ff072499dccba7656eea9911aab4bd7e19fe46e5dfb920d2690df3c64dbb324a83e15f8ec9dd13a56ebbe66 + ethers: ^6.14.0 + hardhat: ^2.26.0 + checksum: 10c0/ed51e9d5e20869fc50f13ee7c8ad65e9531a6222a8b19c1afe21c28d563c8d2361c2f6f36a0c8a7b4e9b6c9c8df9f1878d6512b27919e18ea4e71bf28249bf86 + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-ethers@npm:^3.0.4, @nomicfoundation/hardhat-ethers@npm:^3.1.3": + version: 3.1.3 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.1.3" + dependencies: + debug: "npm:^4.1.1" + lodash.isequal: "npm:^4.5.0" + peerDependencies: + ethers: ^6.14.0 + hardhat: ^2.28.0 + checksum: 10c0/77a20741634a4028324cf329cac28205eff4a318ab92b0f42af4e714ebaab97a760bdba551fec446f4cea171a8964a6a89d19f33105fb8c8538d779a8a975093 languageName: node linkType: hard @@ -1803,6 +1542,15 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/slang@npm:^0.18.3": + version: 0.18.3 + resolution: "@nomicfoundation/slang@npm:0.18.3" + dependencies: + "@bytecodealliance/preview2-shim": "npm:0.17.0" + checksum: 10c0/68036dd38f953451c4b5825600cd44f46931608a9905811fb1d977fac00be5f16b1a39f2f2a0c65f4bbd064d81c05f44f5cd79e626798035815511de89c3b6d0 + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2": version: 0.1.2 resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.2" @@ -1882,16 +1630,6 @@ __metadata: languageName: node linkType: hard -"@nomiclabs/hardhat-ethers@npm:^2.0.6": - version: 2.0.6 - resolution: "@nomiclabs/hardhat-ethers@npm:2.0.6" - peerDependencies: - ethers: ^5.0.0 - hardhat: ^2.0.0 - checksum: 10c0/f8bad2d51f05bc65ebd0061e80a3a3e9f3731bdabde3881aa913c94868916c01c3bef4835a170538a56544cd361f7dc06bdf38e6c46ca20e29c854c0038da8d5 - languageName: node - linkType: hard - "@npmcli/agent@npm:^4.0.0": version: 4.0.0 resolution: "@npmcli/agent@npm:4.0.0" @@ -1949,40 +1687,127 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/hardhat-upgrades@npm:^1.20.0": - version: 1.20.0 - resolution: "@openzeppelin/hardhat-upgrades@npm:1.20.0" +"@openzeppelin/defender-admin-client@npm:^1.52.0": + version: 1.54.6 + resolution: "@openzeppelin/defender-admin-client@npm:1.54.6" + dependencies: + "@openzeppelin/defender-base-client": "npm:1.54.6" + axios: "npm:^1.4.0" + ethers: "npm:^5.7.2" + lodash: "npm:^4.17.19" + node-fetch: "npm:^2.6.0" + checksum: 10c0/784d7d0eee87916546654f8265f0823401b18f34f0c168daa5c3c353000b5a8e595edc26a384a5f4052dedf2602947e58620442c6f1f46760bfb99a77a5ae69d + languageName: node + linkType: hard + +"@openzeppelin/defender-base-client@npm:1.54.6, @openzeppelin/defender-base-client@npm:^1.52.0": + version: 1.54.6 + resolution: "@openzeppelin/defender-base-client@npm:1.54.6" + dependencies: + amazon-cognito-identity-js: "npm:^6.0.1" + async-retry: "npm:^1.3.3" + axios: "npm:^1.4.0" + lodash: "npm:^4.17.19" + node-fetch: "npm:^2.6.0" + checksum: 10c0/adeac961ae8e06e620ff6ff227090180613fbad233bbed962ae1d1769f1a936cdba24b952a1c10fec69bf9695a7faf7572fe86fd174198b86e26706391784bef + languageName: node + linkType: hard + +"@openzeppelin/defender-sdk-base-client@npm:^1.15.2, @openzeppelin/defender-sdk-base-client@npm:^1.8.0": + version: 1.15.2 + resolution: "@openzeppelin/defender-sdk-base-client@npm:1.15.2" + dependencies: + amazon-cognito-identity-js: "npm:^6.3.6" + async-retry: "npm:^1.3.3" + checksum: 10c0/cb1f5a286564b7f4da0c6f4b21f032b7e09697c2e476c2cf3d957287bc9dc880d0f1c2a4b21d42bc8246a99ea117ce39cfff6fd18f20ca63ac3dc859a43b62a1 + languageName: node + linkType: hard + +"@openzeppelin/defender-sdk-deploy-client@npm:^1.8.0": + version: 1.15.2 + resolution: "@openzeppelin/defender-sdk-deploy-client@npm:1.15.2" dependencies: - "@openzeppelin/upgrades-core": "npm:^1.18.0" + "@openzeppelin/defender-sdk-base-client": "npm:^1.15.2" + axios: "npm:^1.7.2" + lodash: "npm:^4.17.21" + checksum: 10c0/af3db2976d14bdeb7b24e109209a37fcd98ab14176ebd62f0543d0dff552fd9359b382e35c2698315e195c42f55b2bc52b2aea0f598a070ac0a24274a1ba93d9 + languageName: node + linkType: hard + +"@openzeppelin/hardhat-upgrades@npm:2.5.1": + version: 2.5.1 + resolution: "@openzeppelin/hardhat-upgrades@npm:2.5.1" + dependencies: + "@openzeppelin/defender-admin-client": "npm:^1.52.0" + "@openzeppelin/defender-base-client": "npm:^1.52.0" + "@openzeppelin/defender-sdk-base-client": "npm:^1.8.0" + "@openzeppelin/defender-sdk-deploy-client": "npm:^1.8.0" + "@openzeppelin/upgrades-core": "npm:^1.31.2" chalk: "npm:^4.1.0" debug: "npm:^4.1.1" + ethereumjs-util: "npm:^7.1.5" proper-lockfile: "npm:^4.1.1" + undici: "npm:^5.14.0" peerDependencies: - "@nomiclabs/hardhat-ethers": ^2.0.0 - "@nomiclabs/hardhat-etherscan": ^3.1.0 - ethers: ^5.0.5 + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-verify": ^1.1.0 + ethers: ^6.6.0 hardhat: ^2.0.2 peerDependenciesMeta: - "@nomiclabs/harhdat-etherscan": + "@nomicfoundation/hardhat-verify": optional: true bin: migrate-oz-cli-project: dist/scripts/migrate-oz-cli-project.js - checksum: 10c0/5c8cfeaf6e05a7a3aada40f12ae8367fdd590ead623b2f30ade59cf2b6e29bd92f9b105e2f00beec6a5933969f789a644c7563048b4c1e4f6c14ad50143766a5 + checksum: 10c0/3c032048a2d58fd59a1287234c5d045e7b231afb6ed3d906f9d5751b93f29dd5f1cbfdd0898c62cc8397ca111a98b7fa032cc93929adbc2072d1ad8bfbcded72 languageName: node linkType: hard -"@openzeppelin/upgrades-core@npm:^1.18.0": - version: 1.19.1 - resolution: "@openzeppelin/upgrades-core@npm:1.19.1" +"@openzeppelin/hardhat-upgrades@patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch": + version: 2.5.1 + resolution: "@openzeppelin/hardhat-upgrades@patch:@openzeppelin/hardhat-upgrades@npm%3A2.5.1#~/.yarn/patches/@openzeppelin-hardhat-upgrades-npm-2.5.1-etherscan-v2.patch::version=2.5.1&hash=6d2f71" dependencies: - cbor: "npm:^8.0.0" + "@openzeppelin/defender-admin-client": "npm:^1.52.0" + "@openzeppelin/defender-base-client": "npm:^1.52.0" + "@openzeppelin/defender-sdk-base-client": "npm:^1.8.0" + "@openzeppelin/defender-sdk-deploy-client": "npm:^1.8.0" + "@openzeppelin/upgrades-core": "npm:^1.31.2" chalk: "npm:^4.1.0" - compare-versions: "npm:^5.0.0" + debug: "npm:^4.1.1" + ethereumjs-util: "npm:^7.1.5" + proper-lockfile: "npm:^4.1.1" + undici: "npm:^5.14.0" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@nomicfoundation/hardhat-verify": ^1.1.0 + ethers: ^6.6.0 + hardhat: ^2.0.2 + peerDependenciesMeta: + "@nomicfoundation/hardhat-verify": + optional: true + bin: + migrate-oz-cli-project: dist/scripts/migrate-oz-cli-project.js + checksum: 10c0/8a15e1ed75c3833f501bca1b53baf56babc4d6055576e92d3b18752a92352dbe7a39c7836d49bff0ba786c7c2fc842773da70aee8a7765c7fed8dd2530295dd4 + languageName: node + linkType: hard + +"@openzeppelin/upgrades-core@npm:^1.31.2": + version: 1.46.0 + resolution: "@openzeppelin/upgrades-core@npm:1.46.0" + dependencies: + "@nomicfoundation/slang": "npm:^0.18.3" + bignumber.js: "npm:^9.1.2" + cbor: "npm:^10.0.0" + chalk: "npm:^4.1.0" + compare-versions: "npm:^6.0.0" debug: "npm:^4.1.1" ethereumjs-util: "npm:^7.0.3" + minimatch: "npm:^10.2.5" + minimist: "npm:^1.2.7" proper-lockfile: "npm:^4.1.1" - solidity-ast: "npm:^0.4.15" - checksum: 10c0/a46d72034bf0599a5fc2be424dccaac3baeaca24bbe8d95da014e5b5cc1ca2ffec5a0b69ee215ad23eacbf51d873e60dd6c2776f07eb475e5471f2562d02876c + solidity-ast: "npm:^0.4.60" + bin: + openzeppelin-upgrades-core: dist/cli/cli.js + checksum: 10c0/11b938ef442cecb8441a8022f67b5fb3e87e84f521b8d33d2b1f94ef954382f8538e59afa58e23cd5ec29f39446ea67f428d30416b8a03671dc509aff87167e4 languageName: node linkType: hard @@ -2193,6 +2018,15 @@ __metadata: languageName: node linkType: hard +"@smithy/types@npm:^4.17.2": + version: 4.18.0 + resolution: "@smithy/types@npm:4.18.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10c0/f948eaf2c6004ce919a5a203615da4d2d4923465df764c2f6ab982fcacde10c81e1fd23c40f983387459ffdad056f8e827ebecaa776a4331ed4f6431ad8bdd34 + languageName: node + linkType: hard + "@solidity-parser/parser@npm:^0.20.1, @solidity-parser/parser@npm:^0.20.2": version: 0.20.2 resolution: "@solidity-parser/parser@npm:0.20.2" @@ -2225,16 +2059,24 @@ __metadata: languageName: node linkType: hard -"@tenderly/hardhat-tenderly@npm:1.0.12": - version: 1.0.12 - resolution: "@tenderly/hardhat-tenderly@npm:1.0.12" +"@tenderly/hardhat-tenderly@npm:2.1.1": + version: 2.1.1 + resolution: "@tenderly/hardhat-tenderly@npm:2.1.1" dependencies: - axios: "npm:^0.21.1" - fs-extra: "npm:^9.0.1" - js-yaml: "npm:^3.14.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@nomicfoundation/hardhat-ethers": "npm:^3.0.4" + axios: "npm:^0.27.2" + ethers: "npm:^6.8.1" + fs-extra: "npm:^10.1.0" + hardhat-deploy: "npm:^0.11.43" + tenderly: "npm:^0.8.0" + ts-node: "npm:^10.9.1" + tslog: "npm:^4.3.1" + typescript: "npm:^5.2.2" peerDependencies: - hardhat: ^2.0.3 - checksum: 10c0/6834011e41215508f7086767ed4e32e0d7d4300c70d8a9e4e511c86b9cf40972a7f380d8abd9fc6d0162558ee03171d3442f8f2eab7303d9680c55d1d8683de6 + ethers: ^6.8.1 + hardhat: ^2.19.0 + checksum: 10c0/f51fdef7e3b857d5f7f6bc0f139f2b565641dc9f31805376245d65af815493a79cf60a6888f3a70f0d29c55eabed4fe972e7ab6ac138a13d4fb71046d60a671f languageName: node linkType: hard @@ -2258,6 +2100,17 @@ __metadata: languageName: node linkType: hard +"@threshold-network/solidity-contracts@patch:@threshold-network/solidity-contracts@npm%3A1.3.0-dev.14#./.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch::locator=%40keep-network%2Frandom-beacon%40workspace%3A.": + version: 1.3.0-dev.14 + resolution: "@threshold-network/solidity-contracts@patch:@threshold-network/solidity-contracts@npm%3A1.3.0-dev.14#./.yarn/patches/@threshold-network-solidity-contracts-npm-1.3.0-dev.14-ethers-v6.patch::version=1.3.0-dev.14&hash=fd9350&locator=%40keep-network%2Frandom-beacon%40workspace%3A." + dependencies: + "@openzeppelin/contracts": "npm:~4.5.0" + "@openzeppelin/contracts-upgradeable": "npm:~4.5.2" + "@thesis/solidity-contracts": "github:thesis/solidity-contracts#4985bcf" + checksum: 10c0/a6a7d2facb4e5ee695b55706dfe2c47eeca68bc3e73a3e76eaffa4df5e677360a33282101a25209aada1d83c1234839a013f93d784bb9a9c435b24f1d3cbf902 + languageName: node + linkType: hard + "@tsconfig/node10@npm:^1.0.7": version: 1.0.8 resolution: "@tsconfig/node10@npm:1.0.8" @@ -2295,35 +2148,45 @@ __metadata: languageName: node linkType: hard -"@typechain/ethers-v5@npm:^11.1.2": - version: 11.1.2 - resolution: "@typechain/ethers-v5@npm:11.1.2" +"@typechain/ethers-v6@npm:0.5.1": + version: 0.5.1 + resolution: "@typechain/ethers-v6@npm:0.5.1" dependencies: lodash: "npm:^4.17.15" ts-essentials: "npm:^7.0.1" peerDependencies: - "@ethersproject/abi": ^5.0.0 - "@ethersproject/providers": ^5.0.0 - ethers: ^5.1.3 + ethers: 6.x typechain: ^8.3.2 - typescript: ">=4.3.0" - checksum: 10c0/5da6109ded6e02701e5ad718479b8a316011c5366adcbfbd8b7ee1c149c02960714c6906d823d76ab1839046aad127f9c8793f4b36a65f4299d7ce4314265ae1 + typescript: ">=4.7.0" + checksum: 10c0/f3c80151c07e01adbf520e0854426649edb0ee540920569487dd8da7eca2fa8615710f4c0eda008e7afdf255fbb8dfdebf721a5d324a4dffeb087611d9bd64b9 languageName: node linkType: hard -"@typechain/hardhat@npm:^7.0.0": - version: 7.0.0 - resolution: "@typechain/hardhat@npm:7.0.0" +"@typechain/ethers-v6@patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch": + version: 0.5.1 + resolution: "@typechain/ethers-v6@patch:@typechain/ethers-v6@npm%3A0.5.1#~/.yarn/patches/@typechain-ethers-v6-npm-0.5.1-e825560376.patch::version=0.5.1&hash=496509" + dependencies: + lodash: "npm:^4.17.15" + ts-essentials: "npm:^7.0.1" + peerDependencies: + ethers: 6.x + typechain: ^8.3.2 + typescript: ">=4.7.0" + checksum: 10c0/cbf3447ec6ac2351df39f69c11066d8f3e48d1c9792281127499cc53da66b537db97e4a4385c925ab9c2fe04ea25912a126bd71f28564a93343d4f1c901f764b + languageName: node + linkType: hard + +"@typechain/hardhat@npm:^9.1.0": + version: 9.1.0 + resolution: "@typechain/hardhat@npm:9.1.0" dependencies: fs-extra: "npm:^9.1.0" peerDependencies: - "@ethersproject/abi": ^5.4.7 - "@ethersproject/providers": ^5.4.7 - "@typechain/ethers-v5": ^11.0.0 - ethers: ^5.4.7 + "@typechain/ethers-v6": ^0.5.1 + ethers: ^6.1.0 hardhat: ^2.9.9 - typechain: ^8.2.0 - checksum: 10c0/80732203ec94fd6933eedbef24d2b74ce167e0bdaf697ca1a98edbcb88775814a02e1e0fabdb2fd1e53d53730204fcad392580b42c0b47beeb30c403535dd652 + typechain: ^8.3.2 + checksum: 10c0/3a1220efefc7b02ca335696167f6c5332a33ff3fbf9f20552468566a1760f76bc88d330683e97ca6213eb9518a2a901391c31c84c0548006b72bd2ec62d4af9c languageName: node linkType: hard @@ -2401,6 +2264,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:22.7.5": + version: 22.7.5 + resolution: "@types/node@npm:22.7.5" + dependencies: + undici-types: "npm:~6.19.2" + checksum: 10c0/cf11f74f1a26053ec58066616e3a8685b6bcd7259bc569738b8f752009f9f0f7f85a1b2d24908e5b0f752482d1e8b6babdf1fbb25758711ec7bb9500bfcd6e60 + languageName: node + linkType: hard + "@types/node@npm:^24.13.3": version: 24.13.3 resolution: "@types/node@npm:24.13.3" @@ -2426,6 +2298,13 @@ __metadata: languageName: node linkType: hard +"@types/qs@npm:^6.9.7": + version: 6.14.0 + resolution: "@types/qs@npm:6.14.0" + checksum: 10c0/5b3036df6e507483869cdb3858201b2e0b64b4793dc4974f188caa5b5732f2333ab9db45c08157975054d3b070788b35088b4bc60257ae263885016ee2131310 + languageName: node + linkType: hard + "@types/secp256k1@npm:^4.0.1": version: 4.0.3 resolution: "@types/secp256k1@npm:4.0.3" @@ -2813,6 +2692,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: 10c0/444f4eefa1e602cbc4f2a3c644bc990f93fd982b148425fee17634da510586fc09da940dcf8ace1b2d001453c07ff042e55f7a0482b3cc9372bf1ef75479090c + languageName: node + linkType: hard + "agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -2875,6 +2761,19 @@ __metadata: languageName: node linkType: hard +"amazon-cognito-identity-js@npm:^6.0.1, amazon-cognito-identity-js@npm:^6.3.6": + version: 6.3.21 + resolution: "amazon-cognito-identity-js@npm:6.3.21" + dependencies: + "@aws-crypto/sha256-js": "npm:1.2.2" + buffer: "npm:4.9.2" + fast-base64-decode: "npm:^1.0.0" + isomorphic-unfetch: "npm:^3.0.0" + js-cookie: "npm:^3.0.7" + checksum: 10c0/c7541a70f5fc7a9cdc9642dec5c223420c4719219a24eab05decb1292741ebd82e4746dccc396f26436550896f5aa249311c4628f2b0f40ef4b436d50c05a16d + languageName: node + linkType: hard + "ansi-align@npm:^3.0.0": version: 3.0.1 resolution: "ansi-align@npm:3.0.1" @@ -2956,15 +2855,6 @@ __metadata: languageName: node linkType: hard -"argparse@npm:^1.0.7": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: "npm:~1.0.2" - checksum: 10c0/b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -3021,6 +2911,15 @@ __metadata: languageName: node linkType: hard +"async-retry@npm:^1.3.3": + version: 1.3.3 + resolution: "async-retry@npm:1.3.3" + dependencies: + retry: "npm:0.13.1" + checksum: 10c0/cabced4fb46f8737b95cc88dc9c0ff42656c62dc83ce0650864e891b6c155a063af08d62c446269b51256f6fbcb69a6563b80e76d0ea4a5117b0c0377b6b19d8 + languageName: node + linkType: hard + "asynckit@npm:^0.4.0": version: 0.4.0 resolution: "asynckit@npm:0.4.0" @@ -3035,24 +2934,15 @@ __metadata: languageName: node linkType: hard -"axios@npm:^0.21.1": - version: 0.21.4 - resolution: "axios@npm:0.21.4" - dependencies: - follow-redirects: "npm:^1.14.0" - checksum: 10c0/fbcff55ec68f71f02d3773d467db2fcecdf04e749826c82c2427a232f9eba63242150a05f15af9ef15818352b814257541155de0281f8fb2b7e8a5b79f7f2142 - languageName: node - linkType: hard - -"axios@npm:^1.6.7": - version: 1.18.1 - resolution: "axios@npm:1.18.1" +"axios@npm:^1.8.4": + version: 1.20.0 + resolution: "axios@npm:1.20.0" dependencies: follow-redirects: "npm:^1.16.0" - form-data: "npm:^4.0.5" + form-data: "npm:^4.0.6" https-proxy-agent: "npm:^5.0.1" proxy-from-env: "npm:^2.1.0" - checksum: 10c0/9d9378a3af0d0ad730a52ad9d15ec7201f3926ad6e7e8bbffc5ae21ca2835ad11d1d9598698f5dd9718917486039f55ea1d7dc23d8e44fa827a55cc3262c02fc + checksum: 10c0/976088acf532286356f4c2e65df1ef47ba7da3936d83e928d0d64357bbf5370456abd3eb5826c15df322335fcb1fe200d4a84b4fcf20ffccdd63b40d80fa495c languageName: node linkType: hard @@ -3079,6 +2969,13 @@ __metadata: languageName: node linkType: hard +"base64-js@npm:^1.0.2": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf + languageName: node + linkType: hard + "bech32@npm:1.1.4": version: 1.1.4 resolution: "bech32@npm:1.1.4" @@ -3101,6 +2998,13 @@ __metadata: languageName: node linkType: hard +"bignumber.js@npm:^9.1.2": + version: 9.3.1 + resolution: "bignumber.js@npm:9.3.1" + checksum: 10c0/61342ba5fe1c10887f0ecf5be02ff6709271481aff48631f86b4d37d55a99b87ce441cfd54df3d16d10ee07ceab7e272fc0be430c657ffafbbbf7b7d631efb75 + languageName: node + linkType: hard + "binary-extensions@npm:^2.0.0": version: 2.2.0 resolution: "binary-extensions@npm:2.2.0" @@ -3267,6 +3171,17 @@ __metadata: languageName: node linkType: hard +"buffer@npm:4.9.2": + version: 4.9.2 + resolution: "buffer@npm:4.9.2" + dependencies: + base64-js: "npm:^1.0.2" + ieee754: "npm:^1.1.4" + isarray: "npm:^1.0.0" + checksum: 10c0/dc443d7e7caab23816b58aacdde710b72f525ad6eecd7d738fcaa29f6d6c12e8d9c13fed7219fd502be51ecf0615f5c077d4bdc6f9308dde2e53f8e5393c5b21 + languageName: node + linkType: hard + "bytes@npm:3.1.0": version: 3.1.0 resolution: "bytes@npm:3.1.0" @@ -3337,6 +3252,16 @@ __metadata: languageName: node linkType: hard +"call-bound@npm:^1.0.2": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 + languageName: node + linkType: hard + "callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -3351,7 +3276,16 @@ __metadata: languageName: node linkType: hard -"cbor@npm:^8.0.0, cbor@npm:^8.1.0": +"cbor@npm:^10.0.0": + version: 10.0.12 + resolution: "cbor@npm:10.0.12" + dependencies: + nofilter: "npm:^3.0.2" + checksum: 10c0/4c197d783415cade31565725a5e6b2b967d856285eacdb0b5f5ec0687d93c12f2ee9c6cc05aa7be02e8bbf0fe3ba40d22be69b56bd2ab1be2cc0a59370f14246 + languageName: node + linkType: hard + +"cbor@npm:^8.1.0": version: 8.1.0 resolution: "cbor@npm:8.1.0" dependencies: @@ -3500,7 +3434,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.3": +"cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": version: 0.6.5 resolution: "cli-table3@npm:0.6.5" dependencies: @@ -3617,6 +3551,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^9.4.0": + version: 9.5.0 + resolution: "commander@npm:9.5.0" + checksum: 10c0/5f7784fbda2aaec39e89eb46f06a999e00224b3763dc65976e05929ec486e174fe9aac2655f03ba6a5e83875bd173be5283dc19309b7c65954701c02025b3c1d + languageName: node + linkType: hard + "comment-parser@npm:^1.4.1": version: 1.4.8 resolution: "comment-parser@npm:1.4.8" @@ -3624,10 +3565,10 @@ __metadata: languageName: node linkType: hard -"compare-versions@npm:^5.0.0": - version: 5.0.1 - resolution: "compare-versions@npm:5.0.1" - checksum: 10c0/11210f69725021bc80371f1cbcbb4353ba975cd503ffceb876f8bc043026ad1075bcc6eb7285ba862cadd000fc11d1f40c4d2477c87ceda03b8ab10d67a98eca +"compare-versions@npm:^6.0.0": + version: 6.1.1 + resolution: "compare-versions@npm:6.1.1" + checksum: 10c0/415205c7627f9e4f358f571266422980c9fe2d99086be0c9a48008ef7c771f32b0fbe8e97a441ffedc3910872f917a0675fe0fe3c3b6d331cda6d8690be06338 languageName: node linkType: hard @@ -3822,6 +3763,13 @@ __metadata: languageName: node linkType: hard +"define-lazy-prop@npm:^2.0.0": + version: 2.0.0 + resolution: "define-lazy-prop@npm:2.0.0" + checksum: 10c0/db6c63864a9d3b7dc9def55d52764968a5af296de87c1b2cc71d8be8142e445208071953649e0386a8cc37cfcf9a2067a47207f1eb9ff250c2a269658fdae422 + languageName: node + linkType: hard + "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -4172,16 +4120,6 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 - languageName: node - linkType: hard - "esquery@npm:^1.7.0": version: 1.7.0 resolution: "esquery@npm:1.7.0" @@ -4281,7 +4219,7 @@ __metadata: languageName: node linkType: hard -"ethereumjs-util@npm:^7.1.4": +"ethereumjs-util@npm:^7.1.4, ethereumjs-util@npm:^7.1.5": version: 7.1.5 resolution: "ethereumjs-util@npm:7.1.5" dependencies: @@ -4294,45 +4232,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^5.4.7": - version: 5.4.7 - resolution: "ethers@npm:5.4.7" - dependencies: - "@ethersproject/abi": "npm:5.4.1" - "@ethersproject/abstract-provider": "npm:5.4.1" - "@ethersproject/abstract-signer": "npm:5.4.1" - "@ethersproject/address": "npm:5.4.0" - "@ethersproject/base64": "npm:5.4.0" - "@ethersproject/basex": "npm:5.4.0" - "@ethersproject/bignumber": "npm:5.4.2" - "@ethersproject/bytes": "npm:5.4.0" - "@ethersproject/constants": "npm:5.4.0" - "@ethersproject/contracts": "npm:5.4.1" - "@ethersproject/hash": "npm:5.4.0" - "@ethersproject/hdnode": "npm:5.4.0" - "@ethersproject/json-wallets": "npm:5.4.0" - "@ethersproject/keccak256": "npm:5.4.0" - "@ethersproject/logger": "npm:5.4.1" - "@ethersproject/networks": "npm:5.4.2" - "@ethersproject/pbkdf2": "npm:5.4.0" - "@ethersproject/properties": "npm:5.4.1" - "@ethersproject/providers": "npm:5.4.5" - "@ethersproject/random": "npm:5.4.0" - "@ethersproject/rlp": "npm:5.4.0" - "@ethersproject/sha2": "npm:5.4.0" - "@ethersproject/signing-key": "npm:5.4.0" - "@ethersproject/solidity": "npm:5.4.0" - "@ethersproject/strings": "npm:5.4.0" - "@ethersproject/transactions": "npm:5.4.0" - "@ethersproject/units": "npm:5.4.0" - "@ethersproject/wallet": "npm:5.4.0" - "@ethersproject/web": "npm:5.4.0" - "@ethersproject/wordlists": "npm:5.4.0" - checksum: 10c0/189de436ebf69d0ce206a82ae9784709281d25c5db963639568d487fd1cc1cc5c016f007077583d08bbedfdea6198490a4da9416a5d7c647591de5b19bb16f94 - languageName: node - linkType: hard - -"ethers@npm:^5.7.0": +"ethers@npm:^5.7.0, ethers@npm:^5.7.2": version: 5.8.0 resolution: "ethers@npm:5.8.0" dependencies: @@ -4370,6 +4270,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.17.0, ethers@npm:^6.8.1": + version: 6.17.0 + resolution: "ethers@npm:6.17.0" + dependencies: + "@adraffy/ens-normalize": "npm:1.11.1" + "@noble/curves": "npm:1.2.0" + "@noble/hashes": "npm:1.3.2" + "@types/node": "npm:22.7.5" + aes-js: "npm:4.0.0-beta.5" + tslib: "npm:2.7.0" + ws: "npm:8.21.0" + checksum: 10c0/0a75f3b4cedaaddb95ba31fecdfca04202735564e66512f202069dd1a11946e01c310a158e3a1299b994274e9d9fe11db10c6f7997222a28d79dfecb8f1fd162 + languageName: node + linkType: hard + "ethers@npm:~5.7.0": version: 5.7.2 resolution: "ethers@npm:5.7.2" @@ -4433,6 +4348,13 @@ __metadata: languageName: node linkType: hard +"fast-base64-decode@npm:^1.0.0": + version: 1.0.0 + resolution: "fast-base64-decode@npm:1.0.0" + checksum: 10c0/6d8feab513222a463d1cb58d24e04d2e04b0791ac6559861f99543daaa590e2636d040d611b40a50799bfb5c5304265d05e3658b5adf6b841a50ef6bf833d821 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -4563,16 +4485,6 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.0": - version: 1.15.2 - resolution: "follow-redirects@npm:1.15.2" - peerDependenciesMeta: - debug: - optional: true - checksum: 10c0/da5932b70e63944d38eecaa16954bac4347036f08303c913d166eda74809d8797d38386e3a0eb1d2fe37d2aaff2764cce8e9dbd99459d860cf2cdfa237923b5f - languageName: node - linkType: hard - "follow-redirects@npm:^1.16.0": version: 1.16.0 resolution: "follow-redirects@npm:1.16.0" @@ -4611,7 +4523,7 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^4.0.5": +"form-data@npm:^4.0.6": version: 4.0.6 resolution: "form-data@npm:4.0.6" dependencies: @@ -4638,7 +4550,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^10.0.0": +"fs-extra@npm:^10.0.0, fs-extra@npm:^10.1.0": version: 10.1.0 resolution: "fs-extra@npm:10.1.0" dependencies: @@ -4671,7 +4583,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^9.0.1, fs-extra@npm:^9.1.0": +"fs-extra@npm:^9.1.0": version: 9.1.0 resolution: "fs-extra@npm:9.1.0" dependencies: @@ -4746,7 +4658,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.6": +"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": version: 1.3.1 resolution: "get-intrinsic@npm:1.3.1" dependencies: @@ -4938,6 +4850,38 @@ __metadata: languageName: node linkType: hard +"hardhat-deploy@npm:^0.11.43": + version: 0.11.45 + resolution: "hardhat-deploy@npm:0.11.45" + dependencies: + "@ethersproject/abi": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/contracts": "npm:^5.7.0" + "@ethersproject/providers": "npm:^5.7.2" + "@ethersproject/solidity": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/wallet": "npm:^5.7.0" + "@types/qs": "npm:^6.9.7" + axios: "npm:^0.21.1" + chalk: "npm:^4.1.2" + chokidar: "npm:^3.5.2" + debug: "npm:^4.3.2" + enquirer: "npm:^2.3.6" + ethers: "npm:^5.7.0" + form-data: "npm:^4.0.0" + fs-extra: "npm:^10.0.0" + match-all: "npm:^1.2.6" + murmur-128: "npm:^0.2.1" + qs: "npm:^6.9.4" + zksync-web3: "npm:^0.14.3" + checksum: 10c0/6171ffccd46bb21954ebf2303a00d35d3793ad7216adaaf2d6e1836ec9387583a34e1640ff93e0d2d89e61cd3b06454f40cb11573463d86900eb24a940ce3682 + languageName: node + linkType: hard + "hardhat-deploy@npm:^1.0.4": version: 1.0.4 resolution: "hardhat-deploy@npm:1.0.4" @@ -5249,6 +5193,13 @@ __metadata: languageName: node linkType: hard +"ieee754@npm:^1.1.4": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb + languageName: node + linkType: hard + "ignore@npm:^5.2.0, ignore@npm:^5.2.4": version: 5.3.2 resolution: "ignore@npm:5.3.2" @@ -5366,6 +5317,15 @@ __metadata: languageName: node linkType: hard +"is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": + version: 2.2.1 + resolution: "is-docker@npm:2.2.1" + bin: + is-docker: cli.js + checksum: 10c0/e828365958d155f90c409cdbe958f64051d99e8aedc2c8c4cd7c89dcf35329daed42f7b99346f7828df013e27deb8f721cf9408ba878c76eb9e8290235fbcdcc + languageName: node + linkType: hard + "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -5417,6 +5377,22 @@ __metadata: languageName: node linkType: hard +"is-wsl@npm:^2.2.0": + version: 2.2.0 + resolution: "is-wsl@npm:2.2.0" + dependencies: + is-docker: "npm:^2.0.0" + checksum: 10c0/a6fa2d370d21be487c0165c7a440d567274fbba1a817f2f0bfa41cc5e3af25041d84267baa22df66696956038a43973e72fca117918c91431920bdef490fa25e + languageName: node + linkType: hard + +"isarray@npm:^1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: 10c0/18b5be6669be53425f0b84098732670ed4e727e3af33bc7f948aac01782110eb9a18b3b329c5323bcdd3acdaae547ee077d3951317e7f133bff7105264b3003d + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -5431,6 +5407,16 @@ __metadata: languageName: node linkType: hard +"isomorphic-unfetch@npm:^3.0.0": + version: 3.1.0 + resolution: "isomorphic-unfetch@npm:3.1.0" + dependencies: + node-fetch: "npm:^2.6.1" + unfetch: "npm:^4.2.0" + checksum: 10c0/d3b61fca06304db692b7f76bdfd3a00f410e42cfa7403c3b250546bf71589d18cf2f355922f57198e4cc4a9872d3647b20397a5c3edf1a347c90d57c83cf2a89 + languageName: node + linkType: hard + "isows@npm:1.0.7": version: 1.0.7 resolution: "isows@npm:1.0.7" @@ -5453,10 +5439,10 @@ __metadata: languageName: node linkType: hard -"js-sha3@npm:0.5.7": - version: 0.5.7 - resolution: "js-sha3@npm:0.5.7" - checksum: 10c0/17b17d557f9d594ed36ba6c8cdc234bedd7b74ce4baf171e23a1f16b9a89b1527ae160e4eb1b836520acf5919b00732a22183fb00b7808702c36f646c1e9e973 +"js-cookie@npm:^3.0.7": + version: 3.0.8 + resolution: "js-cookie@npm:3.0.8" + checksum: 10c0/421912a4a55535bda32b3059835864e1182c3af5b4516df00a060edc1fa5a53d38bb8d5a91d5d305e396206f4fd11e829f17850aa5aa8164118c04d8ebf1ff5d languageName: node linkType: hard @@ -5474,18 +5460,6 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.14.0": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: "npm:^1.0.7" - esprima: "npm:^4.0.0" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/6746baaaeac312c4db8e75fa22331d9a04cccb7792d126ed8ce6a0bbcfef0cedaddd0c5098fade53db067c09fe00aa1c957674b4765610a8b06a5a189e46433b - languageName: node - linkType: hard - "js-yaml@npm:^4.1.0": version: 4.3.0 resolution: "js-yaml@npm:4.3.0" @@ -5620,6 +5594,13 @@ __metadata: languageName: node linkType: hard +"kleur@npm:^3.0.3": + version: 3.0.3 + resolution: "kleur@npm:3.0.3" + checksum: 10c0/cd3a0b8878e7d6d3799e54340efe3591ca787d9f95f109f28129bdd2915e37807bf8918bb295ab86afb8c82196beec5a1adcaf29042ce3f2bd932b038fe3aa4b + languageName: node + linkType: hard + "latest-version@npm:^7.0.0": version: 7.0.0 resolution: "latest-version@npm:7.0.0" @@ -5676,6 +5657,13 @@ __metadata: languageName: node linkType: hard +"lodash.isequal@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.isequal@npm:4.5.0" + checksum: 10c0/dfdb2356db19631a4b445d5f37868a095e2402292d59539a987f134a8778c62a2810c2452d11ae9e6dcac71fc9de40a6fedcb20e2952a15b431ad8b29e50e28f + languageName: node + linkType: hard + "lodash.truncate@npm:^4.4.2": version: 4.4.2 resolution: "lodash.truncate@npm:4.4.2" @@ -5690,7 +5678,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.21": +"lodash@npm:^4.17.19, lodash@npm:^4.17.21": version: 4.18.1 resolution: "lodash@npm:4.18.1" checksum: 10c0/757228fc68805c59789e82185135cf85f05d0b2d3d54631d680ca79ec21944ec8314d4533639a14b8bcfbd97a517e78960933041a5af17ecb693ec6eecb99a27 @@ -5919,6 +5907,13 @@ __metadata: languageName: node linkType: hard +"minimist@npm:^1.2.7": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 + languageName: node + linkType: hard + "minipass-collect@npm:^2.0.1": version: 2.0.1 resolution: "minipass-collect@npm:2.0.1" @@ -6116,6 +6111,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 + languageName: node + linkType: hard + "node-gyp-build@npm:^4.2.0": version: 4.5.0 resolution: "node-gyp-build@npm:4.5.0" @@ -6147,7 +6156,7 @@ __metadata: languageName: node linkType: hard -"nofilter@npm:^3.1.0": +"nofilter@npm:^3.0.2, nofilter@npm:^3.1.0": version: 3.1.0 resolution: "nofilter@npm:3.1.0" checksum: 10c0/92459f3864a067b347032263f0b536223cbfc98153913b5dce350cb39c8470bc1813366e41993f22c33cc6400c0f392aa324a4b51e24c22040635c1cdb046499 @@ -6186,6 +6195,13 @@ __metadata: languageName: node linkType: hard +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 + languageName: node + linkType: hard + "obliterator@npm:^1.6.1": version: 1.6.1 resolution: "obliterator@npm:1.6.1" @@ -6202,6 +6218,17 @@ __metadata: languageName: node linkType: hard +"open@npm:^8.4.0": + version: 8.4.2 + resolution: "open@npm:8.4.2" + dependencies: + define-lazy-prop: "npm:^2.0.0" + is-docker: "npm:^2.1.1" + is-wsl: "npm:^2.2.0" + checksum: 10c0/bb6b3a58401dacdb0aad14360626faf3fb7fba4b77816b373495988b724fb48941cad80c1b65d62bb31a17609b2cd91c41a181602caea597ca80dfbcc27e84c9 + languageName: node + linkType: hard + "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -6487,6 +6514,16 @@ __metadata: languageName: node linkType: hard +"prompts@npm:^2.4.2": + version: 2.4.2 + resolution: "prompts@npm:2.4.2" + dependencies: + kleur: "npm:^3.0.3" + sisteransi: "npm:^1.0.5" + checksum: 10c0/16f1ac2977b19fe2cf53f8411cc98db7a3c8b115c479b2ca5c82b5527cd937aa405fa04f9a5960abeb9daef53191b53b4d13e35c1f5d50e8718c76917c5f1ea4 + languageName: node + linkType: hard + "proper-lockfile@npm:^4.1.1": version: 4.1.2 resolution: "proper-lockfile@npm:4.1.2" @@ -6528,6 +6565,16 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.9.4": + version: 6.15.3 + resolution: "qs@npm:6.15.3" + dependencies: + es-define-property: "npm:^1.0.1" + side-channel: "npm:^1.1.1" + checksum: 10c0/8f3f6e45ece255347d57696628401cde29e9ec649fff698b53bd3150dea7cefdf33036e1bc1826b9f110bfa7cb0ec4ab9f5297eca628ce216c55af82c304e08e + languageName: node + linkType: hard + "quick-lru@npm:^5.1.1": version: 5.1.1 resolution: "quick-lru@npm:5.1.1" @@ -6691,6 +6738,13 @@ __metadata: languageName: node linkType: hard +"retry@npm:0.13.1": + version: 0.13.1 + resolution: "retry@npm:0.13.1" + checksum: 10c0/9ae822ee19db2163497e074ea919780b1efa00431d197c7afdb950e42bf109196774b92a49fc9821f0b8b328a98eea6017410bfc5e8a0fc19c85c6d11adb3772 + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -6851,6 +6905,54 @@ __metadata: languageName: node linkType: hard +"side-channel-list@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-list@npm:1.0.1" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.4" + checksum: 10c0/d346c787fd2f9f1c2fdea14f00e8250118db0e7596d85a6cb9faa75f105d31a73a8f7a341c93d7df2a2429098c3d37a77bd3be9e88c37094b8c01807bc77c7a2 + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185 + languageName: node + linkType: hard + +"side-channel@npm:^1.1.1": + version: 1.1.1 + resolution: "side-channel@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.4" + side-channel-list: "npm:^1.0.1" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10c0/dc0ab81d67f61bda9247d053ce93f41c3fd8ad2bdcb9cf9d8d2f8540d488f26d87a5e99ebfc07eea49ec025867b2452b705442d974b1478f0395e69f6bfb3270 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.2": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -6865,6 +6967,13 @@ __metadata: languageName: node linkType: hard +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: 10c0/230ac975cca485b7f6fe2b96a711aa62a6a26ead3e6fb8ba17c5a00d61b8bed0d7adc21f5626b70d7c33c62ff4e63933017a6462942c719d1980bb0b1207ad46 + languageName: node + linkType: hard + "slice-ansi@npm:^4.0.0": version: 4.0.0 resolution: "slice-ansi@npm:4.0.0" @@ -6952,13 +7061,6 @@ __metadata: languageName: node linkType: hard -"solidity-ast@npm:^0.4.15": - version: 0.4.32 - resolution: "solidity-ast@npm:0.4.32" - checksum: 10c0/01a15ecf07878d0bbe8549775c13fc6d3de1923086305d9a736579e0bb2bae6b6c4687f23f496965b65811387ceea4f62a809c9d2b7044412a6154a9771b5ea3 - languageName: node - linkType: hard - "solidity-ast@npm:^0.4.38": version: 0.4.46 resolution: "solidity-ast@npm:0.4.46" @@ -6966,6 +7068,13 @@ __metadata: languageName: node linkType: hard +"solidity-ast@npm:^0.4.60": + version: 0.4.62 + resolution: "solidity-ast@npm:0.4.62" + checksum: 10c0/8f9bfb41dddaa68e48d8620785cae43583a6711e79b132d3110f8cbf8f028a41004ca6ff8a3896f1e7f408932efb28b9f0390a67e729c12033ec95895430efeb + languageName: node + linkType: hard + "solidity-docgen@npm:^0.6.0-beta.35": version: 0.6.0-beta.35 resolution: "solidity-docgen@npm:0.6.0-beta.35" @@ -6995,13 +7104,6 @@ __metadata: languageName: node linkType: hard -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 10c0/ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb - languageName: node - linkType: hard - "ssri@npm:^13.0.0": version: 13.0.1 resolution: "ssri@npm:13.0.1" @@ -7182,6 +7284,29 @@ __metadata: languageName: node linkType: hard +"tenderly@npm:^0.8.0": + version: 0.8.0 + resolution: "tenderly@npm:0.8.0" + dependencies: + axios: "npm:^0.27.2" + cli-table3: "npm:^0.6.2" + commander: "npm:^9.4.0" + js-yaml: "npm:^4.1.0" + open: "npm:^8.4.0" + prompts: "npm:^2.4.2" + tslog: "npm:^4.4.0" + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + checksum: 10c0/090d3a526d9881968a1bb4f6d2fbe33db3a00677adfcf05ae54c7a585cab14760651982d0a5ded3caa9efdc3f6744cbf55abfcca74e4713941f2167be76cbfea + languageName: node + linkType: hard + "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -7234,6 +7359,13 @@ __metadata: languageName: node linkType: hard +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 + languageName: node + linkType: hard + "ts-api-utils@npm:^2.5.0": version: 2.5.0 resolution: "ts-api-utils@npm:2.5.0" @@ -7302,20 +7434,72 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^1.9.3": +"ts-node@npm:^10.9.1": + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" + dependencies: + "@cspotcode/source-map-support": "npm:^0.8.0" + "@tsconfig/node10": "npm:^1.0.7" + "@tsconfig/node12": "npm:^1.0.7" + "@tsconfig/node14": "npm:^1.0.0" + "@tsconfig/node16": "npm:^1.0.2" + acorn: "npm:^8.4.1" + acorn-walk: "npm:^8.1.1" + arg: "npm:^4.1.0" + create-require: "npm:^1.1.0" + diff: "npm:^4.0.1" + make-error: "npm:^1.1.1" + v8-compile-cache-lib: "npm:^3.0.1" + yn: "npm:3.1.1" + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: 10c0/5f29938489f96982a25ba650b64218e83a3357d76f7bede80195c65ab44ad279c8357264639b7abdd5d7e75fc269a83daa0e9c62fd8637a3def67254ecc9ddc2 + languageName: node + linkType: hard + +"tslib@npm:2.7.0": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 + languageName: node + linkType: hard + +"tslib@npm:^1.11.1, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: 10c0/69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 languageName: node linkType: hard -"tslib@npm:^2.4.0": +"tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 languageName: node linkType: hard +"tslog@npm:^4.3.1, tslog@npm:^4.4.0": + version: 4.11.0 + resolution: "tslog@npm:4.11.0" + checksum: 10c0/1bf7aa08d110da69bfe34aadf24fd1e61d3823d5fe82986e35d3279f3dd11ce1c94430620d55dccc05c280351060b6cd0ef31944abf9320884e8572576f4d71d + languageName: node + linkType: hard + "tsort@npm:0.0.1": version: 0.0.1 resolution: "tsort@npm:0.0.1" @@ -7397,6 +7581,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.2.2": + version: 5.9.3 + resolution: "typescript@npm:5.9.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/6bd7552ce39f97e711db5aa048f6f9995b53f1c52f7d8667c1abdc1700c68a76a308f579cd309ce6b53646deb4e9a1be7c813a93baaf0a28ccd536a30270e1c5 + languageName: node + linkType: hard + "typescript@npm:^6.0.3": version: 6.0.3 resolution: "typescript@npm:6.0.3" @@ -7407,6 +7601,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.2.2#optional!builtin": + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/ad09fdf7a756814dce65bc60c1657b40d44451346858eea230e10f2e95a289d9183b6e32e5c11e95acc0ccc214b4f36289dcad4bf1886b0adb84d711d336a430 + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A^6.0.3#optional!builtin": version: 6.0.3 resolution: "typescript@patch:typescript@npm%3A6.0.3#optional!builtin::version=6.0.3&hash=5786d5" @@ -7440,6 +7644,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.19.2": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 + languageName: node + linkType: hard + "undici-types@npm:~7.18.0": version: 7.18.2 resolution: "undici-types@npm:7.18.2" @@ -7456,6 +7667,13 @@ __metadata: languageName: node linkType: hard +"unfetch@npm:^4.2.0": + version: 4.2.0 + resolution: "unfetch@npm:4.2.0" + checksum: 10c0/a5c0a896a6f09f278b868075aea65652ad185db30e827cb7df45826fe5ab850124bf9c44c4dafca4bf0c55a0844b17031e8243467fcc38dd7a7d435007151f1b + languageName: node + linkType: hard + "universalify@npm:^0.1.0": version: 0.1.2 resolution: "universalify@npm:0.1.2" @@ -7585,6 +7803,13 @@ __metadata: languageName: node linkType: hard +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 10c0/bdc36fb8095d3b41df197f5fb6f11e3a26adf4059df3213e3baa93810d8f0cc76f9a74aaefc18b73e91fe7e19154ed6f134eda6fded2e0f1c8d2272ed2d2d391 + languageName: node + linkType: hard + "viem@npm:^2.27.0": version: 2.55.10 resolution: "viem@npm:2.55.10" @@ -7606,6 +7831,23 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: "npm:~0.0.3" + webidl-conversions: "npm:^3.0.0" + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -7836,3 +8078,12 @@ __metadata: checksum: 10c0/a6065dcc484ac9bc96cc2163b939a26caf0f12619ea64d171dcac74d1ac37495d7e31a4a043f4adf51740a93a32f5d144b5e0092dd0df18386d9a46a9f0ce493 languageName: node linkType: hard + +"zksync-web3@npm:^0.14.3": + version: 0.14.4 + resolution: "zksync-web3@npm:0.14.4" + peerDependencies: + ethers: ^5.7.0 + checksum: 10c0/1ee87dc33f2c45dfc5a93abb3ffda92f5e7190d90448aacb4859374975fd72bf269c72126ec06043e57e02c925273ecb936189ea2350a6ac4a620b95b86f7f97 + languageName: node + linkType: hard diff --git a/solidity/scripts/ethers-v6-compatibility/capture.cjs b/solidity/scripts/ethers-v6-compatibility/capture.cjs new file mode 100644 index 0000000000..084c233c21 --- /dev/null +++ b/solidity/scripts/ethers-v6-compatibility/capture.cjs @@ -0,0 +1,140 @@ +const fs = require("fs"); +const path = require("path"); +require( + path.join(process.cwd(), "node_modules/ts-node/register/transpile-only"), +); +const hre = require(path.join(process.cwd(), "node_modules/hardhat")); +(async () => { + if (hre.network.name !== "hardhat" || hre.network.config.forking?.enabled) + throw new Error("Capture requires a non-forked in-process Hardhat network"); + if ( + process.env.TEST_USE_STUBS_BEACON === "true" || + process.env.TEST_USE_STUBS_ECDSA === "true" + ) + throw new Error( + "Capture requires production contracts, without test stubs", + ); + const destination = process.env.MIGRATION_CAPTURE_DIR; + if (!destination) throw new Error("MIGRATION_CAPTURE_DIR is required"); + if (fs.existsSync(destination)) + throw new Error("Capture destination already exists"); + fs.mkdirSync(destination, { recursive: true }); + fs.writeFileSync( + path.join(destination, "inputs.json"), + JSON.stringify( + { + deploy: hre.config.paths.deploy, + externalContracts: hre.config.external?.contracts, + }, + null, + 2, + ) + "\n", + ); + await hre.run("deploy", { + reset: true, + write: false, + export: path.join(destination, "export.json"), + }); + const records = await hre.deployments.all(); + const send = (method, params) => hre.network.provider.send(method, params); + const id = hre.ethers.id || hre.ethers.utils.id; + const slot = (label) => + "0x" + (BigInt(id(label)) - 1n).toString(16).padStart(64, "0"); + const adminSlot = slot("eip1967.proxy.admin"); + const implementationSlot = slot("eip1967.proxy.implementation"); + const state = { contracts: {}, code: {} }; + for (const [name, record] of Object.entries(records)) { + const address = record.address; + const adminWord = await send("eth_getStorageAt", [ + address, + adminSlot, + "latest", + ]); + const implementationWord = await send("eth_getStorageAt", [ + address, + implementationSlot, + "latest", + ]); + const row = { address, adminWord, implementationWord, readers: {} }; + for (const getter of ["owner", "governance", "walletOwner"]) { + if ( + record.abi.some( + (entry) => + entry.type === "function" && + entry.name === getter && + entry.inputs.length === 0, + ) + ) { + row.readers[getter] = await send("eth_call", [ + { to: address, data: id(getter + "()").slice(0, 10) }, + "latest", + ]); + } + } + state.contracts[name] = row; + for (const target of [ + address, + "0x" + adminWord.slice(-40), + "0x" + implementationWord.slice(-40), + ]) { + if (BigInt(target) === 0n) continue; + state.code[target.toLowerCase()] = await send("eth_getCode", [ + target, + "latest", + ]); + } + if (BigInt(adminWord) !== 0n) + row.adminOwner = await send("eth_call", [ + { to: "0x" + adminWord.slice(-40), data: id("owner()").slice(0, 10) }, + "latest", + ]); + } + const blocks = []; + const height = Number(BigInt(await send("eth_blockNumber", []))); + for (let number = 0; number <= height; number++) { + const block = await send("eth_getBlockByNumber", [ + "0x" + number.toString(16), + true, + ]); + const receipts = []; + for (const transaction of block.transactions) + receipts.push( + await send("eth_getTransactionReceipt", [transaction.hash]), + ); + blocks.push({ block, receipts }); + } + const artifactRoot = path.join(process.cwd(), "export/artifacts"); + if (!fs.existsSync(artifactRoot)) + throw new Error("Run prepack before capturing exported artifacts"); + fs.cpSync(artifactRoot, path.join(destination, "artifacts"), { + recursive: true, + }); + const tokenStakingName = + "@threshold-network/solidity-contracts/contracts/staking/TokenStaking.sol:TokenStaking"; + const buildInfo = await hre.artifacts.getBuildInfo(tokenStakingName); + const compilerLayout = + buildInfo?.output.contracts[tokenStakingName.split(":")[0]].TokenStaking + .storageLayout; + fs.writeFileSync( + path.join(destination, "compiler-storage-layout.json"), + JSON.stringify(compilerLayout ?? null, null, 2) + "\n", + ); + fs.writeFileSync( + path.join(destination, "chain.json"), + JSON.stringify(blocks, null, 2) + "\n", + ); + fs.writeFileSync( + path.join(destination, "state.json"), + JSON.stringify(state, null, 2) + "\n", + ); + fs.writeFileSync( + path.join(destination, "deployments.json"), + JSON.stringify(records, null, 2) + "\n", + ); + console.log( + `Captured ${Object.keys(records).length} deployments and ${Object.keys(state.code).length} code addresses`, + ); +})().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/solidity/scripts/ethers-v6-compatibility/compare.cjs b/solidity/scripts/ethers-v6-compatibility/compare.cjs new file mode 100644 index 0000000000..6f2b155cd5 --- /dev/null +++ b/solidity/scripts/ethers-v6-compatibility/compare.cjs @@ -0,0 +1,150 @@ +// Usage: node compare.cjs BASELINE_CAPTURE CANDIDATE_CAPTURE [--ethers-v6] +// The optional flag permits only the reviewed Hardhat 2 ethers v5 -> v6 gas +// changes. Without it, packed-package/fallback captures must match exactly. +const assert = require("node:assert/strict"); +const fs = require("node:fs"); +const path = require("node:path"); +const { createHash } = require("node:crypto"); + +const [baseline, candidate, mode] = process.argv.slice(2); +assert(baseline && candidate, "Two capture directories are required"); +assert(!mode || mode === "--ethers-v6", "Unknown comparison mode"); +const read = (root, file) => JSON.parse(fs.readFileSync(path.join(root, file))); +const byteEqual = (file) => + fs + .readFileSync(path.join(baseline, file)) + .equals(fs.readFileSync(path.join(candidate, file))); +for (const file of ["export.json", "state.json"]) { + assert(byteEqual(file), `${file} differs`); +} + +const before = read(baseline, "chain.json"); +const after = read(candidate, "chain.json"); +assert.equal(after.length, before.length, "Block count differs"); +const isEcdsa = Object.hasOwn( + read(candidate, "deployments.json"), + "WalletRegistry", +); +const gasChanges = + mode && isEcdsa + ? new Map([ + [33, 5222326], + [34, 443289], + [35, 1065225], + [42, 15799896], + [45, 809383], + [46, 683960], + ]) + : new Map(); +const hashes = new Map(); +const changedTransactions = new Set(); +for (let i = 0; i < before.length; i++) { + const a = before[i].block; + const b = after[i].block; + assert.equal(b.stateRoot, a.stateRoot, `State root differs at block ${i}`); + assert.equal(b.transactions.length, a.transactions.length); + if (gasChanges.size && i >= 33) hashes.set(b.hash, a.hash); + if (gasChanges.has(i)) { + assert.equal(a.transactions.length, 1); + const oldTx = a.transactions[0]; + const newTx = b.transactions[0]; + assert.equal(Number(BigInt(oldTx.gas)), gasChanges.get(i)); + assert.equal(Number(BigInt(newTx.gas)), 16777216); + hashes.set(newTx.hash, oldTx.hash); + changedTransactions.add(oldTx.hash); + } +} + +// Only hash-bearing fields are translated. Calldata, topics, bytecode, storage, +// ABI fields and all receipt fields other than hashes remain strict comparisons. +function translateHashes(value, key = "") { + if (Array.isArray(value)) return value.map((entry) => translateHashes(entry)); + if (value && typeof value === "object") { + return Object.fromEntries( + Object.entries(value).map(([name, entry]) => [ + name, + translateHashes(entry, name), + ]), + ); + } + return ["hash", "parentHash", "blockHash", "transactionHash"].includes(key) + ? (hashes.get(value) ?? value) + : value; +} + +const normalizedBefore = structuredClone(before); +const normalizedAfter = translateHashes(after); +for (const i of gasChanges.keys()) { + for (const chain of [normalizedBefore, normalizedAfter]) { + // These two headers encode the differently signed transaction. Everything + // else, including receiptsRoot, gasUsed, base fee and timestamp, must match. + delete chain[i].block.size; + delete chain[i].block.transactionsRoot; + const transaction = chain[i].block.transactions[0]; + assert(changedTransactions.has(transaction.hash)); + for (const field of ["gas", "r", "s", "v"]) delete transaction[field]; + } +} +assert.deepEqual(normalizedAfter, normalizedBefore, "Chain execution differs"); +assert.deepEqual( + translateHashes(read(candidate, "deployments.json")), + read(baseline, "deployments.json"), + "Deployment records differ beyond reviewed transaction/block hashes", +); + +function inventory(root, relative = "") { + return fs + .readdirSync(path.join(root, relative), { withFileTypes: true }) + .flatMap((entry) => { + const name = path.join(relative, entry.name); + return entry.isDirectory() ? inventory(root, name) : [name]; + }) + .sort(); +} +const oldArtifacts = path.join(baseline, "artifacts"); +const newArtifacts = path.join(candidate, "artifacts"); +const files = inventory(oldArtifacts); +assert.deepEqual(inventory(newArtifacts), files, "Artifact inventory differs"); +const additions = []; +for (const file of files) { + const oldBytes = fs.readFileSync(path.join(oldArtifacts, file)); + const newBytes = fs.readFileSync(path.join(newArtifacts, file)); + if (oldBytes.equals(newBytes)) continue; + assert(mode, `Artifact bytes differ: ${file}`); + assert.equal( + file, + "@threshold-network/solidity-contracts/contracts/staking/TokenStaking.sol/TokenStaking.json", + ); + const oldArtifact = JSON.parse(oldBytes); + const newArtifact = JSON.parse(newBytes); + assert(!Object.hasOwn(oldArtifact, "storageLayout")); + assert(newArtifact.storageLayout?.storage?.length > 0); + assert.deepEqual( + newArtifact.storageLayout, + read(candidate, "compiler-storage-layout.json"), + "Layout differs from compiler output", + ); + delete newArtifact.storageLayout; + assert.deepEqual(newArtifact, oldArtifact, "Other artifact fields differ"); + additions.push(`${file}: compiler storageLayout added`); +} +console.log( + JSON.stringify( + { + exportSha256: createHash("sha256") + .update(fs.readFileSync(path.join(candidate, "export.json"))) + .digest("hex"), + contracts: Object.keys(read(candidate, "deployments.json")).length, + transactionsWithIdenticalState: before.reduce( + (total, entry) => total + entry.block.transactions.length, + 0, + ), + deploymentRecordsByteIdentical: byteEqual("deployments.json"), + reviewedGasLimitChanges: [...gasChanges.keys()], + artifacts: files.length, + artifactAdditions: additions, + }, + null, + 2, + ), +); diff --git a/solidity/scripts/ethers-v6-compatibility/hardhat.config.cjs b/solidity/scripts/ethers-v6-compatibility/hardhat.config.cjs new file mode 100644 index 0000000000..ffa15cfd35 --- /dev/null +++ b/solidity/scripts/ethers-v6-compatibility/hardhat.config.cjs @@ -0,0 +1,90 @@ +const fs = require("node:fs"); +const path = require("node:path"); +const { createRequire } = require("node:module"); + +const requirePackage = createRequire(path.join(process.cwd(), "package.json")); +requirePackage("ts-node/register/transpile-only"); +const { extendProvider, task } = requirePackage("hardhat/config"); +const { ProviderWrapper } = requirePackage("hardhat/plugins"); +// Loading the packed configuration also registers only its own task exports. +// Registering source and packed tasks together would redefine required params. +const ecdsaExport = process.env.ECDSA_EXPORT_PATH; +const packageConfig = require( + ecdsaExport + ? path.resolve(ecdsaExport, "hardhat.config.js") + : path.join(process.cwd(), "hardhat.config.ts"), +); +const config = packageConfig.default; + +class FixedClockProvider extends ProviderWrapper { + async request(args) { + if ( + ["eth_sendTransaction", "eth_sendRawTransaction"].includes(args.method) + ) { + const latest = await this._wrapped.request({ + method: "eth_getBlockByNumber", + params: ["latest", false], + }); + await this._wrapped.request({ + method: "evm_setNextBlockTimestamp", + params: [Number.parseInt(latest.timestamp, 16) + 1], + }); + } + return this._wrapped.request(args); + } +} + +extendProvider(async (provider, resolvedConfig, network) => { + if ( + network !== "hardhat" || + resolvedConfig.networks.hardhat.forking?.enabled + ) { + throw new Error( + "Compatibility capture requires non-forked in-process Hardhat", + ); + } + return new FixedClockProvider(provider); +}); + +// Test the executable ECDSA export from an actual packed producer. +if (ecdsaExport) { + // The full-suite account guard imports test fixtures omitted from npm. + // These task tests need only the named slots and one set of staking roles. + task("check-accounts-count").setAction(async (_args, hre) => { + const { nonStakingAccountsCount, stakingRolesCount } = + packageConfig.testConfig; + const required = nonStakingAccountsCount + stakingRolesCount; + if ((await hre.ethers.getSigners()).length < required) { + throw new Error( + `Packed task checks require at least ${required} accounts`, + ); + } + }); + const root = path.resolve(ecdsaExport); + for (const subdir of ["deploy", "artifacts", "tasks"]) { + const directory = path.join(root, subdir); + if (!fs.existsSync(directory) || !fs.statSync(directory).isDirectory()) { + throw new Error(`ECDSA ${subdir} export is missing: ${root}`); + } + } + config.paths = { ...config.paths, deploy: path.join(root, "deploy") }; + config.external = { + ...config.external, + contracts: [ + ...(config.external?.contracts ?? []), + { artifacts: path.join(root, "artifacts") }, + ], + }; +} + +module.exports = { + ...config, + paths: { ...config.paths, root: process.cwd() }, + networks: { + ...config.networks, + hardhat: { + ...config.networks.hardhat, + initialDate: "2024-01-01T00:00:00.000Z", + }, + }, +}; diff --git a/solidity/scripts/ethers-v6-compatibility/pack-and-capture.cjs b/solidity/scripts/ethers-v6-compatibility/pack-and-capture.cjs new file mode 100644 index 0000000000..76800eca48 --- /dev/null +++ b/solidity/scripts/ethers-v6-compatibility/pack-and-capture.cjs @@ -0,0 +1,193 @@ +// Run from solidity/ecdsa; packing runs each package's prepack step: +// node ../scripts/ethers-v6-compatibility/pack-and-capture.cjs NEW_DIRECTORY REFERENCE_CAPTURE +const assert = require("node:assert/strict"); +const fs = require("node:fs"); +const path = require("node:path"); +const { execFileSync } = require("node:child_process"); + +const [destination, reference] = process.argv.slice(2); +assert( + destination && reference, + "A new destination and reference capture are required", +); +assert.equal( + JSON.parse(fs.readFileSync("package.json")).name, + "@keep-network/ecdsa", +); +const root = path.resolve(destination); +assert(!fs.existsSync(root), "Destination already exists"); +fs.mkdirSync(root, { recursive: true }); +const consumerModules = path.join(root, "node_modules"); +fs.mkdirSync(path.join(consumerModules, "@keep-network"), { recursive: true }); + +// Reuse the installed consumer runtime/plugins. Producer contents come solely +// from the archives; no source-directory or sibling-export symlinks are used. +const installed = path.join(process.cwd(), "node_modules"); +for (const name of fs.readdirSync(installed)) { + if (name.startsWith(".")) continue; + if (name === "@keep-network") { + for (const dependency of fs.readdirSync(path.join(installed, name))) { + if (["random-beacon", "ecdsa"].includes(dependency)) continue; + fs.symlinkSync( + path.join(installed, name, dependency), + path.join(consumerModules, name, dependency), + "dir", + ); + } + } else { + fs.symlinkSync( + path.join(installed, name), + path.join(consumerModules, name), + "dir", + ); + } +} + +const packages = {}; +for (const name of ["random-beacon", "ecdsa"]) { + const source = path.resolve("..", name); + // Lifecycle scripts stay enabled so prepack regenerates export/ for the + // archive. npm runs prepare/prepack for `npm pack`, never prepublishOnly. + const output = execFileSync( + "npm", + ["pack", "--json", "--pack-destination", root], + { cwd: source, encoding: "utf8" }, + ); + const [packed] = JSON.parse(output); + const target = path.join(consumerModules, "@keep-network", name); + fs.mkdirSync(target); + execFileSync("tar", [ + "-xzf", + path.join(root, packed.filename), + "--strip-components=1", + "-C", + target, + ]); + for (const file of packed.files) { + if ( + !file.path.startsWith("export/") && + !file.path.startsWith("external/random-beacon-export/") + ) + continue; + assert( + fs + .readFileSync(path.join(source, file.path)) + .equals(fs.readFileSync(path.join(target, file.path))), + `Packed file differs: ${name}/${file.path}`, + ); + } + const artifactCount = packed.files.filter((file) => + file.path.startsWith("export/artifacts/"), + ).length; + const expectedArtifacts = name === "random-beacon" ? 51 : 52; + assert.equal( + artifactCount, + expectedArtifacts, + `${name} packed ${artifactCount} export/artifacts entries, ` + + `expected ${expectedArtifacts}. Update it here and the artifact ` + + `inventory row in solidity/docs/ethers-v6-compatibility.md`, + ); + if (name === "random-beacon") { + assert( + packed.files.some( + (file) => file.path === "export/utils/wait-for-confirmations.js", + ), + ); + } else { + for (const required of [ + "export/tasks/random-beacon.js", + "export/utils/random-beacon-export.js", + "external/random-beacon-export/tasks/initialize.js", + "external/random-beacon-export/tasks/unlock-eth-accounts.js", + "external/random-beacon-export/tasks/utils/index.js", + ]) { + assert( + packed.files.some((file) => file.path === required), + required, + ); + } + const prefix = "external/random-beacon-export/"; + for (const file of packed.files) { + if (!file.path.startsWith(prefix) || !file.path.endsWith(".js")) continue; + assert( + fs + .readFileSync(path.join(target, file.path)) + .equals( + fs.readFileSync( + path.resolve( + "../random-beacon/export", + file.path.slice(prefix.length), + ), + ), + ), + `Bundled Beacon export is stale: ${file.path}`, + ); + } + } + packages[name] = packed; +} +fs.writeFileSync( + path.join(root, "packed-files.json"), + JSON.stringify(packages, null, 2) + "\n", +); +const capture = path.join(root, "capture"); +const producerEnvironment = { + ...process.env, + HARDHAT_CONFIG: path.join(__dirname, "hardhat.config.cjs"), + USE_EXTERNAL_DEPLOY: "true", + RANDOM_BEACON_EXPORT_PATH: path.join( + consumerModules, + "@keep-network/random-beacon/export", + ), + ECDSA_EXPORT_PATH: path.join(consumerModules, "@keep-network/ecdsa/export"), +}; +execFileSync(process.execPath, [path.join(__dirname, "capture.cjs")], { + stdio: "inherit", + env: { + ...producerEnvironment, + MIGRATION_CAPTURE_DIR: capture, + }, +}); +execFileSync( + process.execPath, + [path.join(__dirname, "compare.cjs"), path.resolve(reference), capture], + { stdio: "inherit" }, +); + +const taskTests = [ + path.join(installed, "hardhat/internal/cli/cli.js"), + "test", + "--no-compile", + "--network", + "hardhat", + "test/tasks/initialize.test.ts", + "test/tasks/unlock-accounts.test.ts", +]; +console.log("Checking packed ECDSA tasks with the packed v6 Beacon producer"); +execFileSync(process.execPath, taskTests, { + stdio: "inherit", + env: producerEnvironment, +}); + +// Recreate the locked consumer dependency while retaining ECDSA's real tarball. +// Its compiled task imports must use the shipped v6 bundle, not the v5 neighbor. +const packedBeacon = path.join(consumerModules, "@keep-network/random-beacon"); +const savedPackedBeacon = path.join(root, "packed-random-beacon"); +fs.renameSync(packedBeacon, savedPackedBeacon); +fs.symlinkSync( + path.join(installed, "@keep-network/random-beacon"), + packedBeacon, + "dir", +); +const bundledEnvironment = { ...producerEnvironment }; +delete bundledEnvironment.RANDOM_BEACON_EXPORT_PATH; +try { + console.log("Checking packed ECDSA tasks with the pinned Beacon dependency"); + execFileSync(process.execPath, taskTests, { + stdio: "inherit", + env: bundledEnvironment, + }); +} finally { + fs.unlinkSync(packedBeacon); + fs.renameSync(savedPackedBeacon, packedBeacon); +}