diff --git a/.commitlintrc b/.commitlintrc new file mode 100644 index 0000000..7a4907e --- /dev/null +++ b/.commitlintrc @@ -0,0 +1,3 @@ +{ + "extends": ["@commitlint/config-conventional"] +} \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..27506e5 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +# NOTE: Environment variables are only needed if you are running integration tests + +E2E_BUNDLER_URL= +E2E_PAYMASTER_URL= +E2E_SEPOLIA_RPC= \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..4b6c8b7 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,8 @@ +node_modules +coverage +public +build +dist + +src/constants.ts +test/fixture-projects \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..7dbf302 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,17 @@ +{ + "parser": "@typescript-eslint/parser", + "plugins": [ + "@typescript-eslint", + "prettier" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended", + "prettier" + ], + "rules": { + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-var-requires": "off" + } +} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f6b1f68 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,36 @@ +name: Build + +on: [push] + +concurrency: + group: ${{github.workflow}}-${{github.ref}} + cancel-in-progress: true + +jobs: + build: + name: Run build + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v3 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'yarn' + + - name: Install dependencies + run: yarn --frozen-lockfile --network-concurrency 1 + + - name: Run build + run: yarn build \ No newline at end of file diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml new file mode 100644 index 0000000..a75e3a6 --- /dev/null +++ b/.github/workflows/canary.yml @@ -0,0 +1,37 @@ +name: Canary release + +on: workflow_dispatch + +jobs: + canary-publish: + name: Publish Packages (canary) + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + + - name: Install Node + uses: actions/setup-node@v4 + with: + registry-url: 'https://registry.npmjs.org' + cache: 'yarn' + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Install Dependencies + run: yarn --frozen-lockfile --network-concurrency 1 + + - name: Build + run: yarn build + + - name: Update version + run: yarn version --new-version "0.0.0-${GITHUB_SHA::8}" --no-git-tag-version + + - name: Publish + run: npm publish --access public --tag canary + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..b869414 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,48 @@ +name: Lint + +on: [push] + +concurrency: + group: ${{github.workflow}}-${{github.ref}} + cancel-in-progress: true + +jobs: + commitlint: + name: Lint Commit Messages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: wagoid/commitlint-github-action@v5 + + lint: + name: Run Linters + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v3 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'yarn' + + - name: Install dependencies + run: yarn --frozen-lockfile --network-concurrency 1 + + - name: Run Prettier + run: yarn prettier + + - name: Run Linter + run: yarn lint \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b0498dd --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,36 @@ +name: Release + +on: + release: + types: [published] + +jobs: + release: + name: Release + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + + - name: Install Node + uses: actions/setup-node@v4 + with: + registry-url: 'https://registry.npmjs.org' + cache: 'yarn' + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Install Dependencies + run: yarn --frozen-lockfile --network-concurrency 1 + + - name: Build + run: yarn build + + - name: Publish + run: yarn publish --access public --tag latest + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..7f6c975 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,64 @@ +name: Tests + +on: [push] + +jobs: + unit: + name: Run unit tests + runs-on: ubuntu-latest + + steps: + - name: Check out github repository + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + cache: "yarn" + + - name: Install dependencies + run: yarn --frozen-lockfile + + - name: Run unit tests + run: yarn test:unit + + integration: + name: Run integration tests + runs-on: ubuntu-latest + + steps: + - name: Check out github repository + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + cache: "yarn" + + - name: Install dependencies + run: yarn --frozen-lockfile + + - name: Run integration tests + run: yarn test:integration + env: + E2E_BUNDLER_URL: ${{ secrets.E2E_BUNDLER_URL }} + E2E_PAYMASTER_URL: ${{ secrets.E2E_PAYMASTER_URL }} + E2E_PAYMASTER_TYPE: ${{ secrets.E2E_PAYMASTER_TYPE }} + E2E_SEPOLIA_RPC: ${{ secrets.E2E_SEPOLIA_RPC }} + diff --git a/.gitignore b/.gitignore index 6993c1c..4499af6 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,18 @@ typings/ # environment variables .env + +# Solidity compilation files +out/ +cache/ +src/abi/**/* +!src/abi/BatchDeployAndTransferOwnership.sol + +# Hardhat artifacts +test/fixture-projects/integration/artifacts/**/* + +# Sponsored transactions JSON files +test/fixture-projects/integration/sponsored-transactions/ + +# Ignore the sponsored deployments from integration tests +sponsored-transactions/ \ No newline at end of file diff --git a/.husky/.commit-msg b/.husky/.commit-msg new file mode 100644 index 0000000..314e821 --- /dev/null +++ b/.husky/.commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install commitlint --edit $1 \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..0312b76 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged \ No newline at end of file diff --git a/.mocharc.json b/.mocharc.json index 79ba35d..eafcdb8 100644 --- a/.mocharc.json +++ b/.mocharc.json @@ -1,5 +1,5 @@ { "require": "ts-node/register/files", "ignore": ["test/fixture-projects/**/*"], - "timeout": 6000 + "timeout": 120000 } diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f535f09 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules +coverage +public +build +dist +src/constants.ts +src/abi/** +test/fixture-projects/integration/artifacts/** \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..bf3bb18 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "tabWidth": 2, + "printWidth": 120, + "singleQuote": true, + "bracketSpacing": true +} \ No newline at end of file diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..6bc597b --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,179 @@ +# Contributors + +## Adding a new paymaster to the plugin + +### Adding the paymaster + +If you operate a paymaster and would like to add support for your paymaster into the plugin please follow the steps below + +1. Located inside `src/paymasters` you will see all other paymasters please create a typescript file for this example we will call it `ExamplePaymaster.ts` + +1. Now inside `ExamplePaymaster.ts` we will need to inherit the `Paymaster` class and input the neccesarry types. Here is an example setup below. Some paymaster might need access to a bundler client or policy id, feel free to add those into the constructor of your class we will get to how those will be passed in a later step. + +
+ +```ts +import { SponsorUserOperationReturnType } from 'permissionless/actions/pimlico'; +import { PartialUserOperation } from '../types'; +import { Paymaster } from './Paymaster'; + +/** + * Example class for paymasters. + */ +export class ExamplePaymaster extends Paymaster { + + constructor(endpoint: string) { + super(endpoint); + } + + /** + * Sponsor a user operation. + * @param userOperation The user operation to sponsor + * @param entryPoint The entry point to use + * @returns The paymasterAndData and gas information for the user operation or just the paymasterAndData depending on the implementation + */ + public async sponsorUserOperation( + userOp: PartialUserOperation, + entryPoint: `0x${string}`, + ): Promise { + // Your logic for sponsorship + } +} +``` +
+ +3. Now lets export your paymaster from the paymaster folder we will do this in the `index.ts` file located in `src/paymaster`, you can see from below how we would export `ExamplePaymaster.ts` + +
+ +```ts +export * from './Paymaster'; +export * from './PimlicoPaymaster'; +export * from './StackUpPaymaster'; +export * from './BasePaymaster'; +export * from './AlchemyPaymaster'; +export * from './ExamplePaymaster'; +``` + +
+ +4. Next we will register your new paymaster as a type for users to select in their hardhat config. Go to `src/type.ts` and add your paymaster info to the `PaymasterType` enum and update the natspec to reflect the changes, heres how we would do it with `ExamplePaymaster.ts`. **It is important the value you set is unique to your API for our interpreter to properly parse it**. As you can see base is not set to `base` as there would be conflicts which providers that use it as a param to decide the chain so it is set to `paymaster.base` to be unique. + +
+ +```ts +/** + * The type of paymaster class + * @property Pimlico for the Pimlico paymaster + * @property Base for the Base paymaster + * @property StackUp for the StackUp paymaster + * @property Alchemy for the Alchemy paymaster + * @property Example for the example paymaster + */ +export enum PaymasterType { + Pimlico = 'pimlico', + Base = 'paymaster.base', + StackUp = 'stackup', + Alchemy = 'alchemy', + Example = 'example' +} +``` +
+ +5. Now we will go to `src/paymaster.ts` and add your paymaster to the switch statement, and optionally pass in the bundler client or policy id if your paymaster implementation needs them. + +
+ +```ts +export function createPaymasterClient( + paymasterType: PaymasterType, + paymasterUrl: string, + bundlerClient: PimlicoBundlerClient, + policyId?: string, +): Paymaster { + switch (paymasterType) { + case PaymasterType.Pimlico: + return new Pm.PimlicoPaymaster(paymasterUrl, policyId); + case PaymasterType.StackUp: + return new Pm.StackUpPaymaster(paymasterUrl); + case PaymasterType.Base: + return new Pm.BasePaymaster(paymasterUrl, bundlerClient); + case PaymasterType.Alchemy: + return new Pm.AlchemyPaymaster(paymasterUrl, policyId); + case PaymasterType.Example: + return new Pm.ExamplePaymaster(paymasterUrl); + } +} +``` + +
+ +6. Finally be sure to update the README's list of supported paymaster to reflect your changes, the table can be found [here](./README.md#supported-paymaster-types) + +7. And thats it! In order to test that you have done the implementation correctly you can clone our [example repo found here](https://github.com/defi-wonderland/sponsored-txs-hardhat-example) and link it to your local plugin, see the simple guide below for steps on how to do that! + +
+ +### Testing the paymaster locally + +1. Make sure you are in the sponsored transaction repo you forked and are ready to test your paymaster implementation + +1. run `yarn && yarn build` + +1. Run `yarn link` + +1. Clone the [example repo](https://github.com/defi-wonderland/hardhat-account-abstraction-example) and `cd` into it + +1. run `yarn link @defi-wonderland/hardhat-account-abstraction` + +1. Now open the example repo in your code editor of choice and navigate to the `hardhat.config.ts` file + +1. Here we need to set our `paymasterType` to the paymaster we just made! If your paymaster does not run on goerli feel free to change the network as well! + +
+ +```ts +const config: HardhatUserConfig = { + solidity: '0.8.19', + defaultNetwork: 'goerli', + networks: { + goerli: { + url: process.env.GOERLI_RPC_URL as string, + accounts: [process.env.PRIVATE_KEY as string], + accountAbstraction: { + bundlerUrl: 'https://example.com', // The bundler that the UserOperations will be sent to + paymasterUrl: 'https://example.com', // The paymaster API that will be used for sponsoring transactions + } + } + } +}; +``` +
+ +8. Next we need to set the environment variable in the `.env` + +
+ +``` +GOERLI_RPC_URL=https://example_rpc +PRIVATE_KEY=YOUR_PK +``` +9. Now we can test everything by running `npx hardhat run scripts/deploy.ts` + +10. Assuming all goes well and you are done testing your implementation feel free to make a PR to the official plugin with a description on how the reviewer can test your new paymaster and we will do our best to review it in a timely manner! + +### Running the integration tests + +1. When adding a paymaster we need to also run our integration tests inside the plugin's repository to do so follow these steps + +1. Set the environment variables: +``` +# NOTE: Environment variables are only needed if you are running integration tests + +E2E_BUNDLER_URL= +E2E_PAYMASTER_URL= +E2E_SEPOLIA_RPC= +``` +
+ +3. Run `yarn test:integration` and observe thne results \ No newline at end of file diff --git a/LICENSE b/LICENSE index 3b8858c..bc53de4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,10 @@ -MIT License +The MIT License (MIT) +Copyright © 2024 Wonder Ltd -Copyright (c) 2019 Nomic Labs LLC +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + \ No newline at end of file diff --git a/README.md b/README.md index 06fe5ce..534f0fd 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,226 @@ -# hardhat-example-plugin +# Hardhat Account Abstraction -_A one line description of the plugin_ +A plugin to send sponsored transactions utilizing account abstraction! -[Hardhat](https://hardhat.org) plugin example. ## What -<_A longer, one paragraph, description of the plugin_> - -This plugin will help you with world domination by implementing a simple tic-tac-toe in the terminal. +This plugin sponsors any transaction the user sends through the power of account abstraction. Through seemless integration after the configuration is set just submit any transaction, and you can see it get mined on the testnets without costing the signer any gas! ## Installation -<_A step-by-step guide on how to install the plugin_> ```bash -yarn install [list of peer dependencies] +yarn install @defi-wonderland/hardhat-account-abstraction ``` Import the plugin in your `hardhat.config.js`: ```js -require(""); +require("@defi-wonderland/hardhat-account-abstraction"); ``` Or if you are using TypeScript, in your `hardhat.config.ts`: ```ts -import ""; +import "@defi-wonderland/hardhat-account-abstraction"; ``` ## Required plugins -<_The list of all the required Hardhat plugins if there are any_> +> **NOTE: Only one of these packages is needed depending on what you are writing your scripts in** + +
-- [@nomiclabs/hardhat-web3](https://github.com/nomiclabs/hardhat/tree/master/packages/hardhat-web3) +- [@nomicfoundation/hardhat-ethers](https://github.com/NomicFoundation/hardhat/tree/main/packages/hardhat-ethers) +- [@nomicfoundation/hardhat-viem](https://github.com/NomicFoundation/hardhat/tree/main/packages/hardhat-viem) ## Tasks -<_A description of each task added by this plugin. If it just overrides internal -tasks, this may not be needed_> This plugin creates no additional tasks. -<_or_> - -This plugin adds the _example_ task to Hardhat: -``` -output of `npx hardhat help example` -``` ## Environment extensions -<_A description of each extension to the Hardhat Runtime Environment_> - -This plugin extends the Hardhat Runtime Environment by adding an `example` field -whose type is `ExampleHardhatRuntimeEnvironmentField`. +This plugin does not extend the hardhat runtime environment ## Configuration +> **NOTE: Currently the plugin will only use the first private key in `accounts`** -<_A description of each extension to the HardhatConfig or to its fields_> - -This plugin extends the `HardhatUserConfig`'s `ProjectPathsUserConfig` object with an optional -`newPath` field. +This plugin requires 2 new fields inside an `accountAbstraction` object which will be nested inside each hardhat network that is set in the config This is an example of how to set it: -```js -module.exports = { - paths: { - newPath: "new-path" +```ts +const config: HardhatUserConfig = { + solidity: '0.8.19', + defaultNetwork: 'goerli', + networks: { + goerli: { + url: process.env.GOERLI_RPC_URL as string, + accounts: [process.env.PRIVATE_KEY as string], + accountAbstraction: { + bundlerUrl: 'https://example.com', + paymasterUrl: 'https://example.com', + } + } } }; ``` +### Options + +| Option | Description | Required | Default | +| ------------------------------ | ---------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------ | +| `bundlerUrl` | The bundler that the UserOperations will be sent to | Yes | No default | +| `paymasterUrl` | The paymaster API that will be used for sponsoring transactions | Yes | No default | +| `simpleAccountFactoryAddress` | The simple account factory address you want to use | No | 0x9406cc6185a346906296840746125a0e44976454 | +| `smartAccount` | Address of a smart account to use in your scripts | No | Will deploy one for you | +| `policyId` | The policy id to use if your paymaster has one | No | No default | + +### Supported Paymaster Types + +The list of paymasters we currently support + +1. Pimlico +1. Stackup +1. Alchemy +1. Base + + +If you would like to add support for a new paymaster check out the [contributors guide](./CONTRIBUTORS.md#adding-a-new-paymaster-to-the-plugin) + +### Supported Chains + +#### For a chain to be supported the conditions are: + +1. The SimpleAccount Factory is deployed to the address `0x9406cc6185a346906296840746125a0e44976454` or alternatively entered as an optional parameter in the config +1. The [CreateXFactory](https://github.com/pcaversaccio/createx) needs to be deployed to its standard address +
+#### Currently the list of supported chains is, but not limited to the following: + +1. Ethereum Sepolia +1. Ethereum Goerli +1. Polygon Mumbai +1. Base Goerli +1. Optimism Goerli +1. Arbitrum Goerli + ## Usage -<_A description of how to use this plugin. How to use the tasks if there are any, etc._> +> **⚠ WARNING: Any non-zero msg.value call will not work as intended as paymaster's dont sponsor this value, in order to use native transfers or interact with payable functions you will need the native token of your chain in the smart account wallet beforehand** + +After you have setup the configuration for the `accountAbstraction` and you are using a network that has them enable you are good to go, you can right a simple script below and your transactions will be mined on the testnet that you have configured! + +```js +const signer = await ethers.provider.getSigner(); +const testToken = new ethers.Contract('0x16F63C5036d3F48A239358656a8f123eCE85789C', TEST_TOKEN_ABI, signer); +const amountToMint = ethers.parseEther('6.9'); +await testToken.mint(amountToMint); +``` + +## Deploying Contracts + +Deploying contracts works just as any other transaction would, however due to the nature of account abstraction we deploy all contracts through the `CreateXFactory`, The `CreateXFactory` is deployed on **most** EVM compatible chains, if you would like to learn more about it or deploy it to your new chain you can do so by checking out [their repo](https://github.com/pcaversaccio/createx) + +### What are the differences? + +- **Ownable contracts** + + We do support ownable contracts and the default `owner` of your contract will be the smart account you deployed with, the only condition is you must have a `transferOwnership(address)` function to make this work, if you have a custom implementation of `Ownable` and dont instantiate `owner` as `msg.sender` in the constructor it will also work. + +- **Contract addresses in scripts** + + Scripting with deployed contracts works pretty much out of the box with one caveat, the address that ethers provides for your address is wrong. This is because ethers predicts the deployment address by the default `CREATE` opcode standards which takes the transaction's `from` and `nonce` values, these values do not match that of our middlewares deployment so we expose a [custom method to get this address](#aa_getdeploymentfor). This issue is only present with libraries that hardcode the predicted address such as ethers. Other libraries use the receipt to retrieve the contract address such as viem, for those libraries the address returned will be correct as we modify the receipts in our middleware. + +
+ + Scripting will work as expected even with this incorrect address param, this is because our middleware overwrites any transaction being sent to the incorrect predicted address and routes it to the address we deployed. As you can see from this example below. + + ```js + const lock = await ethers.getContractFactory('Lock'); + + const lockContract = await lock.deploy(); + + const originalOwner = await lockContract.owner(); + + console.log('Original owner set to: ', originalOwner); // Logs the smart account address + + await lockContract.transferOwnership("0xEB7cFd33CfEfFf98EF067F501B81D31C9a7077C3"); + + const newOwner = await lockContract.owner(); + + console.log('New owner set to: ', newOwner); // Logs the 0xEB7... address + ``` +
+ + However it is very important to remember that `lockContract` has the wrong address, however using the address the contract computes will work as a parameter as you can see below + +
+ + ```js + const lock = await ethers.getContractFactory('Lock'); + const lockContract = await lock.deploy(); + + console.log(lockContract.target); // Wrong address + + const lockContractAddress = await network.provider.request({ + method: 'aa_getDeploymentFor', + params: [lockContract.target] + }); + + console.log(lockContractAddress) // Correct address + + lockContract.randomFunctionWithAddressAsParam(lockContract.target) // Will use the correct address + ``` + +## Custom JSON API methods + +This plugin adds additional JSON-RPC methods to be able to interact and get data from our custom provider middleware. + +### `aa_getSmartAccountAddress` + +**Description:** Returns the address for the smart account that is being used by the provider. + - Example: + ```js + const smartAccountAddress = await network.provider.request({ + method: 'aa_getSmartAccountAddress', + params: [], + }); + console.log(`Smart account address: ${smartAccountAddress}`); + ``` + +### `aa_getDeploymentFor`: + +**Description:** Returns the address of which a contract was deployed through our middleware, [to learn more about why this is needed click here](#deploying-contracts) + - Parameters: + - `contract: 0x${string}`: The contract address that you want to check the deployment for + - Example: + ```js + const lock = await ethers.getContractFactory('Lock'); + const lockContract = await lock.deploy(); + + const lockContractAddress = await network.provider.request({ + method: 'aa_getDeploymentFor', + params: [lockContract.target] + }); + ``` + + +## Contributors + +If you want to learn how to add support for your own paymaster implementation checkout our guide [here](./CONTRIBUTORS.md#adding-a-new-paymaster-to-the-plugin) to learn how to add it to the plugin! + +
+ +Hardhat Account Abstraction was built with ❤️ by [Wonderland](https://defi.sucks). + +Wonderland the largest core development group in web3. Our commit ment is to a financial future that's open, decentralized, and accessible to all. + +[DeFi sucks](https://defi.sucks), but Wonderland is here to make it better. -There are no additional steps you need to take for this plugin to work. +## Licensing -Install it and access ethers through the Hardhat Runtime Environment anywhere -you need it (tasks, scripts, tests, etc). +The primary license for Hardhat Account Abstraction is MIT, see [`LICENSE`](./LICENSE). \ No newline at end of file diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 0000000..5df12d1 --- /dev/null +++ b/foundry.toml @@ -0,0 +1,18 @@ +[fmt] +line_length = 120 +tab_width = 2 +bracket_spacing = false +int_types = 'long' +quote_style = 'single' +single_line_statement_blocks = 'single' +number_underscore = 'thousands' +multiline_func_header = 'params_first' + +[profile.default] +solc = '0.8.19' +src = './src/batch' +out = './src/abi' +cache = true +evm_version = 'london' +auto_detect_solc = true +optimizer = false \ No newline at end of file diff --git a/package.json b/package.json index 6030ab7..a989b6d 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "@defi-wonderland/sponsored-txs-hardhat-plugin", - "version": "0.0.1", - "description": "Hardhat TypeScript plugin for Sponsored Txs", - "repository": "github:defi-wonderland/sponsored-txs-hardhat-plugin", + "name": "@defi-wonderland/hardhat-account-abstraction", + "version": "1.0.0", + "description": "Hardhat TypeScript plugin for Account Abstraction", + "repository": "github:defi-wonderland/hardhat-account-abstraction", "author": "Wonderland", "license": "MIT", "main": "dist/src/index.js", @@ -15,11 +15,24 @@ "hardhat-plugin" ], "scripts": { - "format": "prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' README.md", + "format": "yarn run prettier:fix && yarn run lint:fix", "test": "mocha --exit --recursive 'test/**/*.test.ts'", - "build": "tsc", + "test:unit": "mocha --exit --recursive 'test/unit/**/*.test.ts'", + "test:integration": "mocha --exit --recursive 'test/integration/**/*.test.ts'", + "build": "forge compile && tsc", "watch": "tsc -w", - "prepublishOnly": "npm run build" + "prepublishOnly": "npm run build", + "lint": "yarn lint:src && yarn lint:test", + "lint:fix": "yarn lint:src --fix && yarn lint:test --fix && forge fmt", + "lint:src": "eslint ./src", + "lint:test": "eslint ./test", + "prepare": "husky install", + "prettier": "prettier src test --check", + "prettier:fix": "yarn run prettier -- --write" + }, + "lint-staged": { + "*.ts": "eslint --cache --fix", + "src/**/*.{js,ts,md}": "yarn run prettier:fix" }, "files": [ "dist/src/", @@ -28,22 +41,35 @@ "README.md" ], "devDependencies": { + "@nomicfoundation/hardhat-ethers": "3.0.5", "@types/chai": "4.3.11", "@types/debug": "4.1.12", "@types/mocha": "5.2.6", + "@types/sinon": "10.0.15", + "@typescript-eslint/eslint-plugin": "5.59.6", + "@typescript-eslint/parser": "5.59.6", "chai": "4.3.10", + "dotenv": "16.4.1", + "eslint": "8.34.0", + "eslint-config-prettier": "9.0.0", + "eslint-plugin-prettier": "5.0.1", "hardhat": "2.19.0", + "husky": "8.0.3", + "lint-staged": "13.2.2", "mocha": "10.2.0", "prettier": "3.1.0", + "sinon": "15.2.0", "ts-node": "10.9.1", - "typescript": "5.3.3" + "typescript": "5.0.4" }, "peerDependencies": { - "hardhat": "^2.19.0" + "hardhat": "2.19.5" }, "dependencies": { - "axios": "1.6.2", + "axios": "1.6.7", "debug": "4.3.4", - "ethers": "5.7.2" + "ethers": "6.9.0", + "permissionless": "0.0.16", + "viem": "1.20.3" } } diff --git a/src/abi/BatchDeployAndTransferOwnership.sol/BatchDeployAndTransferOwnership.json b/src/abi/BatchDeployAndTransferOwnership.sol/BatchDeployAndTransferOwnership.json new file mode 100644 index 0000000..270134c --- /dev/null +++ b/src/abi/BatchDeployAndTransferOwnership.sol/BatchDeployAndTransferOwnership.json @@ -0,0 +1,945 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "_initCode", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ], + "bytecode": { + "object": "0x60806040526040516102ef3803806102ef83398181016040528101906100259190610249565b6000808083516020850134f591508173ffffffffffffffffffffffffffffffffffffffff1663f2fde38b336040518263ffffffff1660e01b815260040161006c91906102d3565b600060405180830381600087803b15801561008657600080fd5b505af1925050508015610097575060015b6100a457600091506100a5565b5b6000826040516020016100b891906102d3565b6040516020818303038152906040529050602081018059038082f35b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61013b826100f2565b810181811067ffffffffffffffff8211171561015a57610159610103565b5b80604052505050565b600061016d6100d4565b90506101798282610132565b919050565b600067ffffffffffffffff82111561019957610198610103565b5b6101a2826100f2565b9050602081019050919050565b60005b838110156101cd5780820151818401526020810190506101b2565b60008484015250505050565b60006101ec6101e78461017e565b610163565b905082815260208101848484011115610208576102076100ed565b5b6102138482856101af565b509392505050565b600082601f8301126102305761022f6100e8565b5b81516102408482602086016101d9565b91505092915050565b60006020828403121561025f5761025e6100de565b5b600082015167ffffffffffffffff81111561027d5761027c6100e3565b5b6102898482850161021b565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102bd82610292565b9050919050565b6102cd816102b2565b82525050565b60006020820190506102e860008301846102c4565b9291505056fe", + "sourceMap": "147:983:0:-:0;;;359:769;;;;;;;;;;;;;;;;;;;;;:::i;:::-;409:20;435;595:12;583:9;577:16;570:4;559:9;555:20;542:11;534:74;518:90;;708:12;691:48;;;740:10;691:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;687:118;;796:1;773:25;;687:118;;;;811:17;842:12;831:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;811:44;;1037:2;1031:4;1027:13;1075:9;1066:7;1062:23;1110:7;1099:9;1092:26;7:75:3;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:117;566:1;563;556:12;580:102;621:6;672:2;668:7;663:2;656:5;652:14;648:28;638:38;;580:102;;;:::o;688:180::-;736:77;733:1;726:88;833:4;830:1;823:15;857:4;854:1;847:15;874:281;957:27;979:4;957:27;:::i;:::-;949:6;945:40;1087:6;1075:10;1072:22;1051:18;1039:10;1036:34;1033:62;1030:88;;;1098:18;;:::i;:::-;1030:88;1138:10;1134:2;1127:22;917:238;874:281;;:::o;1161:129::-;1195:6;1222:20;;:::i;:::-;1212:30;;1251:33;1279:4;1271:6;1251:33;:::i;:::-;1161:129;;;:::o;1296:307::-;1357:4;1447:18;1439:6;1436:30;1433:56;;;1469:18;;:::i;:::-;1433:56;1507:29;1529:6;1507:29;:::i;:::-;1499:37;;1591:4;1585;1581:15;1573:23;;1296:307;;;:::o;1609:246::-;1690:1;1700:113;1714:6;1711:1;1708:13;1700:113;;;1799:1;1794:3;1790:11;1784:18;1780:1;1775:3;1771:11;1764:39;1736:2;1733:1;1729:10;1724:15;;1700:113;;;1847:1;1838:6;1833:3;1829:16;1822:27;1671:184;1609:246;;;:::o;1861:432::-;1949:5;1974:65;1990:48;2031:6;1990:48;:::i;:::-;1974:65;:::i;:::-;1965:74;;2062:6;2055:5;2048:21;2100:4;2093:5;2089:16;2138:3;2129:6;2124:3;2120:16;2117:25;2114:112;;;2145:79;;:::i;:::-;2114:112;2235:52;2280:6;2275:3;2270;2235:52;:::i;:::-;1955:338;1861:432;;;;;:::o;2312:353::-;2378:5;2427:3;2420:4;2412:6;2408:17;2404:27;2394:122;;2435:79;;:::i;:::-;2394:122;2545:6;2539:13;2570:89;2655:3;2647:6;2640:4;2632:6;2628:17;2570:89;:::i;:::-;2561:98;;2384:281;2312:353;;;;:::o;2671:522::-;2750:6;2799:2;2787:9;2778:7;2774:23;2770:32;2767:119;;;2805:79;;:::i;:::-;2767:119;2946:1;2935:9;2931:17;2925:24;2976:18;2968:6;2965:30;2962:117;;;2998:79;;:::i;:::-;2962:117;3103:73;3168:7;3159:6;3148:9;3144:22;3103:73;:::i;:::-;3093:83;;2896:290;2671:522;;;;:::o;3199:126::-;3236:7;3276:42;3269:5;3265:54;3254:65;;3199:126;;;:::o;3331:96::-;3368:7;3397:24;3415:5;3397:24;:::i;:::-;3386:35;;3331:96;;;:::o;3433:118::-;3520:24;3538:5;3520:24;:::i;:::-;3515:3;3508:37;3433:118;;:::o;3557:222::-;3650:4;3688:2;3677:9;3673:18;3665:26;;3701:71;3769:1;3758:9;3754:17;3745:6;3701:71;:::i;:::-;3557:222;;;;:::o", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x6080604052600080fdfea264697066735822122033af4b3c4e9127118ae7ad3f84ed7c91019da16bbae3b6ec8dedff17d1b08f8964736f6c63430008130033", + "sourceMap": "147:983:0:-:0;;;;;", + "linkReferences": {} + }, + "methodIdentifiers": {}, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_initCode\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_initCode\":\"The contract we are deploings init code\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Simulates a deployment and transfer ownership as if this contract was a factory\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/batch/BatchDeployAndTransferOwnership.sol\":\"BatchDeployAndTransferOwnership\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":hardhat/=node_modules/hardhat/\"]},\"sources\":{\"src/batch/BatchDeployAndTransferOwnership.sol\":{\"keccak256\":\"0x81b97e4c3bef21203fb75ed63b6bb356bd0253118abacb3da7a60ecb6ee8495d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://142e32ceda7d609cd94f1e1417d018080afcadb3290bae1c64aa62638b47755f\",\"dweb:/ipfs/QmU43YaweEYQ3zcMNsmMdLajHUBD7E1cLk3EE532ixWxc5\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.8.19+commit.7dd6d404" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "_initCode", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ], + "devdoc": { + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_initCode": "The contract we are deploings init code" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "constructor": { + "notice": "Simulates a deployment and transfer ownership as if this contract was a factory" + } + }, + "version": 1 + } + }, + "settings": { + "remappings": [ + "hardhat/=node_modules/hardhat/" + ], + "optimizer": { + "enabled": false, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "src/batch/BatchDeployAndTransferOwnership.sol": "BatchDeployAndTransferOwnership" + }, + "libraries": {} + }, + "sources": { + "src/batch/BatchDeployAndTransferOwnership.sol": { + "keccak256": "0x81b97e4c3bef21203fb75ed63b6bb356bd0253118abacb3da7a60ecb6ee8495d", + "urls": [ + "bzz-raw://142e32ceda7d609cd94f1e1417d018080afcadb3290bae1c64aa62638b47755f", + "dweb:/ipfs/QmU43YaweEYQ3zcMNsmMdLajHUBD7E1cLk3EE532ixWxc5" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "ast": { + "absolutePath": "src/batch/BatchDeployAndTransferOwnership.sol", + "id": 50, + "exportedSymbols": { + "BatchDeployAndTransferOwnership": [ + 49 + ], + "IOwnableContract": [ + 7 + ] + }, + "nodeType": "SourceUnit", + "src": "32:1099:0", + "nodes": [ + { + "id": 1, + "nodeType": "PragmaDirective", + "src": "32:24:0", + "nodes": [], + "literals": [ + "solidity", + "=", + "0.8", + ".19" + ] + }, + { + "id": 7, + "nodeType": "ContractDefinition", + "src": "58:87:0", + "nodes": [ + { + "id": 6, + "nodeType": "FunctionDefinition", + "src": "89:54:0", + "nodes": [], + "functionSelector": "f2fde38b", + "implemented": false, + "kind": "function", + "modifiers": [], + "name": "transferOwnership", + "nameLocation": "98:17:0", + "parameters": { + "id": 4, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 3, + "mutability": "mutable", + "name": "newOwner", + "nameLocation": "124:8:0", + "nodeType": "VariableDeclaration", + "scope": 6, + "src": "116:16:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "116:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "115:18:0" + }, + "returnParameters": { + "id": 5, + "nodeType": "ParameterList", + "parameters": [], + "src": "142:0:0" + }, + "scope": 7, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + } + ], + "abstract": false, + "baseContracts": [], + "canonicalName": "IOwnableContract", + "contractDependencies": [], + "contractKind": "interface", + "fullyImplemented": false, + "linearizedBaseContracts": [ + 7 + ], + "name": "IOwnableContract", + "nameLocation": "68:16:0", + "scope": 50, + "usedErrors": [] + }, + { + "id": 49, + "nodeType": "ContractDefinition", + "src": "147:983:0", + "nodes": [ + { + "id": 48, + "nodeType": "FunctionDefinition", + "src": "359:769:0", + "nodes": [], + "body": { + "id": 47, + "nodeType": "Block", + "src": "403:725:0", + "nodes": [], + "statements": [ + { + "assignments": [ + 14 + ], + "declarations": [ + { + "constant": false, + "id": 14, + "mutability": "mutable", + "name": "_newContract", + "nameLocation": "417:12:0", + "nodeType": "VariableDeclaration", + "scope": 47, + "src": "409:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 13, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "409:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "id": 15, + "nodeType": "VariableDeclarationStatement", + "src": "409:20:0" + }, + { + "assignments": [ + 17 + ], + "declarations": [ + { + "constant": false, + "id": 17, + "mutability": "mutable", + "name": "_guardedSalt", + "nameLocation": "443:12:0", + "nodeType": "VariableDeclaration", + "scope": 47, + "src": "435:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 16, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "435:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 18, + "nodeType": "VariableDeclarationStatement", + "src": "435:20:0" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "510:104:0", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "518:90:0", + "value": { + "arguments": [ + { + "arguments": [], + "functionName": { + "name": "callvalue", + "nodeType": "YulIdentifier", + "src": "542:9:0" + }, + "nodeType": "YulFunctionCall", + "src": "542:11:0" + }, + { + "arguments": [ + { + "name": "_initCode", + "nodeType": "YulIdentifier", + "src": "559:9:0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "570:4:0", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "555:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "555:20:0" + }, + { + "arguments": [ + { + "name": "_initCode", + "nodeType": "YulIdentifier", + "src": "583:9:0" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "577:5:0" + }, + "nodeType": "YulFunctionCall", + "src": "577:16:0" + }, + { + "name": "_guardedSalt", + "nodeType": "YulIdentifier", + "src": "595:12:0" + } + ], + "functionName": { + "name": "create2", + "nodeType": "YulIdentifier", + "src": "534:7:0" + }, + "nodeType": "YulFunctionCall", + "src": "534:74:0" + }, + "variableNames": [ + { + "name": "_newContract", + "nodeType": "YulIdentifier", + "src": "518:12:0" + } + ] + } + ] + }, + "evmVersion": "london", + "externalReferences": [ + { + "declaration": 17, + "isOffset": false, + "isSlot": false, + "src": "595:12:0", + "valueSize": 1 + }, + { + "declaration": 10, + "isOffset": false, + "isSlot": false, + "src": "559:9:0", + "valueSize": 1 + }, + { + "declaration": 10, + "isOffset": false, + "isSlot": false, + "src": "583:9:0", + "valueSize": 1 + }, + { + "declaration": 14, + "isOffset": false, + "isSlot": false, + "src": "518:12:0", + "valueSize": 1 + } + ], + "id": 19, + "nodeType": "InlineAssembly", + "src": "501:113:0" + }, + { + "clauses": [ + { + "block": { + "id": 27, + "nodeType": "Block", + "src": "752:2:0", + "statements": [] + }, + "errorName": "", + "id": 28, + "nodeType": "TryCatchClause", + "src": "752:2:0" + }, + { + "block": { + "id": 36, + "nodeType": "Block", + "src": "765:40:0", + "statements": [ + { + "expression": { + "id": 34, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 29, + "name": "_newContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 14, + "src": "773:12:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "arguments": [ + { + "hexValue": "30", + "id": 32, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "796:1:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 31, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "788:7:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 30, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "788:7:0", + "typeDescriptions": {} + } + }, + "id": 33, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "788:10:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "773:25:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 35, + "nodeType": "ExpressionStatement", + "src": "773:25:0" + } + ] + }, + "errorName": "", + "id": 37, + "nodeType": "TryCatchClause", + "src": "759:46:0" + } + ], + "externalCall": { + "arguments": [ + { + "expression": { + "id": 24, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "740:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 25, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "744:6:0", + "memberName": "sender", + "nodeType": "MemberAccess", + "src": "740:10:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "arguments": [ + { + "id": 21, + "name": "_newContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 14, + "src": "708:12:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 20, + "name": "IOwnableContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 7, + "src": "691:16:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IOwnableContract_$7_$", + "typeString": "type(contract IOwnableContract)" + } + }, + "id": 22, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "691:30:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IOwnableContract_$7", + "typeString": "contract IOwnableContract" + } + }, + "id": 23, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "722:17:0", + "memberName": "transferOwnership", + "nodeType": "MemberAccess", + "referencedDeclaration": 6, + "src": "691:48:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$returns$__$", + "typeString": "function (address) external" + } + }, + "id": 26, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "691:60:0", + "tryCall": true, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 38, + "nodeType": "TryStatement", + "src": "687:118:0" + }, + { + "assignments": [ + 40 + ], + "declarations": [ + { + "constant": false, + "id": 40, + "mutability": "mutable", + "name": "data", + "nameLocation": "824:4:0", + "nodeType": "VariableDeclaration", + "scope": 47, + "src": "811:17:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 39, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "811:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + } + ], + "id": 45, + "initialValue": { + "arguments": [ + { + "id": 43, + "name": "_newContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 14, + "src": "842:12:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "id": 41, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "831:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 42, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "835:6:0", + "memberName": "encode", + "nodeType": "MemberAccess", + "src": "831:10:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 44, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "831:24:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "811:44:0" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "1002:122:0", + "statements": [ + { + "nodeType": "YulVariableDeclaration", + "src": "1010:30:0", + "value": { + "arguments": [ + { + "name": "data", + "nodeType": "YulIdentifier", + "src": "1031:4:0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "1037:2:0", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "1027:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "1027:13:0" + }, + "variables": [ + { + "name": "dataStart", + "nodeType": "YulTypedName", + "src": "1014:9:0", + "type": "" + } + ] + }, + { + "nodeType": "YulVariableDeclaration", + "src": "1047:38:0", + "value": { + "arguments": [ + { + "arguments": [], + "functionName": { + "name": "msize", + "nodeType": "YulIdentifier", + "src": "1066:5:0" + }, + "nodeType": "YulFunctionCall", + "src": "1066:7:0" + }, + { + "name": "dataStart", + "nodeType": "YulIdentifier", + "src": "1075:9:0" + } + ], + "functionName": { + "name": "sub", + "nodeType": "YulIdentifier", + "src": "1062:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "1062:23:0" + }, + "variables": [ + { + "name": "dataEnd", + "nodeType": "YulTypedName", + "src": "1051:7:0", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "dataStart", + "nodeType": "YulIdentifier", + "src": "1099:9:0" + }, + { + "name": "dataEnd", + "nodeType": "YulIdentifier", + "src": "1110:7:0" + } + ], + "functionName": { + "name": "return", + "nodeType": "YulIdentifier", + "src": "1092:6:0" + }, + "nodeType": "YulFunctionCall", + "src": "1092:26:0" + }, + "nodeType": "YulExpressionStatement", + "src": "1092:26:0" + } + ] + }, + "evmVersion": "london", + "externalReferences": [ + { + "declaration": 40, + "isOffset": false, + "isSlot": false, + "src": "1031:4:0", + "valueSize": 1 + } + ], + "id": 46, + "nodeType": "InlineAssembly", + "src": "993:131:0" + } + ] + }, + "documentation": { + "id": 8, + "nodeType": "StructuredDocumentation", + "src": "192:164:0", + "text": " @notice Simulates a deployment and transfer ownership as if this contract was a factory\n @param _initCode The contract we are deploings init code" + }, + "implemented": true, + "kind": "constructor", + "modifiers": [], + "name": "", + "nameLocation": "-1:-1:-1", + "parameters": { + "id": 11, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 10, + "mutability": "mutable", + "name": "_initCode", + "nameLocation": "384:9:0", + "nodeType": "VariableDeclaration", + "scope": 48, + "src": "371:22:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 9, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "371:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + } + ], + "src": "370:24:0" + }, + "returnParameters": { + "id": 12, + "nodeType": "ParameterList", + "parameters": [], + "src": "403:0:0" + }, + "scope": 49, + "stateMutability": "payable", + "virtual": false, + "visibility": "public" + } + ], + "abstract": false, + "baseContracts": [], + "canonicalName": "BatchDeployAndTransferOwnership", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "linearizedBaseContracts": [ + 49 + ], + "name": "BatchDeployAndTransferOwnership", + "nameLocation": "156:31:0", + "scope": 50, + "usedErrors": [] + } + ], + "license": "MIT" + }, + "id": 0 +} \ No newline at end of file diff --git a/src/abi/BatchDeployAndTransferOwnership.sol/IOwnableContract.json b/src/abi/BatchDeployAndTransferOwnership.sol/IOwnableContract.json new file mode 100644 index 0000000..1ee7cdd --- /dev/null +++ b/src/abi/BatchDeployAndTransferOwnership.sol/IOwnableContract.json @@ -0,0 +1,940 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": { + "object": "0x", + "sourceMap": "", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x", + "sourceMap": "", + "linkReferences": {} + }, + "methodIdentifiers": { + "transferOwnership(address)": "f2fde38b" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/batch/BatchDeployAndTransferOwnership.sol\":\"IOwnableContract\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":hardhat/=node_modules/hardhat/\"]},\"sources\":{\"src/batch/BatchDeployAndTransferOwnership.sol\":{\"keccak256\":\"0x81b97e4c3bef21203fb75ed63b6bb356bd0253118abacb3da7a60ecb6ee8495d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://142e32ceda7d609cd94f1e1417d018080afcadb3290bae1c64aa62638b47755f\",\"dweb:/ipfs/QmU43YaweEYQ3zcMNsmMdLajHUBD7E1cLk3EE532ixWxc5\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.8.19+commit.7dd6d404" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transferOwnership" + } + ], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "settings": { + "remappings": [ + "hardhat/=node_modules/hardhat/" + ], + "optimizer": { + "enabled": false, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "src/batch/BatchDeployAndTransferOwnership.sol": "IOwnableContract" + }, + "libraries": {} + }, + "sources": { + "src/batch/BatchDeployAndTransferOwnership.sol": { + "keccak256": "0x81b97e4c3bef21203fb75ed63b6bb356bd0253118abacb3da7a60ecb6ee8495d", + "urls": [ + "bzz-raw://142e32ceda7d609cd94f1e1417d018080afcadb3290bae1c64aa62638b47755f", + "dweb:/ipfs/QmU43YaweEYQ3zcMNsmMdLajHUBD7E1cLk3EE532ixWxc5" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "ast": { + "absolutePath": "src/batch/BatchDeployAndTransferOwnership.sol", + "id": 50, + "exportedSymbols": { + "BatchDeployAndTransferOwnership": [ + 49 + ], + "IOwnableContract": [ + 7 + ] + }, + "nodeType": "SourceUnit", + "src": "32:1099:0", + "nodes": [ + { + "id": 1, + "nodeType": "PragmaDirective", + "src": "32:24:0", + "nodes": [], + "literals": [ + "solidity", + "=", + "0.8", + ".19" + ] + }, + { + "id": 7, + "nodeType": "ContractDefinition", + "src": "58:87:0", + "nodes": [ + { + "id": 6, + "nodeType": "FunctionDefinition", + "src": "89:54:0", + "nodes": [], + "functionSelector": "f2fde38b", + "implemented": false, + "kind": "function", + "modifiers": [], + "name": "transferOwnership", + "nameLocation": "98:17:0", + "parameters": { + "id": 4, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 3, + "mutability": "mutable", + "name": "newOwner", + "nameLocation": "124:8:0", + "nodeType": "VariableDeclaration", + "scope": 6, + "src": "116:16:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "116:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "115:18:0" + }, + "returnParameters": { + "id": 5, + "nodeType": "ParameterList", + "parameters": [], + "src": "142:0:0" + }, + "scope": 7, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + } + ], + "abstract": false, + "baseContracts": [], + "canonicalName": "IOwnableContract", + "contractDependencies": [], + "contractKind": "interface", + "fullyImplemented": false, + "linearizedBaseContracts": [ + 7 + ], + "name": "IOwnableContract", + "nameLocation": "68:16:0", + "scope": 50, + "usedErrors": [] + }, + { + "id": 49, + "nodeType": "ContractDefinition", + "src": "147:983:0", + "nodes": [ + { + "id": 48, + "nodeType": "FunctionDefinition", + "src": "359:769:0", + "nodes": [], + "body": { + "id": 47, + "nodeType": "Block", + "src": "403:725:0", + "nodes": [], + "statements": [ + { + "assignments": [ + 14 + ], + "declarations": [ + { + "constant": false, + "id": 14, + "mutability": "mutable", + "name": "_newContract", + "nameLocation": "417:12:0", + "nodeType": "VariableDeclaration", + "scope": 47, + "src": "409:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 13, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "409:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "id": 15, + "nodeType": "VariableDeclarationStatement", + "src": "409:20:0" + }, + { + "assignments": [ + 17 + ], + "declarations": [ + { + "constant": false, + "id": 17, + "mutability": "mutable", + "name": "_guardedSalt", + "nameLocation": "443:12:0", + "nodeType": "VariableDeclaration", + "scope": 47, + "src": "435:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 16, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "435:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 18, + "nodeType": "VariableDeclarationStatement", + "src": "435:20:0" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "510:104:0", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "518:90:0", + "value": { + "arguments": [ + { + "arguments": [], + "functionName": { + "name": "callvalue", + "nodeType": "YulIdentifier", + "src": "542:9:0" + }, + "nodeType": "YulFunctionCall", + "src": "542:11:0" + }, + { + "arguments": [ + { + "name": "_initCode", + "nodeType": "YulIdentifier", + "src": "559:9:0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "570:4:0", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "555:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "555:20:0" + }, + { + "arguments": [ + { + "name": "_initCode", + "nodeType": "YulIdentifier", + "src": "583:9:0" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "577:5:0" + }, + "nodeType": "YulFunctionCall", + "src": "577:16:0" + }, + { + "name": "_guardedSalt", + "nodeType": "YulIdentifier", + "src": "595:12:0" + } + ], + "functionName": { + "name": "create2", + "nodeType": "YulIdentifier", + "src": "534:7:0" + }, + "nodeType": "YulFunctionCall", + "src": "534:74:0" + }, + "variableNames": [ + { + "name": "_newContract", + "nodeType": "YulIdentifier", + "src": "518:12:0" + } + ] + } + ] + }, + "evmVersion": "london", + "externalReferences": [ + { + "declaration": 17, + "isOffset": false, + "isSlot": false, + "src": "595:12:0", + "valueSize": 1 + }, + { + "declaration": 10, + "isOffset": false, + "isSlot": false, + "src": "559:9:0", + "valueSize": 1 + }, + { + "declaration": 10, + "isOffset": false, + "isSlot": false, + "src": "583:9:0", + "valueSize": 1 + }, + { + "declaration": 14, + "isOffset": false, + "isSlot": false, + "src": "518:12:0", + "valueSize": 1 + } + ], + "id": 19, + "nodeType": "InlineAssembly", + "src": "501:113:0" + }, + { + "clauses": [ + { + "block": { + "id": 27, + "nodeType": "Block", + "src": "752:2:0", + "statements": [] + }, + "errorName": "", + "id": 28, + "nodeType": "TryCatchClause", + "src": "752:2:0" + }, + { + "block": { + "id": 36, + "nodeType": "Block", + "src": "765:40:0", + "statements": [ + { + "expression": { + "id": 34, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 29, + "name": "_newContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 14, + "src": "773:12:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "arguments": [ + { + "hexValue": "30", + "id": 32, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "796:1:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 31, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "788:7:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 30, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "788:7:0", + "typeDescriptions": {} + } + }, + "id": 33, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "788:10:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "773:25:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 35, + "nodeType": "ExpressionStatement", + "src": "773:25:0" + } + ] + }, + "errorName": "", + "id": 37, + "nodeType": "TryCatchClause", + "src": "759:46:0" + } + ], + "externalCall": { + "arguments": [ + { + "expression": { + "id": 24, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "740:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 25, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "744:6:0", + "memberName": "sender", + "nodeType": "MemberAccess", + "src": "740:10:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "arguments": [ + { + "id": 21, + "name": "_newContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 14, + "src": "708:12:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 20, + "name": "IOwnableContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 7, + "src": "691:16:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IOwnableContract_$7_$", + "typeString": "type(contract IOwnableContract)" + } + }, + "id": 22, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "691:30:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IOwnableContract_$7", + "typeString": "contract IOwnableContract" + } + }, + "id": 23, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "722:17:0", + "memberName": "transferOwnership", + "nodeType": "MemberAccess", + "referencedDeclaration": 6, + "src": "691:48:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$returns$__$", + "typeString": "function (address) external" + } + }, + "id": 26, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "691:60:0", + "tryCall": true, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 38, + "nodeType": "TryStatement", + "src": "687:118:0" + }, + { + "assignments": [ + 40 + ], + "declarations": [ + { + "constant": false, + "id": 40, + "mutability": "mutable", + "name": "data", + "nameLocation": "824:4:0", + "nodeType": "VariableDeclaration", + "scope": 47, + "src": "811:17:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 39, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "811:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + } + ], + "id": 45, + "initialValue": { + "arguments": [ + { + "id": 43, + "name": "_newContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 14, + "src": "842:12:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "id": 41, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "831:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 42, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "835:6:0", + "memberName": "encode", + "nodeType": "MemberAccess", + "src": "831:10:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 44, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "831:24:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "811:44:0" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "1002:122:0", + "statements": [ + { + "nodeType": "YulVariableDeclaration", + "src": "1010:30:0", + "value": { + "arguments": [ + { + "name": "data", + "nodeType": "YulIdentifier", + "src": "1031:4:0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "1037:2:0", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "1027:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "1027:13:0" + }, + "variables": [ + { + "name": "dataStart", + "nodeType": "YulTypedName", + "src": "1014:9:0", + "type": "" + } + ] + }, + { + "nodeType": "YulVariableDeclaration", + "src": "1047:38:0", + "value": { + "arguments": [ + { + "arguments": [], + "functionName": { + "name": "msize", + "nodeType": "YulIdentifier", + "src": "1066:5:0" + }, + "nodeType": "YulFunctionCall", + "src": "1066:7:0" + }, + { + "name": "dataStart", + "nodeType": "YulIdentifier", + "src": "1075:9:0" + } + ], + "functionName": { + "name": "sub", + "nodeType": "YulIdentifier", + "src": "1062:3:0" + }, + "nodeType": "YulFunctionCall", + "src": "1062:23:0" + }, + "variables": [ + { + "name": "dataEnd", + "nodeType": "YulTypedName", + "src": "1051:7:0", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "dataStart", + "nodeType": "YulIdentifier", + "src": "1099:9:0" + }, + { + "name": "dataEnd", + "nodeType": "YulIdentifier", + "src": "1110:7:0" + } + ], + "functionName": { + "name": "return", + "nodeType": "YulIdentifier", + "src": "1092:6:0" + }, + "nodeType": "YulFunctionCall", + "src": "1092:26:0" + }, + "nodeType": "YulExpressionStatement", + "src": "1092:26:0" + } + ] + }, + "evmVersion": "london", + "externalReferences": [ + { + "declaration": 40, + "isOffset": false, + "isSlot": false, + "src": "1031:4:0", + "valueSize": 1 + } + ], + "id": 46, + "nodeType": "InlineAssembly", + "src": "993:131:0" + } + ] + }, + "documentation": { + "id": 8, + "nodeType": "StructuredDocumentation", + "src": "192:164:0", + "text": " @notice Simulates a deployment and transfer ownership as if this contract was a factory\n @param _initCode The contract we are deploings init code" + }, + "implemented": true, + "kind": "constructor", + "modifiers": [], + "name": "", + "nameLocation": "-1:-1:-1", + "parameters": { + "id": 11, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 10, + "mutability": "mutable", + "name": "_initCode", + "nameLocation": "384:9:0", + "nodeType": "VariableDeclaration", + "scope": 48, + "src": "371:22:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 9, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "371:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + } + ], + "src": "370:24:0" + }, + "returnParameters": { + "id": 12, + "nodeType": "ParameterList", + "parameters": [], + "src": "403:0:0" + }, + "scope": 49, + "stateMutability": "payable", + "virtual": false, + "visibility": "public" + } + ], + "abstract": false, + "baseContracts": [], + "canonicalName": "BatchDeployAndTransferOwnership", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "linearizedBaseContracts": [ + 49 + ], + "name": "BatchDeployAndTransferOwnership", + "nameLocation": "156:31:0", + "scope": 50, + "usedErrors": [] + } + ], + "license": "MIT" + }, + "id": 0 +} \ No newline at end of file diff --git a/src/batch/BatchDeployAndTransferOwnership.sol b/src/batch/BatchDeployAndTransferOwnership.sol new file mode 100644 index 0000000..470d3a8 --- /dev/null +++ b/src/batch/BatchDeployAndTransferOwnership.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.19; + +interface IOwnableContract { + function transferOwnership(address newOwner) external; +} + +contract BatchDeployAndTransferOwnership { + /** + * @notice Simulates a deployment and transfer ownership as if this contract was a factory + * @param _initCode The contract we are deploings init code + */ + constructor(bytes memory _initCode) payable { + address _newContract; + uint256 _guardedSalt; + + // Deploy the contract via CREATE2 + assembly { + _newContract := create2(callvalue(), add(_initCode, 0x20), mload(_initCode), _guardedSalt) + } + + // Attempt to transfer ownership to see if the function exists + try IOwnableContract(_newContract).transferOwnership(msg.sender) {} + catch { + _newContract = address(0); + } + + bytes memory data = abi.encode(_newContract); + + // force constructor to return data via assembly + // If everything was successful will return the address of the deployment + assembly { + let dataStart := add(data, 32) + let dataEnd := sub(msize(), dataStart) + return(dataStart, dataEnd) + } + } +} diff --git a/src/constants.ts b/src/constants.ts index 8f26064..c3709f1 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,5 +1,11 @@ -export const SIGNATURE_PROXY_FACTORY_ADDRESS = '0xeeb1498dA3C99376d2E47cc2d8520884FcedB99D'; -export const SIGNATURE_PROXY_FACTORY_ABI = [{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"contract ISignatureProxy","name":"_signatureProxy","type":"address"}],"name":"DeploySignatureProxy","type":"event"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"deploy","outputs":[{"internalType":"contract ISignatureProxy","name":"_signatureProxy","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"deployAndExec","outputs":[{"internalType":"contract ISignatureProxy","name":"_signatureProxy","type":"address"},{"internalType":"bytes","name":"_returnData","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getSignatureProxy","outputs":[{"internalType":"contract ISignatureProxy","name":"_signatureProxy","type":"address"}],"stateMutability":"view","type":"function"}]; -export const SIGNATURE_PROXY_ABI = [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"bytes","name":"_returnData","type":"bytes"}],"name":"SignatureProxy_FailedCall","type":"error"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_signer","type":"address"}],"name":"SignatureProxy_NotOwner","type":"error"},{"inputs":[],"name":"OWNER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"exec","outputs":[{"internalType":"bytes","name":"_returnData","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"nextNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]; -// In order to get the data look for a sample deployment tx in tenderly and see the init code used. It appears in the debugger as the input to CREATE2. -export const SIGNATURE_PROXY_CHILD_INIT_CODE = '0x60a060405234801561001057600080fd5b506040516108da3803806108da83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161084961009160003960008181605601526101b801526108496000f3fe6080604052600436106100385760003560e01c8063117803e314610044578063a03ce6ab146100a2578063d69c3d30146100c257600080fd5b3661003f57005b600080fd5b34801561005057600080fd5b506100787f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100b56100b03660046105cd565b6100e6565b6040516100999190610762565b3480156100ce57600080fd5b506100d860005481565b604051908152602001610099565b606060008787874660005460405160200161010595949392919061077c565b6040516020818303038152906040528051906020012090506000610156827f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b604080516020810188905280820187905260f889901b7fff0000000000000000000000000000000000000000000000000000000000000016606082015281516041818303018152606190910190915290915060006101b4838361030f565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8082169083161461024e576040517f6819f52a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8083166004830152831660248201526044015b60405180910390fd5b60008c73ffffffffffffffffffffffffffffffffffffffff168b8d60405161027691906107c8565b60006040518083038185875af1925050503d80600081146102b3576040519150601f19603f3d011682016040523d82523d6000602084013e6102b8565b606091505b5097509050806102f657866040517f53a5bf440000000000000000000000000000000000000000000000000000000081526004016102459190610762565b5050600080546001019055505050509695505050505050565b60008060008061031f8686610339565b92509250925061032f8282610386565b5090949350505050565b600080600083516041036103735760208401516040850151606086015160001a6103658882858561048e565b95509550955050505061037f565b50508151600091506002905b9250925092565b600082600381111561039a5761039a6107e4565b036103a3575050565b60018260038111156103b7576103b76107e4565b036103ee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610402576104026107e4565b0361043c576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610245565b6003826003811115610450576104506107e4565b0361048a576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610245565b5050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156104c9575060009150600390508261057e565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561051d573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166105745750600092506001915082905061057e565b9250600091508190505b9450945094915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803560ff811681146105c857600080fd5b919050565b60008060008060008060c087890312156105e657600080fd5b863573ffffffffffffffffffffffffffffffffffffffff8116811461060a57600080fd5b9550602087013567ffffffffffffffff8082111561062757600080fd5b818901915089601f83011261063b57600080fd5b81358181111561064d5761064d610588565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561069357610693610588565b816040528281528c60208487010111156106ac57600080fd5b826020860160208301376000602084830101528099505050505050604087013593506106da606088016105b7565b92506080870135915060a087013590509295509295509295565b60005b8381101561070f5781810151838201526020016106f7565b50506000910152565b600081518084526107308160208601602086016106f4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006107756020830184610718565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8616815260a0602082015260006107ab60a0830187610718565b604083019590955250606081019290925260809091015292915050565b600082516107da8184602087016106f4565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220b320f4298e1e313e4626e2a9410f38ffcaf13b74667f5308fe3750309830fc2764736f6c634300081400330000000000000000000000006fa32937e61f488e7bd87511d5a1fa859189aacd'; \ No newline at end of file +export const SIMPLE_ACCOUNT_FACTORY_ADDRESS = '0x9406Cc6185a346906296840746125a0E44976454'; + +export const DUMMY_SIG = '0xa15569dd8f8324dbeabf8023fdec36d4b754f53ce5901e283c6de79af177dc94557fa3c9922cd7af2a96ca94402d35c39f266925ee6407aeb32b31d76978d4ba1c'; + +export const CREATEX_FACTORY = '0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed'; + +export const MAIN_FOLDER_NAME = './sponsored-transactions'; + +export const LATEST_FOLDER_NAME = `${ MAIN_FOLDER_NAME }/run-latest`; + +export const JIFFYSCAN_URL = 'https://jiffyscan.xyz/userOpHash' diff --git a/src/gasless-provider.ts b/src/gasless-provider.ts index 73e27f3..cb72854 100644 --- a/src/gasless-provider.ts +++ b/src/gasless-provider.ts @@ -1,121 +1,550 @@ -import { ethers } from "ethers"; -import { ProviderWrapper } from "hardhat/plugins"; -import { EIP1193Provider, RequestArguments } from "hardhat/types"; -import init from "debug"; -import axios, { AxiosInstance } from "axios"; -import { SIGNATURE_PROXY_ABI, SIGNATURE_PROXY_FACTORY_ADDRESS, SIGNATURE_PROXY_CHILD_INIT_CODE } from "./constants"; - -const log = init("hardhat:plugin:gasless"); - -// TODO: Using wallets with no ETH does not work -// TODO: Test this with value transfers -// TODO: Test this with tx type 0, 1 -export class GaslessProvider extends ProviderWrapper { +import { BytesLike, Transaction, ethers } from 'ethers'; +import { ProviderWrapper } from 'hardhat/plugins'; +import { EIP1193Provider, RequestArguments } from 'hardhat/types'; +import init from 'debug'; +import { createPublicClient, encodeFunctionData, Hex, getCreateAddress, TransactionReceipt } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { PimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { UserOperation } from 'permissionless/types'; +import { GetUserOperationReceiptReturnType } from 'permissionless'; +import { signUserOperationHashWithECDSA, getAccountNonce } from './mock'; +import * as constants from './constants'; +import { bytecode as batchDeployAndTransferOwnershipBytecode } from './abi/BatchDeployAndTransferOwnership.sol/BatchDeployAndTransferOwnership.json'; +import { Paymaster } from './paymasters'; +import { PartialBy } from 'viem/types/utils'; +import { txToJson, getSmartAccountData, getRandomHex32ByteString, emptyFolder } from './utils'; +import { EstimateGasTxn } from './types'; + +const log = init('hardhat:plugin:gasless'); - private readonly _sponsorAPI: AxiosInstance; +/** + * Gasless Provider class that routes transactions through a bundler and paymaster, based on the ERC 4337 standard + */ +export class GaslessProvider extends ProviderWrapper { + private _expectedDeploymentsToCreateXDeployments: Map<`0x${string}`, `0x${string}`>; + private _txnHashToDeployment: Map<`0x${string}`, `0x${string}`>; + private _runTimestamp: number; constructor( - protected readonly _signerPk: string, + protected readonly _signerPk: `0x${string}`, protected readonly _wrappedProvider: EIP1193Provider, - public readonly sponsorUrl: string, + protected readonly bundlerClient: PimlicoBundlerClient, + protected readonly paymasterClient: Paymaster, + protected readonly publicClient: ReturnType, + protected readonly _initCode: `0x${string}`, + protected readonly senderAddress: `0x${string}`, + protected readonly _owner: ReturnType, + protected readonly _entryPoint: `0x${string}`, + protected readonly _simpleAccountFactoryAddress: `0x${string}`, + protected _nonce: bigint, ) { super(_wrappedProvider); - this._sponsorAPI = axios.create({baseURL: this.sponsorUrl}); + this._expectedDeploymentsToCreateXDeployments = new Map<`0x${string}`, `0x${string}`>(); + this._txnHashToDeployment = new Map<`0x${string}`, `0x${string}`>(); + + // Save the current timestamp to be used when generating the run folder + this._runTimestamp = Math.floor(Date.now() / 1000); } + /** + * Asynchronously creates a new GaslessProvider + * @param _signerPk The signer of the transactions that will be sent through the provider + * @param _wrappedProvider The provider that we are wrapping + * @param bundlerClient The bundler client we will submit bundles to + * @param paymasterClient The paymaster that will sponsor our transactions + * @param publicClient The public client that will be used to query for gas prices + * @param simpleAccountFactoryAddress The simple account factory address to use + * @returns A new GaslessProvider + */ + static async create( + _signerPk: `0x${string}`, + _wrappedProvider: EIP1193Provider, + bundlerClient: PimlicoBundlerClient, + paymasterClient: Paymaster, + publicClient: ReturnType, + simpleAccountFactoryAddress: `0x${string}`, + smartAccount?: `0x${string}`, + ) { + // Clear latest folder + await emptyFolder(constants.LATEST_FOLDER_NAME); + + // NOTE: Bundlers can support many entry points, but currently they only support one, we use this method so if they ever add a new one the entry point will still work + const entryPoint = (await bundlerClient.supportedEntryPoints())[0]; + const owner = privateKeyToAccount(_signerPk); + + const { initCode, senderAddress } = !smartAccount + ? await getSmartAccountData(publicClient, simpleAccountFactoryAddress, owner.address, entryPoint) + : ({ initCode: '0x', senderAddress: smartAccount } as { + initCode: `0x${string}`; + senderAddress: `0x${string}`; + }); + + const nonce = await getAccountNonce(publicClient, { + sender: senderAddress, + entryPoint: entryPoint, + }); + + const gaslessProvider = new GaslessProvider( + _signerPk, + _wrappedProvider, + bundlerClient, + paymasterClient, + publicClient, + initCode, + senderAddress, + owner, + entryPoint, + simpleAccountFactoryAddress, + nonce, + ); + + return gaslessProvider; + } + + /** + * Sends requests to the provider, if the request is a transaction, it will be sent through the bundler and paymaster. + * If the request is a smart contract address request, it will be queried from the public client and return the smart account address + * @param args The arguments for the request + * @returns Unknown, as it depends on the request being made + */ public request(args: RequestArguments): Promise { - if (args.method === "eth_sendRawTransaction" && args.params !== undefined) { - const params = this._getParams(args); - return this._sendGaslessTransaction(params[0]); + if (args.method === 'aa_getSmartAccountAddress') { + return this._getSmartAccountAddress(); + } + + if (args.params !== undefined) { + // Need to override this for plugins that check receipt for deployment addresses + if (args.method === 'eth_getTransactionReceipt') { + const params = this._getParams(args); + return this._getTransactionReceipt(params[0]); + } + + if (args.method === 'eth_sendRawTransaction') { + const params = this._getParams(args); + return this._sendGaslessTransaction(params[0]); + } + + if (args.method === 'aa_getDeploymentFor') { + const params = this._getParams(args); + return this._getDeploymentFor(params[0]); + } + + if (args.method === 'eth_estimateGas') { + const params = this._getParams(args); + return this._estimateGas(params[0]); + } + + // We need to partially overwrite eth_call incase the 'to' field uses an address that was deployed from us + if (args.method === 'eth_call') { + const params = this._getParams(args); + + const newParams = params.map((tx) => { + // Check if the address being called to was deployed by us + const deploymentFromCreateX = this._expectedDeploymentsToCreateXDeployments.get( + tx.to?.toLowerCase() as `0x${string}`, + ); + + // If it was deployed by us overrwrite tx.to with our address + if (deploymentFromCreateX !== undefined) { + tx.to = deploymentFromCreateX.toLowerCase(); + } + + if (tx.data !== undefined) { + tx.data = this._checkCalldataForBadDeployments(tx.data as `0x${string}`); + } + + // Return the new transaction + return tx; + }); + + return this._wrappedProvider.request({ method: 'eth_call', params: newParams }); + } } return this._wrappedProvider.request(args); } - public async _sendGaslessTransaction(tx: string): Promise { - const signer = new ethers.Wallet(this._signerPk); - + /** + * Sends a gasless transaction + * @param tx The transactions that needs to be bundled and sponsored + * @returns The transaction hash of the sponsored transaction + */ + private async _sendGaslessTransaction(tx: string): Promise { log('Transaction to be signed for sponsoring', tx); - const { to, data } = ethers.utils.parseTransaction(tx); - - const value = 0; - const chainId = await this.getChainId(); - const proxyAddress = this.getProxyAddress(signer.address); - log('Signer computed proxy address', proxyAddress); - - let nextNonce = 0; - const isProxyDeployed = await this.isContractDeployed(proxyAddress); - if (isProxyDeployed) { - nextNonce = await this.getProxyNextNonce(proxyAddress); - log(`Proxy is deployed and its next nonce is ${nextNonce}`); + + // Parse the transaction + const parsedTxn = Transaction.from(tx); + + // Create the user operation + const { userOperation, to } = await this._createUserOperation(tx); + + const paymasterAndData = await this.paymasterClient.sponsorUserOperation(userOperation, this._entryPoint); + + const sponsoredUserOperation: UserOperation = Object.assign(userOperation, paymasterAndData); + + // SIGN THE USER OPERATION + const signature = await signUserOperationHashWithECDSA({ + account: this._owner, + userOperation: sponsoredUserOperation, + chainId: await this.publicClient.getChainId(), + entryPoint: this._entryPoint, + }); + sponsoredUserOperation.signature = signature; + + let userOperationHash: `0x${string}`; + + try { + // SUBMIT THE USER OPERATION TO BE BUNDLED + userOperationHash = await this.bundlerClient.sendUserOperation({ + userOperation: sponsoredUserOperation, + entryPoint: this._entryPoint, + }); + } catch (e) { + // There are some bundler and paymaster combos that are incompatible due to certain bundlers requiring certain gas prices and paymasters might have a different minimum set for example + // We throw this error because if the scripts fail here its because of a combo incompatibility which is out of our control + throw new Error( + `Failed to send user operation! There might be an incompatibility with your bundle and paymaster, try changing one of them. The submission failed from the following error:\n ${e}`, + ); } - log('Signing message for sponsoring', { - signer: signer.address, - to, - data, - value, - chainId, - nonce: nextNonce, - }) - const signature = await this.encodeMessage(signer, to as string, data, value, chainId, nextNonce); - - // call the API - const request = { - from: signer.address, - to: to, - data: data, - value, - ...signature, - }; - log('Sending request to sponsor', { sponsor: this.sponsorUrl, request }) - const sponsorResponse = await this._sponsorAPI.post('/tx-signature', [request]); - const txHash = sponsorResponse.data[0]; - log('Received tx hash from sponsor', txHash); - + log('Received User Operation hash:', userOperationHash); + + // let's also wait for the userOperation to be included, by continually querying for the receipts + log('Querying for receipts...'); + + let receipt: GetUserOperationReceiptReturnType; + try { + // Wait 2 minutes for a receipt if we still cant find one we assume something went wrong with the bundler and throw an error to avoid terminal hanging + receipt = await this.bundlerClient.waitForUserOperationReceipt({ hash: userOperationHash, timeout: 120000 }); + } catch (e) { + throw new Error( + `Failed to get user operation receipt! This usually fails when there is a problem bundling the UserOperation, make sure your transaction is valid! The query reverted with:\n ${e}`, + ); + } + + // If it was a deployment call we need to get the deployed to address from the logs + if (!parsedTxn.to) { + // NOTE: We need to always set the expectedDeployment in lowercase for consistency, our deployment can stay normal cased + const deploymentTxn = await this.publicClient.getTransaction({ hash: receipt.receipt.transactionHash }); + const nonce = deploymentTxn.nonce; + const expectedDeployment = getCreateAddress({ + nonce: BigInt(nonce), + from: receipt.receipt.from, + }).toLowerCase() as `0x${string}`; + + receipt.logs.forEach((log) => { + if (log.address === to) { + // 1st index of topics is the deployed address + const paddedAddress = log.topics[1]; + const deployment = ('0x' + paddedAddress.slice(-40)) as `0x${string}`; + this._expectedDeploymentsToCreateXDeployments.set(expectedDeployment, deployment); + + // Set this so receipt fetchers will be able to see it in eth_getTransactionReceipt + this._txnHashToDeployment.set(receipt.receipt.transactionHash, deployment); + } + }); + } + + await txToJson( + sponsoredUserOperation, + receipt, + this._txnHashToDeployment.get(receipt.receipt.transactionHash), + this._runTimestamp, + ); + + const txHash = receipt.receipt.transactionHash; + log('Transaction hash:', txHash); + + if (receipt.success) { + console.log(`Transaction mined successfully 🚀: ${constants.JIFFYSCAN_URL}/${userOperationHash}`); + } else { + console.log(`Transaction reverted ❌: ${constants.JIFFYSCAN_URL}/${userOperationHash}`); + } + + // Increment nonce for the next transaction + this._nonce += 1n; // return the tx hash return txHash; } - private async getChainId(): Promise { - const rawChainId = await this._wrappedProvider.request({method: "eth_chainId", params: []}) as string; - return parseInt(rawChainId); - }; + /** + * Creates a user operation from a transaction + * @param tx The transaction as a string + * @returns The user operation and the address that the smart account is calling to + */ + private async _createUserOperation(tx: string | EstimateGasTxn): Promise<{ + userOperation: PartialBy< + UserOperation, + 'callGasLimit' | 'preVerificationGas' | 'verificationGasLimit' | 'paymasterAndData' + >; + to: `0x${string}`; + }> { + // Parse the transaction + const parsedTxn = typeof tx === 'string' ? Transaction.from(tx) : tx; + + const value = + typeof parsedTxn.value === 'string' + ? BigInt(parsedTxn.value) + : parsedTxn.value !== undefined + ? parsedTxn.value + : 0n; + + // Get gas prices + const { maxFeePerGas, maxPriorityFeePerGas } = await this.publicClient.estimateFeesPerGas(); + + // Check if a bad deployment address is used in the calldata anywhere, and update to use the correct deployment address + const originalCalldata: `0x${string}` = this._checkCalldataForBadDeployments(parsedTxn.data as `0x${string}`); + let txnData: `0x${string}` = originalCalldata; + let to: `0x${string}` = parsedTxn.to as `0x${string}`; - private getProxyAddress(signer: string): string { - return ethers.utils.getCreate2Address( - SIGNATURE_PROXY_FACTORY_ADDRESS, - ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['address'], [signer])), - ethers.utils.solidityKeccak256(['bytes'], [SIGNATURE_PROXY_CHILD_INIT_CODE]) + // If parsedTxn.to doesnt exist it is a deployment transaction and needs special functionality of sending a transaction to a factory + if (!parsedTxn.to) { + to = constants.CREATEX_FACTORY; + + // If it is a contract deployment we will simulate if the contract is ownable by transferring ownership to the smart account, if transferOwnership fails we will do nothing + const needsHandleOwnable = await this._simulateContractDeploymentIsOwnable(originalCalldata); + + // Create the bytecode to deploy through the CreateXFactory and transfer ownership to the smart account if needed + txnData = needsHandleOwnable + ? this._createOwnableDeploymentBytecode(originalCalldata, value) + : this._createNonOwnableDeploymentBytecode(originalCalldata); + } + + // If "to" is a fake address that we deployed customly we will overwrite the "to" param + const potentialToAddress = this._expectedDeploymentsToCreateXDeployments.get( + parsedTxn.to?.toLowerCase() as `0x${string}`, ); + if (potentialToAddress !== undefined) { + to = potentialToAddress; + } + + // Generate calldata + // This calldata is hardcoded as it is calldata for pimlico to execute + const callData = encodeFunctionData({ + abi: [ + { + inputs: [ + { name: 'dest', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'func', type: 'bytes' }, + ], + name: 'execute', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + ], + args: [to, value, txnData], + }); + + // Construct UserOperation + const userOperation: PartialBy< + UserOperation, + 'callGasLimit' | 'preVerificationGas' | 'verificationGasLimit' | 'paymasterAndData' + > = { + sender: this.senderAddress, + nonce: this._nonce, + initCode: this._nonce === 0n ? this._initCode : '0x', + callData, + maxFeePerGas: maxFeePerGas as bigint, + maxPriorityFeePerGas: maxPriorityFeePerGas as bigint, + // dummy signature, needs to be there so the SimpleAccount doesn't immediately revert because of invalid signature length + signature: constants.DUMMY_SIG as Hex, + callGasLimit: 0n, // dummy value + paymasterAndData: '0x', // dummy value + preVerificationGas: 0n, // dummy value + verificationGasLimit: 0n, // dummy value + }; + + return { userOperation, to }; } - private async isContractDeployed(address: string): Promise { - const code = await this._wrappedProvider.request({method: 'eth_getCode', params: [address, 'latest']}); - return code !== '0x'; + /** + * Overrides the estimate gas method to use the bundler client and estimate based on the user operation + * @param tx The transaction to estimate gas for + * @returns The gas limit + */ + private async _estimateGas(tx: string): Promise<`0x${string}`> { + const { userOperation } = await this._createUserOperation(tx); + const gasConfig = await this.bundlerClient.estimateUserOperationGas({ + userOperation: Object.assign(userOperation, { paymasterAndData: '0x' }), + entryPoint: this._entryPoint, + }); + + return ('0x' + gasConfig.callGasLimit.toString(16)) as `0x${string}`; } - private async getProxyNextNonce(address: string): Promise { - const proxy = new ethers.Contract(address, SIGNATURE_PROXY_ABI); - const populatedNonceFetch = await proxy.populateTransaction.nextNonce(); - const rawNonce = await this._wrappedProvider.request({method: "eth_call", params: [populatedNonceFetch, 'latest']}) as string; - return parseInt(rawNonce); + /** + * Overrides the get transaction receipt method to return a contractAddress field if needed + * @param hash The transaction hash + * @returns The updated receipt + */ + private async _getTransactionReceipt(hash: `0x${string}`): Promise { + const receipt: TransactionReceipt = (await this._wrappedProvider.request({ + method: 'eth_getTransactionReceipt', + params: [hash], + })) as TransactionReceipt; + + const deployment = this._txnHashToDeployment.get(hash); + + if (deployment !== undefined) { + receipt.contractAddress = deployment; + } + + return receipt; } - private async encodeMessage(signer: ethers.Wallet, to: string, data: string, value: number, chainId: number, nonce: number): Promise<{ r: string, s: string, v: number }> { - const encodedMessage = ethers.utils.defaultAbiCoder.encode(['address', 'bytes', 'uint256', 'uint256', 'uint256'], [to, data, value, chainId, nonce]); - log('Encoding message', { - to, data, value, chainId, nonce + /** + * Simulate a contract deployment and transferOwnership call to see if its ownable or not + * @param data The calldata of the transaction + * @returns If the contract is ownable + */ + private async _simulateContractDeploymentIsOwnable(data: `0x${string}`): Promise { + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + const inputData = abiCoder.encode(['bytes'], [data]).slice(2); + const callData = batchDeployAndTransferOwnershipBytecode.object.concat(inputData); + + try { + const response = await this._wrappedProvider.request({ + method: 'eth_call', + params: [ + { + from: this.senderAddress, + data: callData, + }, + 'latest', + ], + }); + + const [decoded] = abiCoder.decode(['address'], response as BytesLike); + + if (decoded === ethers.ZeroAddress) return false; + + return true; + } catch (e) { + throw new Error(`Deployment simulation failed with error: ${e}`); + } + } + + /** + * Creates calldata for deploying through CreateXFactory + * @param deploymentInitCode The contract that we are deploying's init code + * @returns The calldata to use for the user operation + */ + private _createNonOwnableDeploymentBytecode(deploymentInitCode: `0x${string}`): `0x${string}` { + return encodeFunctionData({ + abi: [ + { + inputs: [ + { name: 'salt', type: 'bytes32' }, + { name: 'initCode', type: 'bytes' }, + ], + name: 'deployCreate2', + outputs: [{ name: 'newContract', type: 'address' }], + stateMutability: 'payable', + type: 'function', + }, + ], + args: [getRandomHex32ByteString(), deploymentInitCode], }); - const digest = ethers.utils.keccak256(encodedMessage); - const rawSignature = await ethers.utils.joinSignature(signer._signingKey().signDigest(toEthSignedMessageHash(digest))); - const { r, s, v } = ethers.utils.splitSignature(rawSignature); - return { r, s, v }; } -} -function toEthSignedMessageHash(messageHash: string): string { - const prefix = ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n32'); - return ethers.utils.keccak256(ethers.utils.concat([prefix, messageHash])); -} \ No newline at end of file + /** + * Create the calldata for a transaction to the CreateXFactory for deploying and transfering ownership + * @param deploymentInitCode The contract that we are deploying's init code + * @param constructorAmount The value to send with our deployment + * @returns The calldata to use for the user operation + */ + private _createOwnableDeploymentBytecode( + deploymentInitCode: `0x${string}`, + constructorAmount: bigint, + ): `0x${string}` { + const initFunction = encodeFunctionData({ + abi: [ + { + inputs: [{ name: 'newOwner', type: 'address' }], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + ], + args: [this.senderAddress], + }); + + return encodeFunctionData({ + abi: [ + { + inputs: [ + { name: 'salt', type: 'bytes32' }, + { name: 'initCode', type: 'bytes' }, + { name: 'data', type: 'bytes' }, + { + name: 'values', + type: 'tuple', + components: [ + { + name: 'constructorAmount', + type: 'uint256', + }, + { + name: 'initCallAmount', + type: 'uint256', + }, + ], + }, + ], + name: 'deployCreate2AndInit', + outputs: [{ name: 'newContract', type: 'address' }], + stateMutability: 'payable', + type: 'function', + }, + ], + args: [getRandomHex32ByteString(), deploymentInitCode, initFunction, { constructorAmount, initCallAmount: 0n }], + }); + } + + /** + * Checks the calldata for bad deployments and replaces them with the correct deployment address + * @param calldata The calldata to check + * @returns The modified calldata + */ + private _checkCalldataForBadDeployments(calldata: `0x${string}`): `0x${string}` { + this._expectedDeploymentsToCreateXDeployments.forEach((value, key) => { + // Remove the 0x prefix + const badDeploymentAddress = key.slice(2); + + let index = calldata.indexOf(badDeploymentAddress); + while (index !== -1) { + // Replace only the specific section where the badDeploymentAddress is found + calldata = (calldata.substring(0, index) + + value.slice(2) + + calldata.substring(index + badDeploymentAddress.length)) as `0x${string}`; + + // Update the index for the next occurrence + index = calldata.indexOf(badDeploymentAddress, index + value.slice(2).length); + } + }); + + return calldata; + } + + /** + * Gets the deployment for a given contract + * @param contract Either an object that has the `target` field (this is where ethers stores the address) or just the address + * @returns The address that was deployed or undefined if no address was deployed + */ + private async _getDeploymentFor(contract: `0x${string}`): Promise<`0x${string}` | undefined> { + return this._expectedDeploymentsToCreateXDeployments.get(contract.toLowerCase() as `0x${string}`); + } + + /** + * Determines address for a smart account already deployed or to be deployed + * @returns A promise that resolves to sender address + * @dev Needs to be async so it returns a promise for the request method + */ + private async _getSmartAccountAddress(): Promise<`0x${string}`> { + return this.senderAddress; + } +} diff --git a/src/index.ts b/src/index.ts index 5b130dc..74b52f3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,33 +1,73 @@ -import { extendProvider } from "hardhat/config"; +import 'dotenv/config'; +import init from 'debug'; +import { extendProvider } from 'hardhat/config'; +import { createPublicClient, http } from 'viem'; +import { createPimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { createPaymasterClient } from './paymaster'; +import { SIMPLE_ACCOUNT_FACTORY_ADDRESS as constantSimpleAccountFactoryAddress } from './constants'; +import { GaslessProvider } from './gasless-provider'; +import './type-extensions'; +import { interpretPaymasterType } from './interpreter'; -import init from "debug"; +const log = init('hardhat:plugin:gasless'); -const log = init("hardhat:plugin:gasless"); - -import "./type-extensions"; -import { GaslessProvider } from "./gasless-provider"; - -extendProvider((provider, config, networkName) => { +extendProvider(async (provider, config, networkName) => { log(`Extending provider for network ${networkName}`); const netConfig = config.networks[networkName]; - // TODO: support mnemonics if (!Array.isArray(netConfig.accounts)) { log(`Mnemonics are not yet supported, skipping`); return provider; } - const signer: string = netConfig.accounts[0] as string; + const signer = netConfig.accounts[0] as `0x${string}`; - if (!("url" in netConfig)) { + if (!('url' in netConfig)) { log(`Hardhat Network detected, skipping`); return provider; } - const sponsorUrl = netConfig.sponsorUrl; - if (sponsorUrl === undefined) { - log(`No sponsor url, skipping`); + const accountAbstraction = netConfig.accountAbstraction; + if (!accountAbstraction) { + log(`No configuration for sponsored transactions set, skipping`); return provider; } - return new GaslessProvider(signer, provider, sponsorUrl); + const simpleAccountFactoryAddress = + accountAbstraction.simpleAccountFactoryAddress ?? constantSimpleAccountFactoryAddress; + + const publicClient = createPublicClient({ + transport: http(netConfig.url), + }); + + const bundlerClient = createPimlicoBundlerClient({ + transport: http(accountAbstraction.bundlerUrl), + }); + + // Check if bundler and public client share same chain Id + const bundlerChainId = await bundlerClient.chainId(); + const publicChainId = await publicClient.getChainId(); + if (bundlerChainId !== publicChainId) { + const message = `Bundler chain id ${bundlerChainId} does not match public chain id ${publicChainId} for network ${networkName}`; + log(message); + throw new Error(message); + } + + const paymasterType = interpretPaymasterType(accountAbstraction.paymasterUrl); + + const paymasterClient = createPaymasterClient( + paymasterType, + accountAbstraction.paymasterUrl, + bundlerClient, + accountAbstraction.policyId, + ); + + return await GaslessProvider.create( + signer, + provider, + bundlerClient, + paymasterClient, + publicClient, + simpleAccountFactoryAddress, + accountAbstraction.smartAccount, + ); }); diff --git a/src/interpreter.ts b/src/interpreter.ts new file mode 100644 index 0000000..1cdbb32 --- /dev/null +++ b/src/interpreter.ts @@ -0,0 +1,36 @@ +import { PaymasterType } from './types'; + +/** + * Gets the paymaster type for a given url + * @param paymasterUrl The paymaster url + * @returns The paymaster type + */ +export function interpretPaymasterType(paymasterUrl: string): PaymasterType { + if (!isValidUrl(paymasterUrl)) { + throw new Error('Invalid paymaster url'); + } + + const paymasterTypeValues = Object.values(PaymasterType) as string[]; + + for (const paymasterType of paymasterTypeValues) { + if (paymasterUrl.includes(paymasterType)) { + return paymasterType as PaymasterType; + } + } + + throw new Error(`Unknown paymaster type for url ${paymasterUrl}`); +} + +/** + * Checks if a url is valid + * @param url The url to check + * @returns True if valid, false if it isnt + */ +function isValidUrl(url: string): boolean { + try { + new URL(url); + return true; + } catch (e) { + return false; + } +} diff --git a/src/mock.ts b/src/mock.ts new file mode 100644 index 0000000..5f54988 --- /dev/null +++ b/src/mock.ts @@ -0,0 +1,11 @@ +import { + getSenderAddress as _getSenderAddress, + signUserOperationHashWithECDSA as _signUserOperationHashWithECDSA, + getAccountNonce as _getAccoutnNonce, +} from 'permissionless'; + +export const getSenderAddress = _getSenderAddress; + +export const signUserOperationHashWithECDSA = _signUserOperationHashWithECDSA; + +export const getAccountNonce = _getAccoutnNonce; diff --git a/src/paymaster.ts b/src/paymaster.ts new file mode 100644 index 0000000..0d5fd74 --- /dev/null +++ b/src/paymaster.ts @@ -0,0 +1,30 @@ +import { PimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { PaymasterType } from './types'; +import { Paymaster } from './paymasters/Paymaster'; +import * as Pm from './paymasters'; + +/** + * Creates a paymaster based on the paymaster type. + * @param paymasterType The type of paymaster to create + * @param paymasterUrl The url of the paymaster + * @param bundlerClient The bundler client to use + * @param policyId The optional policy ID for the paymaster + * @returns A paymaster + */ +export function createPaymasterClient( + paymasterType: PaymasterType, + paymasterUrl: string, + bundlerClient: PimlicoBundlerClient, + policyId?: string, +): Paymaster { + switch (paymasterType) { + case PaymasterType.Pimlico: + return new Pm.PimlicoPaymaster(paymasterUrl, policyId); + case PaymasterType.StackUp: + return new Pm.StackUpPaymaster(paymasterUrl); + case PaymasterType.Base: + return new Pm.BasePaymaster(paymasterUrl, bundlerClient); + case PaymasterType.Alchemy: + return new Pm.AlchemyPaymaster(paymasterUrl, policyId); + } +} diff --git a/src/paymasters/AlchemyPaymaster.ts b/src/paymasters/AlchemyPaymaster.ts new file mode 100644 index 0000000..54a9658 --- /dev/null +++ b/src/paymasters/AlchemyPaymaster.ts @@ -0,0 +1,44 @@ +import { SponsorUserOperationReturnType } from 'permissionless/actions/pimlico'; +import { Paymaster } from './Paymaster'; +import { PartialUserOperation } from '../types'; +import { convertBigIntsToString } from '../utils'; + +/** + * Paymaster for Alchemy + */ +export class AlchemyPaymaster extends Paymaster { + public policyId: string; + + constructor(endpoint: string, policyId: string | undefined) { + super(endpoint); + + if (!policyId) throw new Error('Policy ID is required for Alchemy Paymaster'); + this.policyId = policyId; + } + + /** + * Sponsor a user operation. + * @param userOperation The user operation to sponsor + * @param entryPoint The entry point to use + * @returns The paymasterAndData and gas information for the user operation + */ + public async sponsorUserOperation( + userOperation: PartialUserOperation, + entryPoint: `0x${string}`, + ): Promise { + const userOp = convertBigIntsToString(userOperation); + + const gasAndPaymasterAndData = (await this.endpoint.send('alchemy_requestGasAndPaymasterAndData', [ + { + policyId: this.policyId, + entryPoint: entryPoint, + dummySignature: userOperation.signature, + userOperation: userOp, + }, + ])) as SponsorUserOperationReturnType; + + return { + ...gasAndPaymasterAndData, + }; + } +} diff --git a/src/paymasters/BasePaymaster.ts b/src/paymasters/BasePaymaster.ts new file mode 100644 index 0000000..889b82d --- /dev/null +++ b/src/paymasters/BasePaymaster.ts @@ -0,0 +1,62 @@ +import { SponsorUserOperationReturnType } from 'permissionless/actions/pimlico'; +import { PimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { PartialUserOperation } from '../types'; +import { Paymaster } from './Paymaster'; +import { convertBigIntsToString } from '../utils'; + +/** + * Paymaster for Base + */ +export class BasePaymaster extends Paymaster { + public bundlerClient: PimlicoBundlerClient; + + constructor(endpoint: string, bundlerClient: PimlicoBundlerClient) { + super(endpoint); + + this.bundlerClient = bundlerClient; + } + + /** + * Sponsor a user operation. + * @param userOperation The user operation to sponsor + * @param entryPoint The entry point to use + * @returns The paymasterAndData and gas information for the user operation + */ + public async sponsorUserOperation( + userOperation: PartialUserOperation, + entryPoint: `0x${string}`, + ): Promise { + const userOp = convertBigIntsToString(userOperation); + + const chainIdAsNumber = await this.bundlerClient.chainId(); + const chainId = '0x' + chainIdAsNumber.toString(16); + + const paymasterAndDataForEstimateGas = (await this.endpoint.send('eth_paymasterAndDataForEstimateGas', [ + userOp, + entryPoint, + chainId, + ])) as `0x${string}`; + + const gasConfig = await this.bundlerClient.estimateUserOperationGas({ + userOperation: Object.assign(userOperation, { paymasterAndData: paymasterAndDataForEstimateGas }), + entryPoint, + }); + + // Adding gas headroom for safety margin to ensure paymaster signs for enough gas based on estimations + gasConfig.preVerificationGas = gasConfig.preVerificationGas + 2000n; + gasConfig.verificationGasLimit = gasConfig.verificationGasLimit + 4000n; + + const stringifyGasConfig = convertBigIntsToString(gasConfig); + + const paymasterAndDataForUserOperation = (await this.endpoint.send('eth_paymasterAndDataForUserOperation', [ + Object.assign(userOp, stringifyGasConfig), + entryPoint, + chainId, + ])) as `0x${string}`; + + return { + ...gasConfig, + paymasterAndData: paymasterAndDataForUserOperation, + }; + } +} diff --git a/src/paymasters/Paymaster.ts b/src/paymasters/Paymaster.ts new file mode 100644 index 0000000..1f014cc --- /dev/null +++ b/src/paymasters/Paymaster.ts @@ -0,0 +1,27 @@ +import { SponsorUserOperationReturnType } from 'permissionless/actions/pimlico'; +import { JsonRpcProvider } from '@ethersproject/providers'; +import { PartialUserOperation } from '../types'; + +/** + * Base class for paymasters. + */ +export abstract class Paymaster { + public endpoint: JsonRpcProvider; + + constructor(endpoint: string) { + this.endpoint = new JsonRpcProvider(endpoint); + } + + /** + * Sponsor a user operation. + * @param userOperation The user operation to sponsor + * @param entryPoint The entry point to use + * @returns The paymasterAndData and gas information for the user operation or just the paymasterAndData depending on the implementation + */ + abstract sponsorUserOperation( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + userOp: PartialUserOperation, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + entryPoint: `0x${string}`, + ): Promise; +} diff --git a/src/paymasters/PimlicoPaymaster.ts b/src/paymasters/PimlicoPaymaster.ts new file mode 100644 index 0000000..a9b4591 --- /dev/null +++ b/src/paymasters/PimlicoPaymaster.ts @@ -0,0 +1,39 @@ +import { http } from 'viem'; +import { createPimlicoPaymasterClient } from 'permissionless/clients/pimlico'; +import { SponsorUserOperationReturnType } from 'permissionless/actions/pimlico'; +import { Paymaster } from './Paymaster'; +import { PartialUserOperation } from '../types'; + +/** + * Paymaster for Pimlico. + */ +export class PimlicoPaymaster extends Paymaster { + public paymasterClient: ReturnType; + public policyId: string | undefined; + + constructor(endpoint: string, policyId: string | undefined) { + super(endpoint); + + this.paymasterClient = createPimlicoPaymasterClient({ + transport: http(endpoint), + }); + this.policyId = policyId; + } + + /** + * Sponsor a user operation. + * @param userOperation The user operation to sponsor + * @param entryPoint The entry point to use + * @returns The paymasterAndData and gas information for the user operation + */ + public async sponsorUserOperation( + userOperation: PartialUserOperation, + entryPoint: `0x${string}`, + ): Promise { + return await this.paymasterClient.sponsorUserOperation({ + userOperation, + entryPoint, + sponsorshipPolicyId: this.policyId, + }); + } +} diff --git a/src/paymasters/StackUpPaymaster.ts b/src/paymasters/StackUpPaymaster.ts new file mode 100644 index 0000000..e947a01 --- /dev/null +++ b/src/paymasters/StackUpPaymaster.ts @@ -0,0 +1,40 @@ +import { http } from 'viem'; +import { createStackupPaymasterClient } from 'permissionless/clients/stackup'; +import { SponsorUserOperationReturnType } from 'permissionless/actions/stackup'; +import { StackupPaymasterContext } from 'permissionless/types/stackup'; +import { Paymaster } from './Paymaster'; +import { PartialUserOperation } from '../types'; + +/** + * Paymaster for StackUp. + */ +export class StackUpPaymaster extends Paymaster { + public paymasterClient: ReturnType; + + constructor(endpoint: string) { + super(endpoint); + + this.paymasterClient = createStackupPaymasterClient({ + transport: http(endpoint), + }); + } + + /** + * Sponsor a user operation. + * @param userOperation The user operation to sponsor + * @param entryPoint The entry point to use + * @returns The paymasterAndData and gas information for the user operation + */ + public async sponsorUserOperation( + userOperation: PartialUserOperation, + entryPoint: `0x${string}`, + ): Promise { + return await this.paymasterClient.sponsorUserOperation({ + userOperation, + entryPoint, + context: { + type: 'payg', + } as StackupPaymasterContext, + }); + } +} diff --git a/src/paymasters/index.ts b/src/paymasters/index.ts new file mode 100644 index 0000000..313fb8f --- /dev/null +++ b/src/paymasters/index.ts @@ -0,0 +1,5 @@ +export * from './Paymaster'; +export * from './PimlicoPaymaster'; +export * from './StackUpPaymaster'; +export * from './BasePaymaster'; +export * from './AlchemyPaymaster'; diff --git a/src/type-extensions.ts b/src/type-extensions.ts index 66f281b..20c16c5 100644 --- a/src/type-extensions.ts +++ b/src/type-extensions.ts @@ -1,12 +1,38 @@ -import "hardhat/types/config"; -import "hardhat/types/runtime"; +import 'hardhat/types/config'; +import 'hardhat/types/runtime'; -declare module "hardhat/types/config" { +declare module 'hardhat/types/config' { + /** + * The extended interface with the sponsored transactions field + * @property bundlerUrl The URL of the bundler + * @property paymasterUrl The URL of the paymaster + * @property simpleAccountFactoryAddress The address of the simple account factory + * @property policyId The optional policy ID for the paymaster + */ export interface HttpNetworkUserConfig { - sponsorUrl?: string; + accountAbstraction?: { + bundlerUrl: string; + paymasterUrl: string; + simpleAccountFactoryAddress?: `0x${string}`; + policyId?: string; + smartAccount?: `0x${string}`; + }; } + /** + * The extended interface with the sponsored transactions field + * @property bundlerUrl The URL of the bundler + * @property paymasterUrl The URL of the paymaster + * @property simpleAccountFactoryAddress The address of the simple account factory + * @property policyId The optional policy ID for the paymaster + */ export interface HttpNetworkConfig { - sponsorUrl?: string; + accountAbstraction?: { + bundlerUrl: string; + paymasterUrl: string; + simpleAccountFactoryAddress?: `0x${string}`; + policyId?: string; + smartAccount?: `0x${string}`; + }; } } diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..813f690 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,50 @@ +/** + * The partial user operation that is sent to be sponsored + * @property sender The sender of the transaction + * @property nonce The nonce of the transaction + * @property initCode The init code of the transaction + * @property callData The call data of the transaction + * @property maxFeePerGas The max fee per gas of the transaction + * @property maxPriorityFeePerGas The max priority fee per gas of the transaction + * @property signature The signature of the transaction + */ +export type PartialUserOperation = { + sender: `0x${string}`; + nonce: bigint; + initCode: `0x${string}`; + callData: `0x${string}`; + maxFeePerGas: bigint; + maxPriorityFeePerGas: bigint; + signature: `0x${string}`; +}; + +/** + * The type of paymaster class + * @property Pimlico for the Pimlico paymaster + * @property Base for the Base paymaster + * @property StackUp for the StackUp paymaster + */ +export enum PaymasterType { + Pimlico = 'pimlico', + Base = 'paymaster.base', + StackUp = 'stackup', + Alchemy = 'alchemy', +} + +export type EstimateGasTxn = { + from?: `0x${string}`; + to?: `0x${string}`; + data?: `0x${string}`; + value?: bigint | `0x${string}`; +}; + +/** + * The type for the getSmartAccountData function + * @property initCode The init code of the smart account + * @property senderAddress The sender address of the smart account + */ + +export type GetSmartAccountDataReturnType = { + initCode: `0x${string}`; + senderAddress: `0x${string}`; +}; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..910d7bf --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,206 @@ +import { GetUserOperationReceiptReturnType, UserOperation } from 'permissionless'; +import { randomBytes, toBeHex, toBigInt } from 'ethers'; +import { getSenderAddress } from './mock'; +import { concat, createPublicClient, encodeFunctionData } from 'viem'; +import fs from 'fs'; +import path from 'path'; +import { LATEST_FOLDER_NAME, MAIN_FOLDER_NAME } from './constants'; +import { GetSmartAccountDataReturnType } from './types'; + +/** + * Converts all BigInts in an object to strings because the nonce + * @param obj An object that may contain BigInts + * @returns The object with all BigInts converted to strings in hexadecimal form + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function convertBigIntsToString(obj: any) { + for (const key in obj) { + if (typeof obj[key] === 'bigint') { + // Convert 0n to '0x', and other BigInts to their string representation + // NOTE: base expects gas values to be non-zero, but nonce might be zero so we need to be sure to exclude it + obj[key] = obj[key] === 0n && key !== 'nonce' ? '0x1' : '0x' + obj[key].toString(16); + } + + // Recursively convert BigInts in nested objects + if (typeof obj[key] === 'object') { + obj[key] = convertBigIntsToString(obj[key]); + } + } + + return obj; +} + +/** + * Converts a bigint to a 32 byte padded hexadecimal string + * @param bigintValue The bigint value + * @returns The hexadecimal string + */ + +export function bigintToPaddedHex(bigintValue: bigint): `0x${string}` { + // Convert the bigint to a hexadecimal string + let hexString = bigintValue.toString(16); + + // Ensure the length is even to represent full bytes + if (hexString.length % 2 !== 0) { + hexString = '0' + hexString; + } + + // Calculate the padding length (64 hex characters for 32 bytes) + const paddingLength = 64 - hexString.length; + + // Pad the string with trailing zeros + hexString = hexString + '0'.repeat(paddingLength); + + return ('0x' + hexString) as `0x${string}`; +} + +/* + * Determines the init code and sender address for a smart account already deployed or to be deployed + * @param publicClient The public client to use to query the sender address + * @param simpleAccountFactoryAddress The factory address to use + * @param owner The owner of the smart account + * @param entryPoint The entry point to use + * @returns A promise that resolves to the init code and sender address + */ +export async function getSmartAccountData( + publicClient: ReturnType, + simpleAccountFactoryAddress: `0x${string}`, + owner: `0x${string}`, + entryPoint: `0x${string}`, +): Promise { + const initCode = concat([ + simpleAccountFactoryAddress, + encodeFunctionData({ + abi: [ + { + inputs: [ + { name: 'owner', type: 'address' }, + { name: 'salt', type: 'uint256' }, + ], + name: 'createAccount', + outputs: [{ name: 'ret', type: 'address' }], + stateMutability: 'nonpayable', + type: 'function', + }, + ], + args: [owner, BigInt(owner)], + }), + ]); + + const senderAddress = await getSenderAddress(publicClient, { + initCode: initCode, + entryPoint: entryPoint, + }); + + return { + initCode, + senderAddress, + }; +} + +/** + * Creates a folder if it doesn't exist + * @param folderName The name of the folder to create + */ +async function createFolderIfNotExists(folderName: string): Promise { + try { + // If successfull, folder should not be created + await fs.promises.access(folderName); + } catch { + await fs.promises.mkdir(folderName, { recursive: true }); + } +} + +/** + * Writes data to a JSON file + * @param fileName Complete path to the file + * @param data Data to write + */ +async function writeJSON(fileName: string, data: unknown): Promise { + // Create the file + await fs.promises.writeFile(fileName, JSON.stringify(data, null, 2), { + flag: 'w', + }); +} + +/** + * Writes the run data to a JSON file, along with a latest file + * @param runFolderName The name of the run folder + * @param fileName The name of the file (not the path, just the name) + * @param data Data to write + */ +async function writeRunToJSON(runFolderName: string, fileName: string, data: unknown): Promise { + await createFolderIfNotExists(runFolderName); + + // Create the file with timestamp + await writeJSON(fileName, data); + + // Create the file with latest + const latestFileName = `${runFolderName}/sponsored_latest.json`; + await writeJSON(latestFileName, data); +} + +/** + * Empties a folder + * @param folderName The name of the folder to empty (complete path) + */ +export async function emptyFolder(folderName: string): Promise { + // Read all the files in the directory + fs.readdir(folderName, async (_, files) => { + // If empty just return + if (!files) { + return; + } + + await Promise.all( + // For each file, unlink it (delete it) + files?.map((file) => + fs.unlink(path.join(folderName, file), (err) => { + if (err) throw err; + }), + ), + ); + }); +} + +/** + * Saves the tx data to a JSON file + * @param sponsoredUserOperation The sponsored user operation + * @param receipt The receipt returned by the bundler + * @param contractAddress If not null, the contract address to override the receipt's contractAddress field + * @param runTimestamp The timestamp of the run + */ +export async function txToJson( + sponsoredUserOperation: UserOperation, + receipt: GetUserOperationReceiptReturnType, + contractAddress: `0x${string}` | undefined, + runTimestamp: number, +): Promise { + const txData = convertBigIntsToString(Object.assign(receipt, sponsoredUserOperation)); + const timestamp = Math.floor(Date.now() / 1000); + + // Override the contractAddress field + if (contractAddress !== undefined) { + txData.receipt.contractAddress = contractAddress; + } + + // Create main folder if doesn't exist + await createFolderIfNotExists(MAIN_FOLDER_NAME); + + // Create run subfolder if doesn't exist (with timestamp) + const runFolderName = `${MAIN_FOLDER_NAME}/run-${runTimestamp}`; + const fileName = `${runFolderName}/sponsored_${timestamp}.json`; + await writeRunToJSON(runFolderName, fileName, txData); + + // Create latest subfolder if doesn't exist (latest) + const latestFileName = `${LATEST_FOLDER_NAME}/sponsored_${timestamp}.json`; + await writeRunToJSON(LATEST_FOLDER_NAME, latestFileName, txData); +} + +/** + * Gets a random 32 byte hexadecimal string + * @returns The hexadecimal string + */ +export function getRandomHex32ByteString(): `0x${string}` { + return toBeHex(toBigInt(randomBytes(32))) as `0x${string}`; +} diff --git a/test/fixture-projects/hardhat-project/hardhat.config.ts b/test/fixture-projects/hardhat-project/hardhat.config.ts deleted file mode 100644 index 4b74b80..0000000 --- a/test/fixture-projects/hardhat-project/hardhat.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -// We load the plugin here. -import { HardhatUserConfig } from "hardhat/types"; - -import "../../../src/index"; - -const config: HardhatUserConfig = { - solidity: "0.7.3", - defaultNetwork: "hardhat", - networks: { - localhost: { - sponsorUrl: "foo", - }, - }, -}; - -export default config; diff --git a/test/fixture-projects/integration/contracts/NonOwnableContract.sol b/test/fixture-projects/integration/contracts/NonOwnableContract.sol new file mode 100644 index 0000000..282b1ad --- /dev/null +++ b/test/fixture-projects/integration/contracts/NonOwnableContract.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.9; + +// Uncomment this line to use console.log +// import "hardhat/console.sol"; + +contract NonOwnableContract { + uint256 public returns100; + + constructor() { + returns100 = 100; + } +} diff --git a/test/fixture-projects/integration/contracts/OwnableContract.sol b/test/fixture-projects/integration/contracts/OwnableContract.sol new file mode 100644 index 0000000..1dab5fd --- /dev/null +++ b/test/fixture-projects/integration/contracts/OwnableContract.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.9; + +// Uncomment this line to use console.log +// import "hardhat/console.sol"; + +contract OwnableContract { + event OwnerChanged(address); + + address public owner; + + constructor() { + owner = msg.sender; + } + + function transferOwnership(address newOwner) external { + require(msg.sender == owner, 'Only owner can transfer ownership'); + owner = newOwner; + + emit OwnerChanged(newOwner); + } +} diff --git a/test/fixture-projects/integration/hardhat.config.ts b/test/fixture-projects/integration/hardhat.config.ts new file mode 100644 index 0000000..5a45b20 --- /dev/null +++ b/test/fixture-projects/integration/hardhat.config.ts @@ -0,0 +1,22 @@ +// We load the plugin here. +import { HardhatUserConfig } from 'hardhat/types'; +import { generatePrivateKey } from 'viem/accounts'; +import '@nomicfoundation/hardhat-ethers'; +import '../../../src/index'; + +const config: HardhatUserConfig = { + solidity: '0.8.19', + defaultNetwork: 'sepolia', + networks: { + sepolia: { + url: process.env.E2E_SEPOLIA_RPC as string, + accounts: [generatePrivateKey()], + accountAbstraction: { + bundlerUrl: process.env.E2E_BUNDLER_URL as string, + paymasterUrl: process.env.E2E_PAYMASTER_URL as string, + }, + }, + }, +}; + +export default config; diff --git a/test/fixture-projects/unit/hardhat.config.ts b/test/fixture-projects/unit/hardhat.config.ts new file mode 100644 index 0000000..6192d08 --- /dev/null +++ b/test/fixture-projects/unit/hardhat.config.ts @@ -0,0 +1,19 @@ +// We load the plugin here. +import { HardhatUserConfig } from 'hardhat/types'; + +import '../../../src/index'; + +const config: HardhatUserConfig = { + solidity: '0.7.3', + defaultNetwork: 'hardhat', + networks: { + localhost: { + accountAbstraction: { + bundlerUrl: 'http://localhost:3000', + paymasterUrl: 'http://localhost:3001', + }, + }, + }, +}; + +export default config; diff --git a/test/helpers.ts b/test/helpers.ts index 6efee77..17af392 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -1,21 +1,79 @@ -import { resetHardhatContext } from "hardhat/plugins-testing"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import path from "path"; +import { resetHardhatContext } from 'hardhat/plugins-testing'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import path from 'path'; +import { Hex } from 'viem'; +import { SponsorUserOperationReturnType } from 'permissionless/actions/pimlico'; +import { exec } from 'child_process'; +import { DUMMY_SIG } from '../src/constants'; +import { PartialUserOperation } from '../src/types'; -declare module "mocha" { +declare module 'mocha' { interface Context { hre: HardhatRuntimeEnvironment; } } +// Mock string for a transaction +export const mockTxn = + '0x02f89283aa36a7808459682f0085184478a9c48253109416f63c5036d3f48a239358656a8f123ece85789c80a4a0712d680000000000000000000000000000000000000000000000005fc1b97136320000c001a032427c034049c7d7743a198273d170b6a38ee476715903ac8bd79aa3d32ec8fba054a6a5763ee6561d7dc168639f858057679882d534f169de379e144a2d96e32a'; + +export const mockSponsorResult = { + paymasterAndData: + '0x02f89283aa36a7808459682f0085184478a9c48253109416f63c5036d3f48a239358656a8f123ece85789c80a4a0712d680000000000000000', + preVerificationGas: 100000n, + verificationGasLimit: 100000n, + callGasLimit: 100000n, +}; + +export const mockUserOperation: PartialUserOperation = { + sender: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', + nonce: 0n, + initCode: '0x', + callData: '0x', + maxFeePerGas: 1n, + maxPriorityFeePerGas: 1n, + // dummy signature, needs to be there so the SimpleAccount doesn't immediately revert because of invalid signature length + signature: DUMMY_SIG as Hex, +}; + +export const mockSponsorReturnType: SponsorUserOperationReturnType = { + paymasterAndData: '0x', + preVerificationGas: 1n, + verificationGasLimit: 1n, + callGasLimit: 1n, +}; + +export const mockEntryPoint = '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'; + export function useEnvironment(fixtureProjectName: string) { - beforeEach("Loading hardhat environment", function () { - process.chdir(path.join(__dirname, "fixture-projects", fixtureProjectName)); + before('Loading hardhat environment', async function () { + process.chdir(path.join(__dirname, 'fixture-projects', fixtureProjectName)); + + // If doing integration testing we need to compile the contracts + if (fixtureProjectName === 'integration') { + await compileHardhatProject(); + } - this.hre = require("hardhat"); + this.hre = require('hardhat'); }); - afterEach("Resetting hardhat", function () { + after('Resetting hardhat', function () { resetHardhatContext(); }); } + +async function compileHardhatProject(): Promise { + return new Promise((resolve) => { + exec('npx hardhat compile', (error, _, stderr) => { + if (error) { + throw new Error(`exec error: ${error}`); + } + + if (stderr) { + throw new Error(`stderr: ${stderr}`); + } + + resolve(); + }); + }); +} diff --git a/test/integration/deployment.test.ts b/test/integration/deployment.test.ts new file mode 100644 index 0000000..26011ca --- /dev/null +++ b/test/integration/deployment.test.ts @@ -0,0 +1,41 @@ +import 'dotenv/config'; +import { assert } from 'chai'; +import { useEnvironment } from '../helpers'; + +describe('Integration deployments', function () { + useEnvironment('integration'); + + it('Should deploy a non ownable contract', async function () { + const nonOwnableContract = await this.hre.ethers.deployContract('NonOwnableContract'); + + const deploymentAddress = await this.hre.network.provider.request({ + method: 'aa_getDeploymentFor', + params: [nonOwnableContract.target], + }); + + // Mock function in contract + const returns100 = await nonOwnableContract.returns100(); + + assert.equal(returns100, 100); + assert.isTrue(deploymentAddress !== undefined); + }); + + it('Should deploy an ownable contract', async function () { + const smartAccount = await this.hre.network.provider.request({ + method: 'aa_getSmartAccountAddress', + params: [], + }); + + const ownableContract = await this.hre.ethers.deployContract('OwnableContract'); + + const deploymentAddress = await this.hre.network.provider.request({ + method: 'aa_getDeploymentFor', + params: [ownableContract.target], + }); + + const owner = await ownableContract.owner(); + + assert.equal(owner, smartAccount); + assert.isTrue(deploymentAddress !== undefined); + }); +}); diff --git a/test/integration/transactions.test.ts b/test/integration/transactions.test.ts new file mode 100644 index 0000000..34fc1ec --- /dev/null +++ b/test/integration/transactions.test.ts @@ -0,0 +1,44 @@ +import 'dotenv/config'; +import { assert } from 'chai'; +import { Contract } from 'ethers'; +import { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers'; +import { useEnvironment } from '../helpers'; +import { TEST_TOKEN_ABI, TOKEN_ADDR, ENTRY_POINT } from '../test-constants'; + +describe('Integration transactions', function () { + useEnvironment('integration'); + + let signer: HardhatEthersSigner; + let signerAddress: string; + let testToken: Contract; + + before(async function () { + signer = await this.hre.ethers.provider.getSigner(); + signerAddress = await signer.getAddress(); + testToken = new this.hre.ethers.Contract(TOKEN_ADDR, TEST_TOKEN_ABI, signer); + }); + + it('Should send a transaction', async function () { + const smartAccount = await this.hre.network.provider.request({ + method: 'aa_getSmartAccountAddress', + params: [], + }); + + const amountToMint = this.hre.ethers.parseEther('6.9'); + const receipt = await testToken.mint(amountToMint); + const balanceOf = await testToken.balanceOf(smartAccount); + + assert.equal(receipt.to, ENTRY_POINT); + assert.equal(balanceOf.toString(), amountToMint.toString()); + }); + + it('Should transfer tokens from the smart account', async function () { + const amountToTransfer = this.hre.ethers.parseEther('1.0'); + + const receipt = await testToken.transfer(signerAddress, amountToTransfer); + const balanceOf = await testToken.balanceOf(signerAddress); + + assert.equal(receipt.to, ENTRY_POINT); + assert.equal(balanceOf.toString(), amountToTransfer.toString()); + }); +}); diff --git a/test/project.test.ts b/test/project.test.ts deleted file mode 100644 index 5df724b..0000000 --- a/test/project.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { assert } from "chai"; -import path from "path"; - -import { useEnvironment } from "./helpers"; - -describe("Integration tests examples", function () { - describe("HardhatConfig extension", function () { - useEnvironment("hardhat-project"); - - it("Should add the sponsoredUrl to the config", function () { - assert.equal(this.hre.config.networks.localhost.sponsorUrl, "foo"); - }); - }); -}); diff --git a/test/test-constants.ts b/test/test-constants.ts new file mode 100644 index 0000000..10119e7 --- /dev/null +++ b/test/test-constants.ts @@ -0,0 +1,189 @@ +export const TEST_TOKEN_ABI = [ + { + inputs: [ + { internalType: 'string', name: '_name', type: 'string' }, + { internalType: 'string', name: '_symbol', type: 'string' }, + { internalType: 'address', name: '_initialAccount', type: 'address' }, + { internalType: 'uint256', name: '_initialBalance', type: 'uint256' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, + { indexed: true, internalType: 'address', name: 'spender', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' }, + ], + name: 'Approval', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { indexed: false, internalType: 'uint256', name: 'value', type: 'uint256' }, + ], + name: 'Transfer', + type: 'event', + }, + { + inputs: [ + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'spender', type: 'address' }, + ], + name: 'allowance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'spender', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'approve', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_owner', type: 'address' }, + { internalType: 'address', name: '_spender', type: 'address' }, + { internalType: 'uint256', name: '_value', type: 'uint256' }, + ], + name: 'approveInternal', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'balanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_amount', type: 'uint256' }], + name: 'burn', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_account', type: 'address' }, + { internalType: 'uint256', name: '_amount', type: 'uint256' }, + ], + name: 'burn', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'spender', type: 'address' }, + { internalType: 'uint256', name: 'subtractedValue', type: 'uint256' }, + ], + name: 'decreaseAllowance', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { inputs: [], name: 'deposit', outputs: [], stateMutability: 'payable', type: 'function' }, + { + inputs: [ + { internalType: 'address', name: 'spender', type: 'address' }, + { internalType: 'uint256', name: 'addedValue', type: 'uint256' }, + ], + name: 'increaseAllowance', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_account', type: 'address' }, + { internalType: 'uint256', name: '_amount', type: 'uint256' }, + ], + name: 'mint', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_amount', type: 'uint256' }], + name: 'mint', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'recipient', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transfer', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'address', name: 'recipient', type: 'address' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '_from', type: 'address' }, + { internalType: 'address', name: '_to', type: 'address' }, + { internalType: 'uint256', name: '_value', type: 'uint256' }, + ], + name: 'transferInternal', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +]; + +export const TOKEN_ADDR = '0x8A59017aF01F5bC6c73CFB6DeD9e162a5fFaA634'; + +export const ENTRY_POINT = '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'; diff --git a/test/unit/gasless-provider.test.ts b/test/unit/gasless-provider.test.ts new file mode 100644 index 0000000..01d57cd --- /dev/null +++ b/test/unit/gasless-provider.test.ts @@ -0,0 +1,154 @@ +import { assert } from 'chai'; +import { generatePrivateKey } from 'viem/accounts'; +import { EIP1193Provider } from 'hardhat/types'; +import { RequestArguments } from 'hardhat/types'; +import { stub, SinonStub } from 'sinon'; +import { createPublicClient, http } from 'viem'; +import { GaslessProvider } from '../../src/gasless-provider'; +import { createPaymasterClient } from '../../src/paymaster'; +import { SIMPLE_ACCOUNT_FACTORY_ADDRESS as constantSimpleAccountFactoryAddress } from '../../src/constants'; +import { createPimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { PaymasterType } from '../../src/types'; +import { mockTxn, mockSponsorResult } from '../helpers'; +import * as MockPermissionless from '../../src/mock'; + +describe('GaslessProvider', function () { + let gaslessProvider: GaslessProvider; + + // Create fake clients for testing + + const publicClient = createPublicClient({ + transport: http('http://localhost:3000'), + }); + + const bundlerClient = createPimlicoBundlerClient({ + transport: http('http://localhost:3001'), + }); + + const paymasterClient = createPaymasterClient( + 'pimlico' as PaymasterType, + 'http://localhost:3002', + bundlerClient, + undefined, + ); + + // Random address for a mock smart account + const account = '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f'; + + // Mock provider + const provider = { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + request(args: RequestArguments): Promise { + return Promise.resolve(); + }, + } as EIP1193Provider; + + // All the sinon stubs we need + + let supportedEntryPointsStub: SinonStub; + let getAccontNonceStub: SinonStub; + let sendUserOpStub: SinonStub; + let sponsorUserOpStub: SinonStub; + let providerRequestStub: SinonStub; + let estimateFeesPerGasStub: SinonStub; + let signOpStub: SinonStub; + let waitForUserOperationReceiptStub: SinonStub; + let getSenderAddressStub: SinonStub; + let getChainIdStub: SinonStub; + + before(async function () { + supportedEntryPointsStub = stub(bundlerClient, 'supportedEntryPoints').resolves([ + '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', + ]); + getAccontNonceStub = stub(MockPermissionless, 'getAccountNonce').resolves(BigInt(0)); + + gaslessProvider = await GaslessProvider.create( + generatePrivateKey(), + provider, + bundlerClient, + paymasterClient, + publicClient, + constantSimpleAccountFactoryAddress, + account, + ); + + supportedEntryPointsStub.restore(); + getAccontNonceStub.restore(); + }); + + beforeEach(async function () { + supportedEntryPointsStub = stub(bundlerClient, 'supportedEntryPoints'); + getAccontNonceStub = stub(MockPermissionless, 'getAccountNonce'); + sendUserOpStub = stub(bundlerClient, 'sendUserOperation'); + sponsorUserOpStub = stub(paymasterClient, 'sponsorUserOperation'); + providerRequestStub = stub(provider, 'request'); + estimateFeesPerGasStub = stub(publicClient, 'estimateFeesPerGas'); + getChainIdStub = stub(publicClient, 'getChainId'); + signOpStub = stub(MockPermissionless, 'signUserOperationHashWithECDSA'); + waitForUserOperationReceiptStub = stub(bundlerClient, 'waitForUserOperationReceipt'); + getSenderAddressStub = stub(MockPermissionless, 'getSenderAddress'); + }); + + afterEach(async function () { + sendUserOpStub.restore(); + sponsorUserOpStub.restore(); + providerRequestStub.restore(); + estimateFeesPerGasStub.restore(); + getChainIdStub.restore(); + signOpStub.restore(); + waitForUserOperationReceiptStub.restore(); + getSenderAddressStub.restore(); + supportedEntryPointsStub.restore(); + getAccontNonceStub.restore(); + }); + + it('Should create a gasless provider', async function () { + assert.exists(gaslessProvider); + }); + + it('Should not sponsor if request isnt eth_sendRawTransaction', async () => { + await gaslessProvider.request({ method: 'eth_getBlock', params: ['latest'] }); + + assert.isFalse(sendUserOpStub.called); + assert.isTrue(providerRequestStub.calledWith({ method: 'eth_getBlock', params: ['latest'] })); + }); + + it('Should sponsor the user operation if request is eth_sendRawTransaction', async () => { + sendUserOpStub.resolves('0x'); + getChainIdStub.resolves(1); + sponsorUserOpStub.resolves(mockSponsorResult); + estimateFeesPerGasStub.resolves({ maxFeePerGas: 1, maxPriorityFeePerGas: 1 }); + signOpStub.resolves(mockTxn); + waitForUserOperationReceiptStub.resolves({ receipt: { transactionHash: '0x000' } }); + + await gaslessProvider.request({ method: 'eth_sendRawTransaction', params: [mockTxn] }); + + assert.isTrue(sendUserOpStub.calledOnce); + assert.isTrue(sponsorUserOpStub.calledOnce); + assert.isTrue(getChainIdStub.calledOnce); + assert.isTrue(estimateFeesPerGasStub.calledOnce); + assert.isTrue(signOpStub.calledOnce); + assert.isTrue(waitForUserOperationReceiptStub.calledOnce); + }); + + it('Creates a smart account if none is provided', async () => { + getSenderAddressStub.resolves(account); + supportedEntryPointsStub.resolves(['0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789']); + getAccontNonceStub.resolves(BigInt(0)); + + const newGaslessProvider = await GaslessProvider.create( + generatePrivateKey(), + provider, + bundlerClient, + paymasterClient, + publicClient, + constantSimpleAccountFactoryAddress, + undefined, + ); + + assert.exists(newGaslessProvider); + assert.isTrue(getSenderAddressStub.calledOnce); + assert.isTrue(supportedEntryPointsStub.calledOnce); + assert.isTrue(getAccontNonceStub.calledOnce); + }); +}); diff --git a/test/unit/interpreter.test.ts b/test/unit/interpreter.test.ts new file mode 100644 index 0000000..9d43022 --- /dev/null +++ b/test/unit/interpreter.test.ts @@ -0,0 +1,37 @@ +import { assert } from 'chai'; +import { interpretPaymasterType } from '../../src/interpreter'; +import { PaymasterType } from '../../src/types'; + +describe('Interpreter', function () { + it('Should revert if an unknown paymaster url is provided', function () { + assert.throws(() => { + interpretPaymasterType('http://localhost:3001'); + }, 'Unknown paymaster type for url http://localhost:3001'); + }); + + it('Shoulld revert if input is not a url', function () { + assert.throws(() => { + interpretPaymasterType('not a url'); + }, 'Invalid paymaster url'); + }); + + it('Should interpret the paymaster type as base', function () { + const result = interpretPaymasterType('http://localhost:3001/paymaster.base'); + assert.equal(result, PaymasterType.Base); + }); + + it('Should interpret the paymaster type as stackup', function () { + const result = interpretPaymasterType('http://localhost:3001/stackup'); + assert.equal(result, PaymasterType.StackUp); + }); + + it('Should interpret the paymaster type as alchemy', function () { + const result = interpretPaymasterType('http://localhost:3001/alchemy'); + assert.equal(result, PaymasterType.Alchemy); + }); + + it('Should interpret the paymaster type as pimlico', function () { + const result = interpretPaymasterType('http://localhost:3001/pimlico'); + assert.equal(result, PaymasterType.Pimlico); + }); +}); diff --git a/test/unit/paymaster.test.ts b/test/unit/paymaster.test.ts new file mode 100644 index 0000000..7021aca --- /dev/null +++ b/test/unit/paymaster.test.ts @@ -0,0 +1,65 @@ +import { assert } from 'chai'; +import { createPimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { http } from 'viem'; +import { JsonRpcProvider } from '@ethersproject/providers'; +import { createPaymasterClient } from '../../src/paymaster'; +import { PaymasterType } from '../../src/types'; +import * as Pm from '../../src/paymasters'; + +describe('Paymaster Construction', function () { + const bundlerClient = createPimlicoBundlerClient({ + transport: http('http://localhost:3001'), + }); + + const endpoint = 'http://localhost:3002'; + + it('Should create a pimlico paymaster client', function () { + const paymasterClient = createPaymasterClient( + 'pimlico' as PaymasterType, + endpoint, + bundlerClient, + undefined, + ) as Pm.PimlicoPaymaster; + + assert.isTrue(paymasterClient instanceof Pm.PimlicoPaymaster); + assert.isTrue(paymasterClient.endpoint instanceof JsonRpcProvider); + assert.equal(paymasterClient.endpoint.connection.url, endpoint); + assert.equal(paymasterClient.policyId, undefined); + }); + + it('Should create a stackup paymaster client', function () { + const paymasterClient = createPaymasterClient('stackup' as PaymasterType, endpoint, bundlerClient, undefined); + + assert.isTrue(paymasterClient instanceof Pm.StackUpPaymaster); + assert.isTrue(paymasterClient.endpoint instanceof JsonRpcProvider); + assert.equal(paymasterClient.endpoint.connection.url, endpoint); + }); + + it('Should create a base paymaster client', function () { + const paymasterClient = createPaymasterClient(PaymasterType.Base, endpoint, bundlerClient, undefined); + + assert.isTrue(paymasterClient instanceof Pm.BasePaymaster); + assert.isTrue(paymasterClient.endpoint instanceof JsonRpcProvider); + assert.equal(paymasterClient.endpoint.connection.url, endpoint); + }); + + it('Should create a alchemy paymaster client', function () { + const paymasterClient = createPaymasterClient( + 'alchemy' as PaymasterType, + endpoint, + bundlerClient, + 'test', + ) as Pm.AlchemyPaymaster; + + assert.isTrue(paymasterClient instanceof Pm.AlchemyPaymaster); + assert.isTrue(paymasterClient.endpoint instanceof JsonRpcProvider); + assert.equal(paymasterClient.endpoint.connection.url, endpoint); + assert.equal(paymasterClient.policyId, 'test'); + }); + + it('Should fail to create a alchemy paymaster client if there is no policy id', function () { + assert.throws(() => { + createPaymasterClient('alchemy' as PaymasterType, endpoint, bundlerClient, undefined); + }, 'Policy ID is required for Alchemy Paymaster'); + }); +}); diff --git a/test/unit/paymasters/AlchemyPaymaster.test.ts b/test/unit/paymasters/AlchemyPaymaster.test.ts new file mode 100644 index 0000000..e992f95 --- /dev/null +++ b/test/unit/paymasters/AlchemyPaymaster.test.ts @@ -0,0 +1,53 @@ +import { assert } from 'chai'; +import { http } from 'viem'; +import { stub, SinonStub } from 'sinon'; +import { createPimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { PaymasterType } from '../../../src/types'; +import { createPaymasterClient } from '../../../src/paymaster'; +import { mockUserOperation, mockEntryPoint, mockSponsorReturnType } from '../../helpers'; +import { AlchemyPaymaster } from '../../../src/paymasters/AlchemyPaymaster'; +import { convertBigIntsToString } from '../../../src/utils'; + +describe('Alchemy Paymaster', function () { + const bundlerClient = createPimlicoBundlerClient({ + transport: http('http://localhost:3001'), + }); + + const endpoint = 'http://localhost:3002'; + + const paymasterClientWithPolicyId = createPaymasterClient( + 'alchemy' as PaymasterType, + endpoint, + bundlerClient, + 'test', + ) as AlchemyPaymaster; + + let paymasterSponsorStubWithPolicyId: SinonStub; + + beforeEach(() => { + paymasterSponsorStubWithPolicyId = stub(paymasterClientWithPolicyId.endpoint, 'send'); + }); + + afterEach(() => { + paymasterSponsorStubWithPolicyId.restore(); + }); + + it('Should sponsor a valid user operation with a sponsor id', async function () { + paymasterSponsorStubWithPolicyId.resolves(mockSponsorReturnType); + + const result = await paymasterClientWithPolicyId.sponsorUserOperation(mockUserOperation, mockEntryPoint); + + assert.deepEqual(result, mockSponsorReturnType); + assert.isTrue(paymasterSponsorStubWithPolicyId.calledOnce); + assert.isTrue( + paymasterSponsorStubWithPolicyId.calledWith('alchemy_requestGasAndPaymasterAndData', [ + { + policyId: 'test', + entryPoint: mockEntryPoint, + dummySignature: mockUserOperation.signature, + userOperation: convertBigIntsToString(mockUserOperation), + }, + ]), + ); + }); +}); diff --git a/test/unit/paymasters/BasePaymaster.test.ts b/test/unit/paymasters/BasePaymaster.test.ts new file mode 100644 index 0000000..be8bfcc --- /dev/null +++ b/test/unit/paymasters/BasePaymaster.test.ts @@ -0,0 +1,76 @@ +import { assert } from 'chai'; +import { http } from 'viem'; +import { stub, SinonStub } from 'sinon'; +import { createPimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { PaymasterType } from '../../../src/types'; +import { BasePaymaster } from '../../../src/paymasters/BasePaymaster'; +import { createPaymasterClient } from '../../../src/paymaster'; +import { mockUserOperation, mockEntryPoint } from '../../helpers'; +import { convertBigIntsToString } from '../../../src/utils'; + +describe('Base Paymaster', function () { + const bundlerClient = createPimlicoBundlerClient({ + transport: http('http://localhost:3001'), + }); + + const endpoint = 'http://localhost:3002'; + + const paymasterClient = createPaymasterClient( + PaymasterType.Base, + endpoint, + bundlerClient, + undefined, + ) as BasePaymaster; + + let paymasterSponsorStub: SinonStub; + let estimateUserOperationGasStub: SinonStub; + let chainIdStub: SinonStub; + + const mockGasConfig = { + preVerificationGas: 10000n, + verificationGasLimit: 10000n, + callGasLimit: 10000n, + }; + + beforeEach(() => { + paymasterSponsorStub = stub(paymasterClient.endpoint, 'send'); + estimateUserOperationGasStub = stub(bundlerClient, 'estimateUserOperationGas'); + chainIdStub = stub(bundlerClient, 'chainId'); + }); + + afterEach(() => { + paymasterSponsorStub.restore(); + estimateUserOperationGasStub.restore(); + chainIdStub.restore(); + }); + + it('Should sponsor a valid user operation', async function () { + const paymasterAndData = '0x123'; + + paymasterSponsorStub.resolves(paymasterAndData); + estimateUserOperationGasStub.resolves(mockGasConfig); + chainIdStub.resolves(1); + + const userOp = convertBigIntsToString(mockUserOperation); + + const result = await paymasterClient.sponsorUserOperation(mockUserOperation, mockEntryPoint); + + const expectedResult = { + ...mockGasConfig, + paymasterAndData: paymasterAndData, + }; + + assert.deepEqual(result, expectedResult); + assert.isTrue(paymasterSponsorStub.calledTwice); + assert.isTrue( + paymasterSponsorStub.calledWith('eth_paymasterAndDataForEstimateGas', [userOp, mockEntryPoint, '0x1']), + ); + assert.isTrue( + paymasterSponsorStub.calledWith('eth_paymasterAndDataForUserOperation', [ + Object.assign(userOp, convertBigIntsToString(mockGasConfig)), + mockEntryPoint, + '0x1', + ]), + ); + }); +}); diff --git a/test/unit/paymasters/PimlicoPaymaster.test.ts b/test/unit/paymasters/PimlicoPaymaster.test.ts new file mode 100644 index 0000000..95e51a1 --- /dev/null +++ b/test/unit/paymasters/PimlicoPaymaster.test.ts @@ -0,0 +1,75 @@ +import { assert } from 'chai'; +import { http } from 'viem'; +import { stub, SinonStub } from 'sinon'; +import { createPimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { PaymasterType } from '../../../src/types'; +import { PimlicoPaymaster } from '../../../src/paymasters/PimlicoPaymaster'; +import { createPaymasterClient } from '../../../src/paymaster'; +import { mockUserOperation, mockEntryPoint, mockSponsorReturnType } from '../../helpers'; + +describe('Pimlico Paymaster', function () { + const bundlerClient = createPimlicoBundlerClient({ + transport: http('http://localhost:3001'), + }); + + const endpoint = 'http://localhost:3002'; + + const paymasterClient = createPaymasterClient( + 'pimlico' as PaymasterType, + endpoint, + bundlerClient, + undefined, + ) as PimlicoPaymaster; + + const paymasterClientWithPolicyId = createPaymasterClient( + 'pimlico' as PaymasterType, + endpoint, + bundlerClient, + 'test', + ) as PimlicoPaymaster; + + let paymasterSponsorStub: SinonStub; + let paymasterSponsorStubWithPolicyId: SinonStub; + + beforeEach(() => { + paymasterSponsorStub = stub(paymasterClient.paymasterClient, 'sponsorUserOperation'); + paymasterSponsorStubWithPolicyId = stub(paymasterClientWithPolicyId.paymasterClient, 'sponsorUserOperation'); + }); + + afterEach(() => { + paymasterSponsorStub.restore(); + paymasterSponsorStubWithPolicyId.restore(); + }); + + it('Should sponsor a valid user operation with no sponsor id', async function () { + paymasterSponsorStub.resolves(mockSponsorReturnType); + + const result = await paymasterClient.sponsorUserOperation(mockUserOperation, mockEntryPoint); + + assert.equal(result, mockSponsorReturnType); + assert.isTrue(paymasterSponsorStub.calledOnce); + assert.isTrue( + paymasterSponsorStub.calledWith({ + userOperation: mockUserOperation, + entryPoint: mockEntryPoint, + sponsorshipPolicyId: undefined, + }), + ); + }); + + it('Should sponsor a valid user operation with a sponsor id', async function () { + paymasterSponsorStubWithPolicyId.resolves(mockSponsorReturnType); + + const result = await paymasterClientWithPolicyId.sponsorUserOperation(mockUserOperation, mockEntryPoint); + + assert.equal(result, mockSponsorReturnType); + assert.isTrue(paymasterSponsorStubWithPolicyId.calledOnce); + assert.isTrue( + paymasterSponsorStubWithPolicyId.calledWith({ + userOperation: mockUserOperation, + entryPoint: mockEntryPoint, + sponsorshipPolicyId: 'test', + }), + ); + }); +}); diff --git a/test/unit/paymasters/StackUpPaymaster.test.ts b/test/unit/paymasters/StackUpPaymaster.test.ts new file mode 100644 index 0000000..b16e483 --- /dev/null +++ b/test/unit/paymasters/StackUpPaymaster.test.ts @@ -0,0 +1,51 @@ +import { assert } from 'chai'; +import { http } from 'viem'; +import { stub, SinonStub } from 'sinon'; +import { createPimlicoBundlerClient } from 'permissionless/clients/pimlico'; +import { PaymasterType } from '../../../src/types'; +import { StackUpPaymaster } from '../../../src/paymasters/StackUpPaymaster'; +import { createPaymasterClient } from '../../../src/paymaster'; +import { mockUserOperation, mockEntryPoint, mockSponsorReturnType } from '../../helpers'; + +describe('StackUp Paymaster', function () { + const bundlerClient = createPimlicoBundlerClient({ + transport: http('http://localhost:3001'), + }); + + const endpoint = 'http://localhost:3002'; + + const paymasterClient = createPaymasterClient( + 'stackup' as PaymasterType, + endpoint, + bundlerClient, + undefined, + ) as StackUpPaymaster; + + let paymasterSponsorStub: SinonStub; + + beforeEach(() => { + paymasterSponsorStub = stub(paymasterClient.paymasterClient, 'sponsorUserOperation'); + }); + + afterEach(() => { + paymasterSponsorStub.restore(); + }); + + it('Should sponsor a valid user operation', async function () { + paymasterSponsorStub.resolves(mockSponsorReturnType); + + const result = await paymasterClient.sponsorUserOperation(mockUserOperation, mockEntryPoint); + + assert.equal(result, mockSponsorReturnType); + assert.isTrue(paymasterSponsorStub.calledOnce); + assert.isTrue( + paymasterSponsorStub.calledWith({ + userOperation: mockUserOperation, + entryPoint: mockEntryPoint, + context: { + type: 'payg', + }, + }), + ); + }); +}); diff --git a/test/unit/project.test.ts b/test/unit/project.test.ts new file mode 100644 index 0000000..bfc5632 --- /dev/null +++ b/test/unit/project.test.ts @@ -0,0 +1,17 @@ +import { assert } from 'chai'; + +import { useEnvironment } from '../helpers'; + +describe('Integration tests examples', function () { + describe('HardhatConfig extension', function () { + useEnvironment('unit'); + + it('Should add the bundlerUrl to the config', function () { + assert.equal(this.hre.config.networks.localhost.accountAbstraction?.bundlerUrl, 'http://localhost:3000'); + }); + + it('Should add the paymasterUrl to the config', function () { + assert.equal(this.hre.config.networks.localhost.accountAbstraction?.paymasterUrl, 'http://localhost:3001'); + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 2d2fa2d..b6f3b84 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,11 +8,13 @@ "outDir": "./dist", "strict": true, "rootDirs": ["./src", "./test"], - "esModuleInterop": true + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true }, "exclude": ["dist", "node_modules"], "include": [ "./test", "./src" - ] +, "test/fixture-projects/integration/artifacts" ] } diff --git a/yarn.lock b/yarn.lock index cb1527e..4adcd44 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,16 @@ # yarn lockfile v1 +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + "@chainsafe/as-sha256@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" @@ -45,6 +55,33 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" + integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.4.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" @@ -392,6 +429,25 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" integrity sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA== +"@humanwhocodes/config-array@^0.11.8": + version "0.11.13" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" + integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== + dependencies: + "@humanwhocodes/object-schema" "^2.0.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" + integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== + "@jridgewell/resolve-uri@^3.0.3": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" @@ -421,16 +477,54 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@noble/curves@1.2.0", "@noble/curves@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== + "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + "@nomicfoundation/ethereumjs-block@5.0.2": version "5.0.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz#13a7968f5964f1697da941281b7f7943b0465d04" @@ -565,6 +659,14 @@ mcl-wasm "^0.7.1" rustbn.js "~0.2.0" +"@nomicfoundation/hardhat-ethers@3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.5.tgz#0422c2123dec7c42e7fb2be8e1691f1d9708db56" + integrity sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw== + dependencies: + debug "^4.1.1" + lodash.isequal "^4.5.0" + "@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz#4c858096b1c17fe58a474fe81b46815f93645c15" @@ -631,11 +733,28 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" +"@pkgr/utils@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" + integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw== + dependencies: + cross-spawn "^7.0.3" + fast-glob "^3.3.0" + is-glob "^4.0.3" + open "^9.1.0" + picocolors "^1.0.0" + tslib "^2.6.0" + "@scure/base@~1.1.0": version "1.1.3" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== +"@scure/base@~1.1.2": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" + integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== + "@scure/bip32@1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" @@ -645,6 +764,15 @@ "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" +"@scure/bip32@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" + integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== + dependencies: + "@noble/curves" "~1.2.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.2" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -653,6 +781,14 @@ "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -721,6 +857,48 @@ "@sentry/types" "5.30.0" tslib "^1.9.3" +"@sinonjs/commons@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" + integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== + dependencies: + type-detect "4.0.8" + +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@sinonjs/fake-timers@^11.2.2": + version "11.2.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699" + integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@sinonjs/samsam@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" + integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew== + dependencies: + "@sinonjs/commons" "^2.0.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" + integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -767,6 +945,11 @@ dependencies: "@types/ms" "*" +"@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/lru-cache@^5.1.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" @@ -789,6 +972,11 @@ dependencies: undici-types "~5.26.4" +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + "@types/pbkdf2@^3.0.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" @@ -811,6 +999,112 @@ dependencies: "@types/node" "*" +"@types/semver@^7.3.12": + version "7.5.6" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" + integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== + +"@types/sinon@10.0.15": + version "10.0.15" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.15.tgz#513fded9c3cf85e589bbfefbf02b2a0541186b48" + integrity sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.5" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz#5fd3592ff10c1e9695d377020c033116cc2889f2" + integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ== + +"@typescript-eslint/eslint-plugin@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz#a350faef1baa1e961698240f922d8de1761a9e2b" + integrity sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.6" + "@typescript-eslint/type-utils" "5.59.6" + "@typescript-eslint/utils" "5.59.6" + debug "^4.3.4" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.6.tgz#bd36f71f5a529f828e20b627078d3ed6738dbb40" + integrity sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA== + dependencies: + "@typescript-eslint/scope-manager" "5.59.6" + "@typescript-eslint/types" "5.59.6" + "@typescript-eslint/typescript-estree" "5.59.6" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz#d43a3687aa4433868527cfe797eb267c6be35f19" + integrity sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ== + dependencies: + "@typescript-eslint/types" "5.59.6" + "@typescript-eslint/visitor-keys" "5.59.6" + +"@typescript-eslint/type-utils@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz#37c51d2ae36127d8b81f32a0a4d2efae19277c48" + integrity sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ== + dependencies: + "@typescript-eslint/typescript-estree" "5.59.6" + "@typescript-eslint/utils" "5.59.6" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.6.tgz#5a6557a772af044afe890d77c6a07e8c23c2460b" + integrity sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA== + +"@typescript-eslint/typescript-estree@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz#2fb80522687bd3825504925ea7e1b8de7bb6251b" + integrity sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA== + dependencies: + "@typescript-eslint/types" "5.59.6" + "@typescript-eslint/visitor-keys" "5.59.6" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.6.tgz#82960fe23788113fc3b1f9d4663d6773b7907839" + integrity sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.59.6" + "@typescript-eslint/types" "5.59.6" + "@typescript-eslint/typescript-estree" "5.59.6" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.59.6": + version "5.59.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz#673fccabf28943847d0c8e9e8d008e3ada7be6bb" + integrity sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q== + dependencies: + "@typescript-eslint/types" "5.59.6" + eslint-visitor-keys "^3.3.0" + +abitype@0.9.8: + version "0.9.8" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.8.tgz#1f120b6b717459deafd213dfbf3a3dd1bf10ae8c" + integrity sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ== + abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" @@ -824,12 +1118,17 @@ abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: module-error "^1.0.1" queue-microtask "^1.2.3" +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + acorn-walk@^8.1.1: version "8.3.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.0.tgz#2097665af50fd0cf7a2dfccd2b9368964e66540f" integrity sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA== -acorn@^8.4.1: +acorn@^8.4.1, acorn@^8.9.0: version "8.11.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== @@ -844,6 +1143,11 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -859,6 +1163,16 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -881,6 +1195,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -895,6 +1214,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -913,22 +1237,32 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -axios@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2" - integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A== +axios@1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" + integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.4" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -954,6 +1288,11 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +big-integer@^1.6.44: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + bigint-crypto-utils@^3.0.23: version "3.3.0" resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz#72ad00ae91062cf07f2b1def9594006c279c1d77" @@ -979,6 +1318,13 @@ bn.js@^5.2.0, bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -994,7 +1340,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1067,11 +1413,23 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== + dependencies: + run-applescript "^5.0.0" + bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + camelcase@^6.0.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" @@ -1100,6 +1458,11 @@ chai@4.3.10: pathval "^1.1.1" type-detect "^4.0.8" +chalk@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" + integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== + chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1109,7 +1472,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1168,6 +1531,29 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + +cli-truncate@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" + integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== + dependencies: + slice-ansi "^5.0.0" + string-width "^5.0.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -1201,6 +1587,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.19: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1218,6 +1609,11 @@ commander@3.0.2: resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1261,7 +1657,16 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1280,6 +1685,34 @@ deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== + dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" + +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -1300,6 +1733,35 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dotenv@16.4.1: + version "16.4.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.1.tgz#1d9931f1d3e5d2959350d1250efab299561f7f11" + integrity sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -1318,6 +1780,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + enquirer@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" @@ -1336,7 +1803,7 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -1346,6 +1813,135 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +eslint-config-prettier@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz#eb25485946dd0c66cd216a46232dc05451518d1f" + integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw== + +eslint-plugin-prettier@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz#a3b399f04378f79f066379f544e42d6b73f11515" + integrity sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.8.5" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@8.34.0: + version "8.34.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.34.0.tgz#fe0ab0ef478104c1f9ebc5537e303d25a8fb22d6" + integrity sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg== + dependencies: + "@eslint/eslintrc" "^1.4.1" + "@humanwhocodes/config-array" "^0.11.8" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.4.0" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-sdsl "^4.1.4" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.4.0: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -1398,7 +1994,20 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethers@5.7.2, ethers@^5.7.1: +ethers@6.9.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.9.0.tgz#a4534bdcdfde306aee94ef32f3d5c70d7e33fcb9" + integrity sha512-pmfNyQzc2mseLe91FnT2vmNaTt8dDzhxZ/xItAV7uGsF4dI4ek2ufMu3rAkgQETL/TIs0GS5A+U05g9QyWnv3Q== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + +ethers@^5.7.1: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -1450,6 +2059,81 @@ evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +execa@^7.0.0, execa@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.2.9, fast-glob@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" + integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1457,7 +2141,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-up@5.0.0: +find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -1472,16 +2156,35 @@ find-up@^2.1.0: dependencies: locate-path "^2.0.0" +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -follow-redirects@^1.12.1, follow-redirects@^1.15.0: +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + +follow-redirects@^1.12.1: version "1.15.3" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== +follow-redirects@^1.15.4: + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -1546,13 +2249,25 @@ get-func-name@^2.0.1, get-func-name@^2.0.2: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -glob-parent@~5.1.2: +get-stream@^6.0.0, get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob@7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -1577,11 +2292,35 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + hardhat@2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.0.tgz#1e08658863550ba351788ea128e544ff80584a31" @@ -1696,6 +2435,21 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + +husky@8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" + integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -1708,11 +2462,29 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" + integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== + immutable@^4.0.0-rc.12: version "4.3.4" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -1750,6 +2522,16 @@ is-buffer@^2.0.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1760,7 +2542,12 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.1, is-glob@~4.0.1: +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -1772,21 +2559,60 @@ is-hex-prefixed@1.0.0: resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isows@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" + integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== + js-sdsl@^4.1.4: version "4.4.2" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" @@ -1797,13 +2623,28 @@ js-sha3@0.8.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-yaml@4.1.0: +js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -1818,6 +2659,11 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +just-extend@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947" + integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw== + keccak@^3.0.0, keccak@^3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" @@ -1827,6 +2673,13 @@ keccak@^3.0.0, keccak@^3.0.2: node-gyp-build "^4.2.0" readable-stream "^3.6.0" +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -1855,6 +2708,52 @@ level@^8.0.0: browser-level "^1.0.1" classic-level "^1.2.0" +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lilconfig@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lint-staged@13.2.2: + version "13.2.2" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.2.tgz#5e711d3139c234f73402177be2f8dd312e6508ca" + integrity sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA== + dependencies: + chalk "5.2.0" + cli-truncate "^3.1.0" + commander "^10.0.0" + debug "^4.3.4" + execa "^7.0.0" + lilconfig "2.1.0" + listr2 "^5.0.7" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-inspect "^1.12.3" + pidtree "^0.6.0" + string-argv "^0.3.1" + yaml "^2.2.2" + +listr2@^5.0.7: + version "5.0.8" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" + integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.19" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.8.0" + through "^2.3.8" + wrap-ansi "^7.0.0" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -1870,6 +2769,21 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash@^4.17.11: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -1883,6 +2797,16 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -1897,6 +2821,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lru_map@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" @@ -1935,6 +2866,24 @@ memorystream@^0.3.1: resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -1947,6 +2896,16 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -1964,7 +2923,7 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -2030,6 +2989,27 @@ napi-macros@^2.2.2: resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.2.2.tgz#817fef20c3e0e40a963fbf7b37d1600bd0201044" integrity sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g== +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +nise@^5.1.4: + version "5.1.7" + resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.7.tgz#03ca96539efb306612eb60a8c5d6beeb208e27e5" + integrity sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^11.2.2" + "@sinonjs/text-encoding" "^0.7.2" + just-extend "^6.2.0" + path-to-regexp "^6.2.1" + node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -2045,6 +3025,25 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + +object-inspect@^1.12.3: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + obliterator@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" @@ -2057,6 +3056,42 @@ once@^1.3.0: dependencies: wrappy "1" +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + +optionator@^0.9.1: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -2102,6 +3137,13 @@ p-try@^1.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -2117,11 +3159,31 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + path-parse@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-to-regexp@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" + integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" @@ -2138,11 +3200,38 @@ pbkdf2@^3.0.17: safe-buffer "^5.0.1" sha.js "^2.4.8" -picomatch@^2.0.4, picomatch@^2.2.1: +permissionless@0.0.16: + version "0.0.16" + resolved "https://registry.yarnpkg.com/permissionless/-/permissionless-0.0.16.tgz#d1f40b7134bd9d83a384b05dcbb5237651dab473" + integrity sha512-tuGMf1l6X+WD8X2/WZAaF0Rqj7ysWX++eiUNgG/A+Qe1vP+e4Oik57jVUOW7Yo/VXQ9zU3luEC2GmwrFeo4b8w== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pidtree@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.0.tgz#c6d16474a5f764ea1a4a373c593b779697744d5e" @@ -2153,6 +3242,11 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + queue-microtask@^1.2.2, queue-microtask@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -2191,6 +3285,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -2201,6 +3300,11 @@ require-from-string@^2.0.0: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve@1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" @@ -2208,6 +3312,24 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + rimraf@^2.2.8: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -2215,6 +3337,13 @@ rimraf@^2.2.8: dependencies: glob "^7.1.3" +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -2230,6 +3359,13 @@ rlp@^2.2.3: dependencies: bn.js "^5.2.0" +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== + dependencies: + execa "^5.0.0" + run-parallel-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" @@ -2237,11 +3373,25 @@ run-parallel-limit@^1.1.0: dependencies: queue-microtask "^1.2.2" +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + rustbn.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== +rxjs@^7.8.0: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -2281,6 +3431,13 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.3.7: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -2306,6 +3463,66 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sinon@15.2.0: + version "15.2.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-15.2.0.tgz#5e44d4bc5a9b5d993871137fd3560bebfac27565" + integrity sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^10.3.0" + "@sinonjs/samsam" "^8.0.0" + diff "^5.1.0" + nise "^5.1.4" + supports-color "^7.2.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -2346,6 +3563,11 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +string-argv@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -2355,6 +3577,15 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -2369,6 +3600,23 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" @@ -2376,7 +3624,7 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" -strip-json-comments@3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -2395,13 +3643,36 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.1.0, supports-color@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" +synckit@^0.8.5: + version "0.8.6" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.6.tgz#b69b7fbce3917c2673cbdc0d87fb324db4a5b409" + integrity sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA== + dependencies: + "@pkgr/utils" "^2.4.2" + tslib "^2.6.2" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== + tmp@0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -2440,16 +3711,33 @@ ts-node@10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tslib@^1.9.3: +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.1.0, tslib@^2.6.0, tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tsort@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" @@ -2460,11 +3748,23 @@ tweetnacl@^1.0.3: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== -type-detect@^4.0.0, type-detect@^4.0.8: +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -2475,10 +3775,10 @@ type-fest@^0.7.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== -typescript@5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +typescript@5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== undici-types@~5.26.4: version "5.26.5" @@ -2502,6 +3802,18 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -2517,11 +3829,41 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +viem@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.20.3.tgz#8b8360daee622295f5385949c02c86d943d14e0f" + integrity sha512-7CrmeCb2KYkeCgUmUyb1hsf+IX/PLwi+Np+Vm4YUTPeG82y3HRSgGHSaCOp3d0YtR2kXD3nv9y5kE7LBFE+wWw== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "0.9.8" + isows "1.0.3" + ws "8.13.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -2541,6 +3883,16 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + ws@^7.4.6: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" @@ -2556,6 +3908,16 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^2.2.2: + version "2.3.4" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" + integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"